I recently started playing with Prolog. When I came to the predicate '
is/2', I suddenly realized that Prolog has embraced the explicit-evaluation paradigm for such a long time!
To show you an example. Below are two definitions are length:
length1([], 0).
length1([_ | Xs], 1 + N) :- length1(Xs, N).
length2([], 0).
length2([_ | Xs], N) :- length2(Xs, M), N is 1 + M.
Querying `length1([1, 2], N)' gives N = (1 + (1 + 0)), while querying `length2([1, 2], N)` gives N = 2. In Prolog, computation is *more* symbolic. Inputs and output of a predicate are all (syntactic) terms. So in `length1', the recursive call will return a term ((1 + 0) in the example) bound to the variable N, then the original call will construct a new term by substituting (1 + 0) for N in the pattern (1 + N) and gives (1 + (1 + 0)) as result. In `length2', however, after the recursive call, we ask Prolog to evaluate the arithmetic expression by means of the `is' predicate (this is quite similar to an explicit call of `eval'), the result of the evaluation will be bound to the variable N, which is returned by the original call.
Thanks to this "program is data" (note that I do not use "program as data" since in Prolog you do not need any `quote' operator to turn program into data), Prolog offers very powerful meta-programming features. Moreover, there is no variable capturing, no triviality of equational theory. It is a new land. I highly recommend you guys explore it.
Best regards,
Yi