Loops With Foreach and List Comprehension
Prolog relies on recursion to describe loops. The lack of powerful loop constructs has arguably made Prolog less acceptable to beginners and less productive to experienced programmers because it is often tedious to define small auxiliary recursive predicates for loops. The emergence of constraint programming constructs such as CLP(FD) has further revealed this weakness of Prolog as a modeling language. B-Prolog provides a built-in, called foreach
, for iterating over collections and the list comprehension notation for constructing lists.
The foreach
built-in has a very simple syntax and semantics. For example,
outputs four tuples (a,1)
, (a,2)
, (b,1)
, and (b,2)
. Syntactically, foreach
is a variable-length call whose last argument specifies a goal to be executed for each combination of values in a sequence of collections. A foreach
call may also give a list of variables that are local to each iteration and a list of accumulators that can be used to accumulate values from each iteration. With accumulators, we can use foreach
to describe recurrences for computing aggregates. Recurrences have to be read procedurally and thus do not fit well with Prolog. For this reason, we adopt the list comprehension notation from functional languages. A list comprehension is a list whose first element has the functor ':
'. A list of this form is interpreted as a list comprehension in calls to @=/2
and arithmetic constraints. For example, the query
binds X
to the list . A list comprehension is treated as a
foreach
call with an accumulator in the implementation.
Calls to foreach
and list comprehensions are translated into tail-recursive predicates. Therefore, there is no or little penalty of using these constructs compared with using recursion.
The loop constructs considerably enhance the modeling power of CLP(FD). The following gives a program for the N-queens problem in B-Prolog:
queens(N):- length(Qs,N), Qs :: 1..N, foreach(I in 1..N-1, J in I+1..N, (Qs #\= Qs, abs(Qs-Qs) #\= J-I)), labeling(,Qs), writeln(Qs).The array notation on lists helps shorten the description. Without it, the foreach
loop in the program would have to be written as follows:
where Qi
and Qj
are declared local to each iteration. The following gives a program for the N-queens problem, which uses a Boolean variable for each square on the board.
Read more about this topic: B-Prolog
Famous quotes containing the words loops and/or list:
“An accurate charting of the American womans progress through history might look more like a corkscrew tilted slightly to one side, its loops inching closer to the line of freedom with the passage of timebut like a mathematical curve approaching infinity, never touching its goal. . . . Each time, the spiral turns her back just short of the finish line.”
—Susan Faludi (20th century)
“The advice of their elders to young men is very apt to be as unreal as a list of the hundred best books.”
—Oliver Wendell Holmes, Jr. (18411935)