Pengine Event Loop fails to terminate

I was looking to update the Pengine’s docs, particularly the examples but I think I’ve found a bug. In the example (updated to https from the one online) :

:- use_module(library(pengines)).

main :-
    pengine_create([
        server('https://pengines.swi-prolog.org'),
        src_text("
            q(X) :- p(X).
            p(a). p(b). p(c).
        ")
    ]),
    pengine_event_loop(handle, []).


handle(create(ID, _)) :-
    pengine_ask(ID, q(_X), []).
handle(success(_ID, [X], false)) :-
    writeln(X).
handle(success(ID, [X], true)) :-
    writeln(X),
    pengine_next(ID, []).

The loop fails to terminate, after writing q(c) it just hangs waiting for more responses. On tracing it there seems to be an Continue = true -> branch that is succeeding when it should fail?

Hmm, it works if I run it from SWISH.

See https://swish.swi-prolog.org/p/mHpuRmLv.pl

From where do you run it?

Since I cannot stop nagging people about Web Prolog, I’d like to take this opportunity to show how the program above can be written in it:

main :-
    pengine_spawn(Pid, [
        node('http://localhost:3060'),
        src_text("
            q(X) :- p(X).
            p(a). p(b). p(c).
        ")
    ]),
    pengine_ask(Pid, q(_X)),
    collect_and_print(Pid).
    
collect_and_print(Pid) :-
    receive({
        success(Pid, [X], false) -> 
            writeln(X);
        success(Pid, [X], true) ->
            writeln(X),
            pengine_next(Pid),
            collect_and_print(Pid)
    }).

Now, let’s compare this program with the program using library(pengines):

  1. Web Prolog’s Erlang-ish style is much easier to understand (and especially easy for Erlangers).

  2. Using library(pengines), one has to wait for a create message before doing anything else. In Web Prolog, pengine_spawn/1-2 doesn’t return until the Pid has a value. Just like in Erlang.

  3. In the Web Prolog program, we are checking that the success messages really are coming from the actor named Pid. (After all, in another context, they could have come from anywhere.) This is not done in the program using library(pengines). (It can be done, but it isn’t. The handler would need one more argument.)

  4. Suppose that instead of printing the value of each X, we want to collect them in a list. This would be a bit tricky using library(pengines), but is easy using Web Prolog:

main(List) :-
    pengine_spawn(Pid, [
        node('http://localhost:3060'),
        src_text("
            q(X) :- p(X).
            p(a). p(b). p(c).
        ")
    ]),
    pengine_ask(Pid, q(_X)),
    collect_in_list(Pid, List).
    
collect_in_list(Pid, List) :-
    receive({
        success(Pid, [X], false) -> 
            List = [X];
        success(Pid, [X], true) ->
            List = [X|Rest],
            pengine_next(Pid),
            collect_in_list(Pid, Rest)
    }).

It runs like this in the PoC demonstrator:

Welcome to SWI Web Prolog!

?- main(List).
List = [q(a),q(b),q(c)].

?- 
  1. There are other problems with library(pengines), but nothing more (I think) that shows up in this example.

Ergo, due to DNA from Erlang, Web Prolog has a much better design. I’m allowed to say this, because I designed library(pengines). Well, Jan helped too, but his design ideas were good, mine were not, and I feel bad about them. Naturally, I want you all to have the best! :slight_smile:

Of course, Web Prolog is under development, and the PoC demonstrator is not secure, so if you need something that is stable and secure, you have to stay with library(pengines).

I was running it in my terminal, but it’s weird, it now runs this morning?! No idea what happened there!

1 Like

The design certainly seems like an improvement. I’m sure the iterative development process will result in a truly powerful tool.

1 Like

Yes, I really do think it’s an improvement. And I’m sure that with the help of you and others in the community, it can be improved even further!

3 posts were split to a new topic: Web prolog error handling