Some "classic" Prolog textbooks still use the confusing and error-prone failure-driven loop syntax where a fail
construct is used to force backtracking to apply a goal to every value of a generator. For example, to print all numbers up to a given limit:
fdl(X) :- between(1,X,Y), print(Y), fail.
fdl(_).
The vast majority of Modern Prologs no longer require this syntax, instead providing a higher order predicate to address this.
nicer(X) :- forall(between(1,X,Y), print(Y)).
Not only is this much easier to read, but if a goal that could fail was used in place of print, its failure would be correctly detected and passed on - whereas failures of the goals in a failure-driven loop are confused with the forced failure that drives the loop.
Visual Prolog has a custom syntactic sugar for these loops, combined with function predicates (see below):
vploop(X) :- foreach Y = std::fromTo(1,X) do
console::write(X)
end foreach.
Although this looks like an imperative for loop, it still follows Prolog rules: in particular, each iteration of the foreach is its own scope.