SWI-Prolog / issues

Dummy repository for issue tracking
7 stars 3 forks source link

Lambda expression (yall) corrupted on reload #56

Closed free-variation closed 7 years ago

free-variation commented 7 years ago

I have a source file with the following relation:

relations_of_type(Type, Relations, RelationsOfType) :-
    include([Rel]>>(Rel=rel(Type, _, _)), Relations, RelationsOfType).

After initially loading this all is well:

?- listing(relations_of_type).
relations_of_type(B, C, D) :-
    include([A]>>(A=rel(B, _, _)),
        C,
        D).

However, if I then reload the file, or issue make, I get an odd corruption:

?- ['src/prolog/logical_form.pro'].
true.

?- listing(relations_of_type).
relations_of_type(_, A, B) :-
    include('__aux_yall_08107e3183ab64415a351df9b946002ecdb185fb',
        A,
        B).

true.

This is on Linux Mint 18.1, running both SWI-Prolog dev and stable, i.e. 7.5.3 and 7.4.2.

free-variation commented 7 years ago

Moving the lambda expression in the include to a separate variable seems to solve it:

relations_of_type(Type, Relations, RelationsOfType) :-
    Includer = [Rel]>>(Rel=rel(Type, _, _)),
    include(Includer, Relations, RelationsOfType).
JanWielemaker commented 7 years ago

Lambda expressions are compiled away using a generated predicate who's name is the secure hash of the term-representation of the predicate. If you load the code for the first time and you do not explicitly include library(apply) it doesn't know include/3 is a meta-predicate and thus it will use the interpreted version. If you run it, include/3 wil be autoloaded and if your next reload it knows this is a meta-predicate.

So, there is only a bug if the generated predicate doesn't do what it is supposed to do. Note that interpreted Lambda expressions are pretty slow.

free-variation commented 7 years ago

Thank you for the explanation Jan. When are lambda expressions interpreted vs compiled? When they contain variables that are not declared in the existentials and lambda var lists?

JanWielemaker commented 7 years ago

They are compiled by expand_goal/2. That means they must appear in a goal position of a predicate and must be sufficiently instantiated at compile time. As they are mostly used together with predicates from the library(apply), make sure to use :- use_module(library(apply)). in such cases. That ensures the definitions of maplist, include, etc. are known.