Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Lambdas in Prolog

33 views
Skip to first unread message

Ulrich Neumerkel

unread,
Jun 23, 2009, 6:23:07 AM6/23/09
to
Recently, I developed a small library lambda.pl to provide lambda expressions
in Prolog. The library runs in SWI and YAP - and with minimal adaptation
in SICStus.

A sample to illustrate the various issues of scoping:

?- Xs = [A,B], maplist(Y+\X^Z^(X+Y #= Z), Xs, Zs).
Xs = [A, B],
Zs = [_G1698, _G1701],
A+Y#=_G1698,
B+Y#=_G1701.

See http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord

Comments welcome!

Joachim Schimpf

unread,
Jun 23, 2009, 8:13:55 PM6/23/09
to
Ulrich Neumerkel wrote:
> Recently, I developed a small library lambda.pl to provide lambda expressions
> in Prolog. The library runs in SWI and YAP - and with minimal adaptation
> in SICStus.
>
> A sample to illustrate the various issues of scoping:
>
> ?- Xs = [A,B], maplist(Y+\X^Z^(X+Y #= Z), Xs, Zs).

Loop version for readability comparison:

?- Xs = [A,B], (foreach(X,Xs),foreach(Z,Zs),param(Y) do X+Y #= Z).


-- Joachim

afa

unread,
Jun 23, 2009, 11:50:28 PM6/23/09
to
On 6月24日, 午前9:13, Joachim Schimpf <jschi...@users.sourceforge.net>
wrote:
Here is another version:

Xs = [A,B], (foreach(X in Xs, [Z], ac1(Zs,[]), (Zs^0=[Z|Zs^1],X+Y#=Z))

I would prefer the recursive version to any iterative version.

Cheers,
Neng-Fa

Ulrich Neumerkel

unread,
Jun 24, 2009, 12:17:29 AM6/24/09
to

What about a list of lists?

I am still not sure how to write this with for-loops compactly.

?- Xs = [[A],[B,C]], maplist(maplist(Y+\X^Z^(X+Y #= Z)), Xs, Zs).
Xs = [[A], [B, C]],
Zs = [[_G1350], [_G1356, _G1359]],
A+Y#=_G1350,
B+Y#=_G1356,
C+Y#=_G1359.


But in any case: lambdas and for loops are related but still quite
different.

One other use of lambdas is to get a different and more readable
quantification in setof/3:

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#setof

Mats Carlsson

unread,
Jul 6, 2009, 6:08:37 AM7/6/09
to
On Jun 24, 2:13 am, Joachim Schimpf <jschi...@users.sourceforge.net>
wrote:

The loop version will be available in SICStus 4.1. --Mats

Jan Burse

unread,
Oct 31, 2009, 2:55:47 PM10/31/09
to

Lambda comes from functional programming. Why not use an
approach that comes from logic? Namely allowing assumption
programming (not invented by, have seen it already in some
places but cannot recall right now) and using it for
passing relations.

Lets first explain what I understand by assumption programming.
I understand by it allowing implication (:-) in goal literals
with the following semantics (BTW there is an interesting theoretical
unterpinning from Minimal Logic):

P, A |- B
-------------
P |- (A :- B)

So when a goal (A :- B) is reached the interpreter will add A
as a new assumption and then try to proof B. Here is a example
how this could be used for map:

map([],[])
map([X|Xs],[Y|Ys]) :- f(X,Y), map(Xs,Ys).

?- ((f(X,Y) :- Y is X+1) :- map([2,5],Z))
Z = [3,6]

Only implementation problem is maybe here that the assumption A needs
proper quantifier handly. Which means on one hand to allow forall
quantification of those assumption variables which should be local
to the assumption and regenerated for each invokation of the assumption.

And on the other hand those variables which are not quantified
should behave like goal variables, and also continue to communicate
with the goal. Here is an example of the behaviour:


?- (p(z,X) :- p(Y,Y))
X=z
Y=z

?- ((forall X p(z,X)) :- p(Y,Y))
Y=z

etc..

Anybody tried this already? Are there some usability problems with it,
such that passing a lambda expression around is more transparent than
dynamically changing the program by an assumption, although the change
goes away when we exit the goal.

Bye


Jan Burse

unread,
Oct 31, 2009, 3:22:34 PM10/31/09
to

And here is yet another idea to do it, and also currious what people
think about it and why somebody would prefer it over lambdas or not.
I simply would use object oriented programming:

map([],[],O)
map([X|Xs],[Y|Ys],O) :- O:f(X,Y), map(Xs,Ys,O).

myobj:f(X,Y) :- Y is X+1.

?- map([2,5],X,myobj)
X = [3,6]

We could also introduce anonymous classes/objects to act as closures.
Something like that:

?- map([2,5],Z,{f(X,Y) :- Y is X+1}).
Z = [3,6]

Now the idea would be that the anonymous classes/objects are created
at compile time or when the {} is first encountered. Problems of
assumption programming appear again.

But new problems pop up also. Suppose we generate objects on the fly,
we would trash memory. So how is the anonymous object automatically
reclaimed in the light of cut, tail recursion etc..?

Is the conclusion this that we would need to compile time a class
which has kind of a constructor where we can pass variables that
should reappear in the closure?

So I am just reading:

Conclusion
There is no need for higher order extensions to bloat ISO
Prolog's syntax. The traditional call/N and this library
are sufficient. The real challenge is an effective error
detection and an efficient compilation scheme. But all
this can be done within 13211-1 and 13211-2.
http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord

Ok, I will bookmark the page and dig deeper when I have time. This
makes me really curious.

Bye

Alan Smaill

unread,
Nov 2, 2009, 6:30:50 AM11/2/09
to
Jan Burse <janb...@fastmail.fm> writes:

> Ulrich Neumerkel wrote:
> > Recently, I developed a small library lambda.pl to provide lambda

> > Y in Prolog. The library runs in SWI and YAP - and with minimal

Both the idea having implicational goals, dealt with by
local assumptions, and lambda abstraction are well dealt with
in Lambda-Prolog:

http://www.lix.polytechnique.fr/~dale/lProlog/

> Bye
>
>

--
Alan Smaill

Paulo Moura

unread,
Nov 2, 2009, 12:30:34 PM11/2/09
to
On Oct 31, 7:22 pm, Jan Burse <janbu...@fastmail.fm> wrote:
> ...

> And here is yet another idea to do it, and also currious what people
> think about it and why somebody would prefer it over lambdas or not.
> I simply would use object oriented programming:
>
>      map([],[],O)
>      map([X|Xs],[Y|Ys],O) :- O:f(X,Y), map(Xs,Ys,O).
>
>      myobj:f(X,Y) :- Y is X+1.
>
>      ?- map([2,5],X,myobj)
>      X = [3,6]

Note that both in Logtalk and, I believe, in most (if not all) Prolgo
module systems, you can already pass a predicate such as map/3 an
explicitly qualified closure.

Cheers,

Paulo

Jan Burse

unread,
Nov 2, 2009, 1:25:45 PM11/2/09
to
Alan Smaill schrieb:

> Both the idea having implicational goals, dealt with by
> local assumptions, and lambda abstraction are well dealt with
> in Lambda-Prolog:
>
> http://www.lix.polytechnique.fr/~dale/lProlog/
>
>> Bye

Can I use easily ISO prolog to implement lambda prolog?
Are there lambda prologs without types?
Are there lambda prologs that can reach classical logic inference?
(a stupid approach would be to allow double negation elimination
together with minimal logic, but maybe another approach is necessary)
When they can reach classical logic inference, do they just simulate
a prover or is it directly natively running?

Bye

Alan Smaill

unread,
Nov 2, 2009, 2:08:20 PM11/2/09
to
Jan Burse <janb...@fastmail.fm> writes:

> Alan Smaill schrieb:
>
> > Both the idea having implicational goals, dealt with by
> > local assumptions, and lambda abstraction are well dealt with
> > in Lambda-Prolog:
> > http://www.lix.polytechnique.fr/~dale/lProlog/
> >
> >> Bye
>
> Can I use easily ISO prolog to implement lambda prolog?

I believe The first implementation was in Prolog ...

> Are there lambda prologs without types?

Types are needed for higher-order unification, which is
also a feature of the language.

> Are there lambda prologs that can reach classical logic inference?
> (a stupid approach would be to allow double negation elimination
> together with minimal logic, but maybe another approach is necessary)

That depends what you're after, and what count as reaching it.
The underlying logic is a part of higher-order intuitionistic logic
(as the underlying logic of (pure) Prolog is intuitionistic first-order).

> When they can reach classical logic inference, do they just simulate
> a prover or is it directly natively running?

See above.

There is a fair-sized litereture out there, if you are interested,
including on the different implementations, which I know less about.

> Bye

--
Alan Smaill

Peter Robinson

unread,
Nov 2, 2009, 4:33:58 PM11/2/09
to
Another option is Qu-Prolog - it provides support for arbitrary
quantifiers and substitutions so it does support lambda terms.

The examples directory of QuProlog contains a couple of lambda term
evaluators and one that does type inference of lambda terms.
E.g. the beta rule can be written as the fact
(lambda x A)(B) => [B/x]A.
There is also a small natural deduction prover.

Ergo is a quite sophisticated sequent calculus theorem prover written
in Qu-Prolog.

Find both at http://www.itee.uq.edu.au/~pjr/

Peter

Ulrich Neumerkel

unread,
Nov 3, 2009, 7:42:15 AM11/3/09
to
Peter Robinson <p...@itee.uq.edu.au> writes:
>Another option is Qu-Prolog - it provides support for arbitrary
>quantifiers and substitutions so it does support lambda terms.
>
>The examples directory of QuProlog contains a couple of lambda term
>evaluators and one that does type inference of lambda terms.
>E.g. the beta rule can be written as the fact
>(lambda x A)(B) => [B/x]A.
>There is also a small natural deduction prover.
>
>Ergo is a quite sophisticated sequent calculus theorem prover written
>in Qu-Prolog.

One advantage of library(lambda) is that it fits seamlessly with
traditional higher order predicates based on call/N. So there
is no need to change everything.

Ulrich Neumerkel

unread,
Nov 3, 2009, 7:44:50 AM11/3/09
to
Jan Burse <janb...@fastmail.fm> writes:
>Ulrich Neumerkel wrote:
>> Recently, I developed a small library lambda.pl to provide lambda expressions
>> in Prolog.
...

>> See http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord
>>
>> Comments welcome!
>
>And here is yet another idea to do it, and also currious what people
>think about it and why somebody would prefer it over lambdas or not.
>I simply would use object oriented programming:
>
> map([],[],O)
> map([X|Xs],[Y|Ys],O) :- O:f(X,Y), map(Xs,Ys,O).
>
> myobj:f(X,Y) :- Y is X+1.
>
> ?- map([2,5],X,myobj)
> X = [3,6]
>
>We could also introduce anonymous classes/objects to act as closures.
>Something like that:
>
> ?- map([2,5],Z,{f(X,Y) :- Y is X+1}).
> Z = [3,6]

The scoping of variables is most probably difficult to handle

Also your scheme does not fit together with the
common higher order predicates. The traditional maplist/2,3 (~ 1983)
has its arguments in a different order - not without reason:

?- Xss = [[[1,2]],[[3]]], maplist(maplist(maplist(\X^Y^(Y is X+1))), Xss, Yss).

...
>Is the conclusion this that we would need to compile ...

A clean sematics is what is needed first. Most compiler based approaches
are not only difficult to implement but also difficult to understand.

Jan Burse

unread,
Nov 7, 2009, 1:45:14 PM11/7/09
to
Ulrich Neumerkel schrieb:

> One advantage of library(lambda) is that it fits seamlessly with
> traditional higher order predicates based on call/N. So there
> is no need to change everything.

I am just reading a Ciao doc (2000 Tutorial),
which says:

?- call(p,1,2,3,4,5,6). --> p(1,2,3,4,5,6)
?- call(p(1),2,3,4,5,6). --> p(2,1,3,4,5,6)
?- call(p(1,2),3,4,5,6). --> p(3,1,2,4,5,6)
?- call(p(1,2,3),4,5,6). --> p(4,1,2,3,5,6)
?- call(p(1,2,3,4),5,6). --> p(5,1,2,3,4,6)
?- call(p(1,2,3,4,5),6). --> p(6,1,2,3,4,5)
?- call(p(1,2,3,4,5,6)). --> p(1,2,3,4,5,6)

This is not to be expected, or am I wrong?
(I guess we have the rule: call(P(X1,...,Xm),
Y1,...,Yn) :- P(X1,...,Xm, Y1,...,Yn))

Bye

Ulrich Neumerkel

unread,
Nov 9, 2009, 7:23:52 PM11/9/09
to
Jan Burse <janb...@fastmail.fm> writes:
>Ulrich Neumerkel schrieb:
>> One advantage of library(lambda) is that it fits seamlessly with
>> traditional higher order predicates based on call/N. So there
>> is no need to change everything.
>
>I am just reading a Ciao doc (2000 Tutorial),
>which says:
>
> ?- call(p,1,2,3,4,5,6). --> p(1,2,3,4,5,6)
> ?- call(p(1),2,3,4,5,6). --> p(2,1,3,4,5,6)
> ?- call(p(1,2),3,4,5,6). --> p(3,1,2,4,5,6)
> ?- call(p(1,2,3),4,5,6). --> p(4,1,2,3,5,6)
> ?- call(p(1,2,3,4),5,6). --> p(5,1,2,3,4,6)
> ?- call(p(1,2,3,4,5),6). --> p(6,1,2,3,4,5)
> ?- call(p(1,2,3,4,5,6)). --> p(1,2,3,4,5,6)

This does not correspond to what call/N is in other systems.
It might be useful in certain situations, but it definitely
should get a different name.

I cannot see how this convention would allow arbitrary nesting
in maplist/N. I.e.

?- Xsss = [[[1,2,3],[4]],[[5]]], maplist(maplist(maplist(\X^Y^(Y is X+3))), Xsss, Ysss).
Xsss = [[[1, 2, 3], [4]], [[5]]],
Ysss = [[[4, 5, 6], [7]], [[8]]].

Historically, the first public mentioning of call/N was
Richard O'Keefe's posting 1987-09-26 with Subject: "The call/N family".
Quintus (as a library) and NU were probably the first to adopt it.
It was not part of DECsystem 10 Prolog which had apply/2 only.

>(I guess we have the rule:
> call(P(X1,...,Xm), Y1,...,Yn) :- P(X1,...,Xm, Y1,...,Yn))

Exactly! And this is a good occasion to make this more explicit in
the current ISO drafts.

Paulo Moura

unread,
Nov 28, 2009, 4:20:37 PM11/28/09
to
Hi,

I have implemented Ulrich's syntax for lambda expressions in the
current development version of Logtalk (r5204 or later). It should
work with all supported back-end Prolog compilers.

Sample queries using GNU Prolog as the back-end compiler:

pmmbp:~ pmoura$ gplgt
...
Logtalk 2.38.0
Copyright (c) 1998-2009 Paulo Moura
...
GNU Prolog 1.3.2
By Daniel Diaz
Copyright (C) 1999-2009 Daniel Diaz
| ?- {metapredicates(loader)}.
...
yes
| ?- meta::map(\X^(X>3),[4,5,9]).

yes
| ?- meta::map(t+\X^Y^(X=A-B,Y=B-A), [1-a,2-b,3-c], Zs).

Zs = [a-1,b-2,c-3]

yes
| ?- meta::map(\X^Y^(X=A-B,Y=B-A), [1-a,2-b,3-c], Zs).

Zs = [a-1,b-2,c-3]

(1 ms) yes
| ?- meta::map(\X^(B-A)^(X=A-B), [1-a,2-b,3-c], Zs).

Zs = [a-1,b-2,c-3]

yes
| ?- meta::map(\ (A-B)^(B-A)^true, [1-a,2-b,3-c], Zs).

Zs = [a-1,b-2,c-3]

yes
| ?- Xss= [[1,2],[3]], meta::map(meta::map(\X^Y^Z^(X+Y#=Z)), Xss, Yss,
Zss).

Xss = [[1,2],[3]]

Yss = [[_#3(0..268435454),_#54(0..268435453)],[_#105(0..268435452)]]
Zss = [[_#22(1..268435455),_#73(2..268435455)],[_#124(3..268435455)]]

(1 ms) yes
| ?- Xss= [[1,2],[3]], meta::map(meta::map(Y+\X^Z^(X+Y#=Z)), Xss,
Zss).

Xss = [[1,2],[3]]

Y = _#3(0..268435452)
Zss = [[_#22(1..268435453),_#66(2..268435454)],[_#110(3..268435455)]]

(1 ms) yes


Feedback welcome, specially when using other back-end Prolog
compilers. Cheers,

Paulo

Ulrich Neumerkel

unread,
Nov 28, 2009, 6:39:34 PM11/28/09
to
Paulo Moura <pjlm...@gmail.com> writes:
>Hi,
>
>I have implemented Ulrich's syntax for lambda expressions in the
>current development version of Logtalk (r5204 or later). It should
>work with all supported back-end Prolog compilers.

Could you tell me what

?- \ _^write(metipse).

does? The reason I am asking is that this seems to be a very
frequent error people do in the beginning (Peter Szeredi alerted
me to this very early on).

It is for this reason that the implementation contains the
no_hat_call/1 - which posed some challenge to be written in such
a manner that it is compatible with the minimally different
module systems of SWI and YAP - and at the same time conformant
to ISO 13211-2 Modules.

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

Paulo Moura

unread,
Nov 28, 2009, 7:23:14 PM11/28/09
to
On Nov 28, 11:39 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

> Paulo Moura <pjlmo...@gmail.com> writes:
> >Hi,
>
> >I have implemented Ulrich's syntax for lambda expressions in the
> >current development version of Logtalk (r5204 or later). It should
> >work with all supported back-end Prolog compilers.
>
> Could you tell me what
>
> ?- \ _^write(metipse).
>
> does?  The reason I am asking is that this seems to be a very
> frequent error people do in the beginning (Peter Szeredi alerted
> me to this very early on).

In the current Logtalk development version (r5205):

?- logtalk << \ _^write(metipse).
metipse
true.

In the above call, "logtalk" is a built-in, empty object and the <</2
is the Logtalk control construct for context switching calls, which
allows calling a goal within the context of an object.

> It is for this reason that the implementation contains the
> no_hat_call/1 - which posed some challenge to be written in such
> a manner that it is compatible with the minimally different
> module systems of SWI and YAP - and at the same time conformant
> to ISO 13211-2 Modules.
>
> http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

I will eventually implement the equivalent of the no_hat_call/1. So
far, the current implementation of lambda expressions in Logtalk is
just an experiment in order to gather feedback and gain insights on a
native implementation (i.e. an implementation that doesn't use a
library object). A problem that we share in both implementations is,
of course, performance. But that will only be a concern when the
implementation stabilizes.

Cheers,

Paulo

Paulo Moura

unread,
Nov 28, 2009, 11:07:01 PM11/28/09
to
On Nov 29, 12:23 am, Paulo Moura <pjlmo...@gmail.com> wrote:
> ...

> I will eventually implement the equivalent of the no_hat_call/1. So
> far, the current implementation of lambda expressions in Logtalk is
> just an experiment in order to gather feedback and gain insights on a
> native implementation (i.e. an implementation that doesn't use a
> library object). A problem that we share in both implementations is,
> of course, performance. But that will only be a concern when the
> implementation stabilizes.

Error checking is implemented in r5208:

| ?- logtalk << \ _^write(hello).
uncaught exception: error(representation_error(lambda_parameters),
\_278^write(hello),logtalk)

| ?- meta::map(\ X^3,[4,5,9]).
uncaught exception: error(type_error(callable,3),\_279^3,meta)

Cheers,

Paulo

Ulrich Neumerkel

unread,
Nov 29, 2009, 10:10:00 AM11/29/09
to
On Nov 29, 12:23=A0am, Paulo Moura <pjlmo...@gmail.com> wrote:
>Error checking is implemented in r5208:
>
>| ?- logtalk << \ _^write(hello).
>uncaught exception: error(representation_error(lambda_parameters),
>\_278^write(hello),logtalk)

Very fine! Having an error here is the only way to prevent so many
misunderstandings of beginners - the runtime overheads are neglectable
- see my next-to-be-written response.

Concerning the representation error - which might appear as somewhat
unusual - here is my motivation:

If one peeks to functional languages, the most "natural" error in this
situation would be a type error. However, type errors have a very
clear connotation in Prolog: They mean semantically failure. In fact,
some Prolog systems even offer to fail optionally, for a particular
goal for type and domain errors. I am still not convinced that this
situation corresponds to such a failure. Also, another error class
covers semantical failure - see below.

I chose a representation error because it is semantically neutral:
There are cases where representation errors would "hide" a case which
actually should fail and others where it should succeed. For example
functor(F,f,10000) may issue a representation error provided max_arity
is smaller than 10000. But in a system with a sufficiently large or
unbounded max_arity it would succeed.

I am less and less happy with this representation error, as - in a
sense - I read a promise in ISO 13211-1 7.12.2 Error Classification f:

| f) There shall be a Representation Error when an
| implementation defined limit has been breached. It has
| the form representation_error(Flag) where
| Flag \el {
| character,
| character_code,
| in_character_code,
| max_arity,
| max_integer,
| min_integer
| }.

The promise is that since the limit that has been breached is "only"
implementation defined, there might be implementations that have a
higher limit or none at all. But in the situation of not passing
sufficiently many arguments there is nothing that depends on an
implementation at all.

Another alternative might be the existence error. Note that
semantically an existence error of a procedure also means failure. So
maybe existence_error(lambda_parameter, Culprit) might be a good idea
with Culprit showing the remaining parameters.

Ulrich Neumerkel

unread,
Nov 29, 2009, 11:25:45 AM11/29/09
to
Paulo Moura <pjlm...@gmail.com> writes:
> ... A problem that we share in both implementations is,

>of course, performance. But that will only be a concern when the
>implementation stabilizes.

There are the following options to implement library(lambda) which can
be handled differently on a case-by-case basis.

a) no optimization - library(lambda) as is

b) additionally to a) for problematic cases warnings (only messages
during compilation) or errors (refusing compilation)

c) optimize while maintaining *complete* operational equivalence

But please do not consider the path of optimizing and changing the
meaning of lambdas. Also please never optimize incorrectly with a
warning. Let's leave that box closed!

(Exactly for this reason there is still some hesitation for
integrating library(lambda) into SWI.)

Maybe

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord

is not clear enough?


Much to my chagrin such cases of ambiguity already exist in related
situations. Consider SICStus 3 and its clpfd imlementation:

| ?- E = 1+1, X #= E.
E = 1+1,
X = 1+1 ?
yes
| ?- E = 1+1, call(X #= E).
E = 1+1,
X = 2 ?


Why is this such a problem? Aren't all resonable uses of constraints
effectively statically resolvable? Unfortunately not.

Higher order programming is very useful exactly for clpfd programs -
and even already without lambdas! You can express relations over
several lists compactly. Take the library(lists) of SICStus 4 which
contains the traditional maplist/2

?- E = 1+1, maplist(#=(E),[X]).

will resolve dynamically, but an optimization would do this
statically. So we would get exactly the same difference as in the
cases with and without call/1.

In SWI and YAP, library(clpfd) behaves identical for all such cases.
Thanks to Markus Triska's meticulous diligence.

Paulo Moura

unread,
Nov 30, 2009, 8:54:31 AM11/30/09
to
On Nov 29, 3:10 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich

Neumerkel) wrote:
> On Nov 29, 12:23=A0am, Paulo Moura <pjlmo...@gmail.com> wrote:
>
> >Error checking is implemented in r5208:
>
> >| ?- logtalk << \ _^write(hello).
> >uncaught exception: error(representation_error(lambda_parameters),
> >\_278^write(hello),logtalk)
>
> Very fine! Having an error here is the only way to prevent so many
> misunderstandings of beginners - the runtime overheads are neglectable
> - see my next-to-be-written response.
>
> Concerning the representation error - which might appear as somewhat
> unusual - here is my motivation:
> ...

> Another alternative might be the existence error.  Note that
> semantically an existence error of a procedure also means failure.  So
> maybe existence_error(lambda_parameter, Culprit) might be a good idea
> with Culprit showing the remaining parameters.

Maybe we should make a distinction, using different exception terms,
between missing lambda parameters and too many lambda parameters?

Cheers,

Paulo

Paulo Moura

unread,
Nov 30, 2009, 9:01:19 AM11/30/09
to
On Nov 29, 4:25 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

> Paulo Moura <pjlmo...@gmail.com> writes:
> >             ... A problem that we share in both implementations is,
> >of course, performance. But that will only be a concern when the
> >implementation stabilizes.
>
> There are the following options to implement library(lambda) which can
> be handled differently on a case-by-case basis.
>
> a) no optimization - library(lambda) as is

Ditto for Logtalk r5209.

> b) additionally to a) for problematic cases warnings (only messages
> during compilation) or errors (refusing compilation)

Hope to include some of that in Logtalk 2.38.9 stable.

> c) optimize while maintaining *complete* operational equivalence
>
> But please do not consider the path of optimizing and changing the
> meaning of lambdas.  Also please never optimize incorrectly with a
> warning.  Let's leave that box closed!

Optimizations that change the semantics are bugs.

Btw, the Logtalk implementation is based only on your proposed syntax,
not in your library(lambda) code. An interesting feature of the
Logtalk implementation is that the number of lambda parameters is only
limited by max_arity of the back-end Prolog compiler.

Cheers,

Paulo

Ulrich Neumerkel

unread,
Nov 30, 2009, 12:40:00 PM11/30/09
to
Paulo Moura <pjlm...@gmail.com> writes:
>On Nov 29, 3:10=A0pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
>Neumerkel) wrote:

>> On Nov 29, 12:23=3DA0am, Paulo Moura <pjlmo...@gmail.com> wrote:
>>
>> >Error checking is implemented in r5208:
>>
>> >| ?- logtalk << \ _^write(hello).
>> >uncaught exception: error(representation_error(lambda_parameters),
>> >\_278^write(hello),logtalk)
>>
>> Very fine! Having an error here is the only way to prevent so many
>> misunderstandings of beginners - the runtime overheads are neglectable
>> - see my next-to-be-written response.
>>
>> Concerning the representation error - which might appear as somewhat
>> unusual - here is my motivation:
>> ...
>> Another alternative might be the existence error. =A0Note that
>> semantically an existence error of a procedure also means failure. =A0So

>> maybe existence_error(lambda_parameter, Culprit) might be a good idea
>> with Culprit showing the remaining parameters.
>
>Maybe we should make a distinction, using different exception terms,
>between missing lambda parameters and too many lambda parameters?

How can we say that we transmit too many parameters? In ISO-Prolog,
and even more in SWI, we associate frequently one name to many
different arities. Not only is ISO-Prolog a precedent, but also
phrase/2, phrase/3 and even some built-ins in DECsystem 10 Prolog as of
1978.

?- [user].
|: factum(1,2).
|: % user://1 compiled 0.00 sec, 312 bytes
true.

?- \ factum(1,2).
true.

?- \_^factum(1,2).
ERROR: user://1:26:
Cannot represent due to `lambda_parameters'

So here we have a case where a lambda parameter expects
an argument, but does not get one.


?- call( \factum(1,2), 3).
ERROR: user://1:29:
lambda:\/2: Undefined procedure: factum/3
However, there are definitions for:
factum/2

And this is the case you probably want to be handled differently.
Impossible - think of open/2 and 3 etc.

Paulo Moura

unread,
Nov 30, 2009, 1:39:58 PM11/30/09
to
On Nov 30, 5:40 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

Are you sure? Consider (using Logtalk r5209 + GNU Prolog):

| ?- meta::map(\X^Y^(X=A-B,Y=B-A), [1-a,2-b,3-c], Zs).

Zs = [a-1,b-2,c-3]

(1 ms) yes

| ?- meta::map(\X^Y^Z^(X=A-B,Y=B-A), [1-a,2-b,3-c], Zs).
uncaught exception: error(representation_error(lambda_parameters),
\_278^_281^_284^(_278=_293-_294,_281=_294-_293),meta)

| ?- meta::map(\X^(X=A-B,Y=B-A), [1-a,2-b,3-c], Zs).
uncaught exception: error(representation_error(lambda_parameters),
\_278^(_278=_287-_288,_290=_288-_287),meta)

In the first error case, there is an extraneous lambda parameter (Z).
In the second case, a lambda parameter is missing. Both cases can be
easily detected and differentiated when unifying the lambda parameters
with the maplist/3 closure arguments. At least in the Logtalk
implementation. The question for me is: is it worth to have two
distinct exception terms for these cases? Say:

representation_error(missing_lambda_parameters) representation_error
(extraneous_lambda_parameters)

I think not but your feedback is welcome.

Cheers,

Paulo

Ulrich Neumerkel

unread,
Nov 30, 2009, 2:48:01 PM11/30/09
to
Paulo Moura <pjlm...@gmail.com> writes:
>On Nov 30, 5:40pm, ulr...@mips.complang.tuwien.ac.at (Ulrich


It is definitely a misunderstanding. You have implemented
only half of the lambdas. I put the entire source code out
such as to avoid misunderstandings as these. But evidently
providing a complete implementation is not enough.

That's why specifications are so necessary.

Please refer to Richard O'Keefe's examples. They are just
above

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord

common_prefix(Front, Xs, Ys) :-
maplist(Front+\append(Front), Xs, Ys).

?- common_prefix([1],Xs,Ys).
Xs = [],
Ys = [] ;
Xs = [_G2168],
Ys = [[1|_G2168]] ;
Xs = [_G2168, _G2187],
Ys = [[1|_G2168], [1|_G2187]]


What do you get here?

Paulo Moura

unread,
Nov 30, 2009, 5:01:46 PM11/30/09
to
On Nov 30, 7:48 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:
> ...

> >In the first error case, there is an extraneous lambda parameter (Z).
> >In the second case, a lambda parameter is missing. Both cases can be
> >easily detected and differentiated when unifying the lambda parameters
> >with the maplist/3 closure arguments. At least in the Logtalk
> >implementation. The question for me is: is it worth to have two
> >distinct exception terms for these cases? Say:
>
> >representation_error(missing_lambda_parameters) representation_error
> >(extraneous_lambda_parameters)
>
> >I think not but your feedback is welcome.
>
> It is definitely a misunderstanding.  You have implemented
> only half of the lambdas.

But maybe I implemented the better half? Just kidding :-)

> I put the entire source code out
> such as to avoid misunderstandings as these.  But evidently
> providing a complete implementation is not enough.

Note that I'm not using a single bit of your implementation. I'm only
taking from your proposal the lambda expressions syntax and query
examples.

> That's why specifications are so necessary.
>
> Please refer to Richard O'Keefe's examples.  They are just
> above
>
> http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord
>
> common_prefix(Front, Xs, Ys) :-
>     maplist(Front+\append(Front), Xs, Ys).
>
> ?- common_prefix([1],Xs,Ys).
> Xs = [],
> Ys = [] ;
> Xs = [_G2168],
> Ys = [[1|_G2168]] ;
> Xs = [_G2168, _G2187],
> Ys = [[1|_G2168], [1|_G2187]]
>
> What do you get here?

In the current development version (not yet in the Subversion server):

| ?- half::common_prefix([1],Xs,Ys).

Xs = []
Ys = [] ? ;

Xs = [A]
Ys = [[1|A]] ? ;

Xs = [A,B]
Ys = [[1|A],[1|B]] ? ;

Xs = [A,B,C]
Ys = [[1|A],[1|B],[1|C]] ? ;

Xs = [A,B,C,D]
Ys = [[1|A],[1|B],[1|C],[1|D]] ? ;

...

Cheers,

Paulo

Paulo Moura

unread,
Nov 30, 2009, 7:40:57 PM11/30/09
to
On Nov 30, 10:01 pm, Paulo Moura <pjlmo...@gmail.com> wrote:
> ...

Committed in r5210. Is quite possible that bugs remain, however.
Moreover, not a single optimization yet in r5210.

Cheers,

Paulo

Ulrich Neumerkel

unread,
Dec 1, 2009, 6:50:43 AM12/1/09
to
Paulo Moura <pjlm...@gmail.com> writes:

>On Nov 30, 10:01=A0pm, Paulo Moura <pjlmo...@gmail.com> wrote:
>> ...
>> > That's why specifications are so necessary.
>>
>> > Please refer to Richard O'Keefe's examples. =A0They are just

>> > above
>>
>> >http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord
>>
>> > common_prefix(Front, Xs, Ys) :-
>> > =A0 =A0 maplist(Front+\append(Front), Xs, Ys).
>>
>> > ?- common_prefix([1],Xs,Ys).
>> > Xs =3D [],
>> > Ys =3D [] ;
>> > Xs =3D [_G2168],
>> > Ys =3D [[1|_G2168]] ;
>> > Xs =3D [_G2168, _G2187],
>> > Ys =3D [[1|_G2168], [1|_G2187]]

>>
>> > What do you get here?
>>
>> In the current development version (not yet in the Subversion server):
>>
>> | ?- half::common_prefix([1],Xs,Ys).
>>
>> Xs =3D []
>> Ys =3D [] ? ;
>>
>> Xs =3D [A]
>> Ys =3D [[1|A]] ? ;
>>
>> Xs =3D [A,B]
>> Ys =3D [[1|A],[1|B]] ? ;
>>
>> Xs =3D [A,B,C]
>> Ys =3D [[1|A],[1|B],[1|C]] ? ;
>>
>> Xs =3D [A,B,C,D]
>> Ys =3D [[1|A],[1|B],[1|C],[1|D]] ? ;

>
>Committed in r5210. Is quite possible that bugs remain, however.
>Moreover, not a single optimization yet in r5210.


What was really interesting here, is that we identified differences
by looking at the "corner cases" only. One case to underline how
important errors are in Prolog.

Paulo Moura

unread,
Dec 3, 2009, 8:50:51 PM12/3/09
to
On Nov 28, 9:20 pm, Paulo Moura <pjlmo...@gmail.com> wrote:
> Hi,
>
> I have implemented Ulrich's syntax for lambda expressions in the
> current development version of Logtalk (r5204 or later). It should
> work with all supported back-end Prolog compilers.
> ...

Logtalk 2.38.0, released today, contains a (no longer experimental)
implementation of lambda expressions (not based in Ulrich's lambda
library implementation). This implementation uses a non-frills syntax
(different from the one in Ulrich's proposal) that reuses existing ISO
Prolog standard operators:

http://logtalk.org/manuals/refman/grammar.html#grammar_lambdas

Currying is supported. Example queries can be found here:

http://svn.logtalk.org/viewvc.cgi/trunk/examples/lambdas/

Needless to say, lambda expressions are supported when using all
compatible back-end Prolog compilers :-) Enjoy!

Cheers,

Paulo

Paulo Moura

unread,
Dec 8, 2009, 11:26:25 AM12/8/09
to
On Dec 4, 1:50 am, Paulo Moura <pjlmo...@gmail.com> wrote:
> ...
> Logtalk 2.38.0, released today, contains a (no longer experimental)
> implementation of lambda expressions (not based in Ulrich's lambda
> library implementation). This implementation uses a non-frills syntax
> (different from the one in Ulrich's proposal) that reuses existing ISO
> Prolog standard operators:
>
> http://logtalk.org/manuals/refman/grammar.html#grammar_lambdas
>
> Currying is supported. Example queries can be found here:
>
> http://svn.logtalk.org/viewvc.cgi/trunk/examples/lambdas/
>
> Needless to say, lambda expressions are supported when using all
> compatible back-end Prolog compilers :-) Enjoy!

I published a more user friendly presentation in my blog:

http://blog.logtalk.org/2009/12/08/lambda-expressions-in-logtalk/

Cheers,

Paulo

Ulrich Neumerkel

unread,
Dec 8, 2009, 4:36:35 PM12/8/09
to
Paulo Moura <pjlm...@gmail.com> writes:

Just to state this clearly: That version is wrong again.

I tried several times, to explain you what the deep
reasons behind are (on the SWI-list) but it seems your
major goal is to use a different syntax. So I give up.

Paulo Moura

unread,
Dec 8, 2009, 5:29:15 PM12/8/09
to
On Dec 8, 9:36 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

> Paulo Moura <pjlmo...@gmail.com> writes:
> >On Dec 4, 1:50=A0am, Paulo Moura <pjlmo...@gmail.com> wrote:
> >> ...
> >> Logtalk 2.38.0, released today, contains a (no longer experimental)
> >> implementation of lambda expressions (not based in Ulrich's lambda
> >> library implementation). This implementation uses a non-frills syntax
> >> (different from the one in Ulrich's proposal) that reuses existing ISO
> >> Prolog standard operators:
>
> >>http://logtalk.org/manuals/refman/grammar.html#grammar_lambdas
>
> >> Currying is supported. Example queries can be found here:
>
> >>http://svn.logtalk.org/viewvc.cgi/trunk/examples/lambdas/
>
> >> Needless to say, lambda expressions are supported when using all
> >> compatible back-end Prolog compilers :-) Enjoy!
>
> >I published a more user friendly presentation in my blog:
>
> >http://blog.logtalk.org/2009/12/08/lambda-expressions-in-logtalk/
>
> Just to state this clearly: That version is wrong again.

Care to post an example that shows what's wrong with it? E.g.
something that is possible with your "lambda" library implementation
that is not possible using the current Logtalk implementation? Or an
example where the Logtalk implementation returns a wrong answer? Can
you back up your claim with hard evidence? I'm happy to learn from my
mistakes.

> I tried several times, to explain you what the deep
> reasons behind are (on the SWI-list)

Like the following one?

https://mailbox.iai.uni-bonn.de/mailman/public/swi-prolog/2009/002611.html

Sure, is quite enlightening in telling that *something* is wrong
without actually pointing to *what* is actually wrong.

> but it seems your
> major goal is to use a different syntax.

No, it's not. You're simply ignoring the critics to your proposed
syntax made by me and others, specially in the SWI-Prolog mailing
list. Have you actually read my blog post?

> So I give up.

That's perfectly within your rights.

Regards,

Paulo

Ulrich Neumerkel

unread,
Mar 18, 2010, 9:41:32 AM3/18/10
to

To facilitate the inclusion of library(lambda) into Prolog systems
the two-clause BSD license has been added:

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

0 new messages