Modeling with foreach and list comprehension

The loop constructs considerably enhance the modeling power of B-Prolog as a CLP language. The following gives a program for the N-queens problem:
    queens(N):-
        length(Qs,N),
        Qs :: 1..N,
        foreach(I in 1..N-1, J in I+1..N,
                (Qs[I] #\= Qs[J],
                 abs(Qs[I]-Qs[J]) #\= J-I)),
        labeling([ff],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:
    foreach(I in 1..N-1, J in I+1..N,[Qi,Qj],
            (nth(Qs,I,Qi),
             nth(Qs,J,Qj),
             Qi #\= Qj,
             abs(Qi-Qj) #\= J-I)),
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.
bool_queens(N):-
    new_array(Qs,[N,N]),
    Vars @= [Qs[I,J] : I in 1..N, J in 1..N],
    Vars :: 0..1,
    foreach(I in 1..N,     % one queen in each row
            sum([Qs[I,J] : J in 1..N]) #= 1),
    foreach(J in 1..N,     % one queen in each column
            sum([Qs[I,J] : I in 1..N]) #= 1),
    foreach(K in 1-N..N-1, % at most one queen in each diag
            sum([Qs[I,J] : I in 1..N, J in 1..N, I-J=:=K]) #=< 1),
    foreach(K in 2..2*N,   
            sum([Qs[I,J] : I in 1..N, J in 1..N, I+J=:=K]) #=< 1),
    labeling(Vars),
    foreach(I in 1..N,[Row],
            (Row @= [Qs[I,J] : J in 1..N], writeln(Row))).



Neng-Fa Zhou 2013-01-25