When does PEngines return args/functor format and when does it return plain format?

I’m using: SWI-Prolog version 8.0.2 on Ubuntu Linux 18.04.

I use the predicate below to create the response I send back to Node.JS queries to my PEngines server.

create_response(EventList) :-
		% Accumulate all the temporary data generated during this volley.
		bagof(Event, u_query(temp(Event)), EventList),
		!.
% If the query did not generate any temp elements, then it is an empty report.
create_response([empty_report]) :- !.

It gathers up all the facts I asserted to the Prolog data that were generated during the query and returns that information as the result of the query. As you can see, if there were no facts asserted to the database, the catch-all response [empty_report] is returned.

What I don’t understand is the following: If the bagof() goal succeeds, I get back a list of objects in a list. As I mentioned in another thread, that list objects reaches my NodeJS code in some custom format I call the args/functor format that appears to be some kind of meta description of the list of objects bagof() returned. This is not my format. It is something that PEngines appears to do on its own. Because of this I wrote a parser on the NodeJS side to turn that format back into the original object llist without the args/functor decorations. This works fine.

However, for some reason the simpler return that is the result of the second create_response() clause, that of the value [empty_report], does not reach my NodeJS code in args/functor format. It shows up in the result object received by my on-success event handler as just a simple list with the variable name I assigned the response to -> Report: [empty_report]. This causes my parsing code to fail since it is not in args/functor format and that code expects it to be in that format.

Can someone tell me the rules for what causes PEngines to use the args/functor format and at other times, not use it?

First of all, why not simply create_response([])?. Second, stay away from bagof/setof unless you really understand them and need them. They are logically sweet, but often surprise people. For most cases simply use findall/3, which gives far less surprises.

Finally, just call u_query(temp(Event)). That gives you the events one-by-one. If there are many this gets slow, but if you give chunk:1000 as option to ask, you get them in chunks of 1,000 with practically the same performance. If there are really a lot, the UI can indicate such instead of going ballistic.

2 Likes