Flag Example

The Jekejeke Prolog programming language provides higher order programming. The given example shows how to define a loop construct. The goal of this example is to return a star banner. In a first step we will only display the star banner on the console which is simpler than returning a star banner. On purpose we will first build a loop construct so that we can use FORTRAN like loops to solve our problem. The displayed star banner should have size 8x8 and look as follows:

xoxoxoxo
oxoxoxox
...
xoxoxoxo
oxoxoxox

To enumerate the x- and y-axis we can define a predicate between/3 which will enumerate integers in a given range. The detailed Prolog text of this predicate can be found in the appendix together with the rest of this example. We then use the between/3 predicate to define a loop construct as follows:

% for1(+Integer, +Integer, +Closure)
for1(Lo, Hi, Closure) :-
 between(Lo, Hi, Value),
  call(Closure, Value),
  fail.
for1(_,_,_).

The above loop construct uses the higher order programming predicate call/n to invoke the given closure. Since 2012 this predicate is part of the ISO Prolog standard via the corrigendum 2. The closure is supposed to be the loop body and the identification of the loop variable. The loop construct will then repeatedly invoke the loop body with integer values ranging from the given lower bound to the given upper bound, both inclusively. A solution to the flag display problem is quickly coded by using the system predicates write/1 and nl/0.

% flag
flag :-
  for1(1,8,X\
     for1(1,8,Y\
        (0 =:= (X+Y) mod 2 -> write(x); write(o))), nl)).

The above solution makes use of another higher order programming predicate besides call/n. We also find the abstraction operator (\)/2 to create a closure. This use of the abstraction operator (\)/2 is Jekejeke Prolog specific and not part of some ISO Prolog standard. One characteristic of the above solution is the peculiar use of backtracking. The image of the flag is generated via backtracking and will thus not persist.

Let’s now turn to the question how we could return a star banner instead of only displaying it? We want a solution where ‘x’ and ‘o’ are assigned to some variable and then returned. But to make this happen we are not allowed to backtrack over the assignment step, since we would then loose the binding. We must therefore chain the closure invocations instead of backtracking over them. Here is our take for an alternative for loop:

% for2(+Integer, +Integer, +Closure)
for2(Lo, Hi, _) :- Lo > Hi, !.
for2(Lo, Hi, Closure) :-
   call(Closure, Lo),
   Lo2 is Lo+1,
   for2(Lo2, Hi, Closure).

The above predicate does not anymore make use of a predicate between/3. Instead it does do the bounds check by itself. There is now no more failure when we are outside of the bounds, instead there is some success and a noop concerning the closure. When we are inside the bounds the closure is invoked and in the same time a recursion into the new loop predicate happens again. Any bindings that are done by the invocation of the closure will not be lost during the next iteration.

We can now go on and for example populate an array in each invocation of the closure via instantiation and will not lose this instantiation. For arrays we do not provide some special constructs but rely on the ISO Prolog standard defined predicates. We simply view arrays as compounds with irrelevant functors. An array with not instantiated elements can be created via the system predicate functor/3:

?- functor(X,'',8).
X = ''(_A,_B,_C,_D,_E,_F,_G,_H)

An element of an array can be accessed via the system predicate arg/3. Please note that the first argument of a compound and thus an array has the index value 1:

?- functor(X,'',8), arg(3,X,x), arg(4,X,o).
X = ''(_A,_B,x,o,_E,_F,_G,_H)

The full code of the flag solution that will return a flag as a 2-dimensional array can be found in the appendix. Running the code yields the following result:

?- flag(X).
X = ''(''(x,o,x,o,x,o,x,o),
''(o,x,o,x,o,x,o,x),
''(x,o,x,o,x,o,x,o),
''(o,x,o,x,o,x,o,x),
''(x,o,x,o,x,o,x,o),
''(o,x,o,x,o,x,o,x),
''(x,o,x,o,x,o,x,o),
''(o,x,o,x,o,x,o,x))

Kommentare