Expression Pattern Language (eXPL)

Introduction to eXPL

Expression Pattern Language (eXPL) is designed combining elements from two programming paradigms: Logic and Imperative. The result is a language that fits well with how the mind works, which is to use patterns for finding and shaping soutions to problems. The "expression pattern" in eXPL is the template, which uses expressions to define relationships and perform transformations. The counterpart to the template is the axiom, which organises data in the same way as a template and can be unified with a template to test if they are logically equivalent. The template expressions are allowed to not only perfom logical expressions, but also perform calculations such scaling or factoring or whatever the solution requires.

A Simple eXPL Program

Here is example of a simple eXPL program with a single "high_cities" query:

axiom city_altitude()
{"bilene", 1718}
{"addis ababa", 8000}
{"denver", 5280}
{"flagstaff", 6970}
{jacksonville", 8}
{"leadville", 10200}
{"madrid", 1305}
{"richmond",19}
{"spokane", 1909}
{"wichita", 1305};

template high_city(city ? altitude > 5000, altitude);

query high_cities (city_altitude : high_city);

This query is executed by the HighCities application of tutorial1.

The Tutorial Examples are available online as described in Getting Started.

The console output when the query is run is:

high_city(name = addis ababa, altitude = 8000)
high_city(name = denver, altitude = 5280)
high_city(name = flagstaff, altitude = 6970)
high_city(name = leadville, altitude = 10200)

The high city template

template high_city(city ? altitude > 5000, altitude)

creates a solution consisting of a collection of "high_city" axioms with terms "city" and "altitude". The first term has a logical ? operator which "short circuits" unification for cities below the specified altitude. Short circuiting here means reversing back to the point the last city axiom was read and then moving forward again after reading the next axiom. So we see that an expression not only defines a logical relationship of axiom term to template term but also exercises control over execution.

Terms

A term is an element of a unification structure , has a name and holds a value. Axiom terms are passive participants in unification and always contain a literal value such as a string, number or boolean true or false. Terms with an empty name are called anonymous terms. When axiom terms are anonymous, such as in the above example, then they are paired to template terms by position, otherwise they are paired by name. Obviously the latter is preferred as pairing by position is brittle.

If you run the second example of Tutorial1 - NamedHighCities, you will see it generates the same solution as the first example. However, in second example, the city axioms are declared with term names ie.

axiom city_altitude(altitude, city) ...
.

You will see the term order is therefore reversed to that in the original high_cities.xpl. Template terms can be placed in any order when they are paired to axiom terms by name.

Template terms

A template term can be singular or a composite depending on whether it evaluates an expression. In the composite case, the expression consists of a graph where each node participates in unification and is given the opportunity to evaulate a value. In the High Cities example, the "city" template term evaluates it's expression with the following nodes:

  • Short-circuit-on-false evaluator (? operator) with name "city"
  • Variable with name "city"
  • Greater-than evaluator (> operator)
  • Variable with name "altitude"

In the case of more complex expressions, the order of evaluation is in accordance with the rules of Java syntax.

Avoiding Anonymous Terms

A query solution is not permitted to contain anonymous terms and therefore it follows template terms are not allowed to be anonymous. Say, for example, you wanted to find the altitude of the city Madrid. You may be tempted to try:

template madrid("madrid", altitude)

or

template madrid(city == "madrid", altitude)

Neither will work. A literal like "madrid" is anonymous and an expression with == operator creates an anonymous boolean value. One answer is given in the Madrid application of tutorial1.

template madrid(city { "madrid" }, altitude)

Here a variable with identity "city" is controlled by a set {} operator to only unify with "madrid". You may wish to experiment by adding more names to the set eg.

template madrid(city { "madrid", "leadville" }, altitude)

or try a more verbose comparison exression:

template madrid(city ? city == "madrid", altitude)

The EuropeanMegaCities application also demonstrates selecting cities in Europe from a list of cities.

Names and Namespaces

Getting started with a new programming language is hard because so many things depend on each other. Rules that govern what names are valid and how they can be used is a fundamental issue to be addressed early. Hence Names and Namespaces is the next topic.