SWI-Prolog / packages-pengines

Pengines: Prolog engines
11 stars 13 forks source link

Bug possibly in selecting the correct default template #10

Closed torbjornlager closed 9 years ago

torbjornlager commented 10 years ago
% Consider the following example:

:- use_module(library(pengines)).

test1 :-
    pengine_create([
        server('http://pengines.swi-prolog.org'),
        ask(p(X)),
        src_text("p(a). p(b).")
    ]),
    pengine_event_loop(handler, []).

handler(success(ID, X, true)) :-
    writeln(X),
    pengine_next(ID, []).
handler(success(_ID, X, false)) :-
    writeln(X). 

/*
Here's a weird behaviour:

?- test1.
[json{}]
[json{}]
true.

Where did the dict come from?

*/

% It works locally:

test2 :-
    pengine_create([
        ask(p(X)),
        src_text("p(a). p(b).")
    ]),
    pengine_event_loop(handler, []).

% It also works if we use the template option:

test3 :-
    pengine_create([
        server('http://pengines.swi-prolog.org'),
        ask(p(X)),
        template(p(X)),
        src_text("p(a). p(b).")
    ]),
    pengine_event_loop(handler, []).

:- test1, test2, test3.
JanWielemaker commented 10 years ago

The problem is that the Prolog term is serialized as p(_) (the variable is anonymous). The only way to solve that would be to stick in a template at the client side if this is missing. Now, it is not clear what this template should be. The entire goal? Or the free variables of the goal?

All in all, I don't think this type if usage makes much sense. You need to program more high level interaction such as pengine_rpc/3 and depending on what you want there, you probably want different templates, probably rarely ever the entire goal.

torbjornlager commented 10 years ago

For Prolog-JS communication the best template is what we already have. But I have always thought that the entire goal would make the most suitable default for Prolog-Prolog communication. This is also how it used to be at one point. One thing that in my mind makes the whole goal template intuitive is that you can easily do pattern matching on the events, like so:

handler(success(ID, p(X), true)) :-
    writeln(X),
    pengine_next(ID, []).

In any case I think the [json{}] answer is far too much a surprise.

torbjornlager commented 9 years ago

Ok, I fixed this:

remote_pengine_create(BaseURL, Options) :-
    partition(pengine_create_option, Options, PengineOptions0, RestOptions),
    (   option(ask(Query), PengineOptions0),
        \+ option(template(_Template), PengineOptions0)
    ->  PengineOptions = [template(Query)|PengineOptions0]
    ;   PengineOptions = PengineOptions0
    ),
        ....
torbjornlager commented 9 years ago

And also created a test :-)