Term expansion conflicts with SWI libraries and addons

Help requests on developing Logtalk applications

Moderator: Paulo Moura

Locked
JacquesRobin
Posts: 3
Joined: Sat May 23, 2020 8:01 am

Term expansion conflicts with SWI libraries and addons

Post by JacquesRobin »

Hi there,

Camilo Correa, Salvador Abreu and I have been experimenting for some time with Logtalk’s interaction with other libraries within the SWI-Prolog ecosystem. Recently, when performing some tests with the HTTP libraries included in SWI-Prolog, some rather odd behaviour has become apparent. Given that the http_dispatch module of this library uses term expansion, it seems conflict with Logtalk’s own term expansion mechanisms at compile time.

To work around this problem we used what is suggested at https://github.com/LogtalkDotOrg/logtalk3/issues/51. Though it works to execute the server, it does not easily allow one to use the route directives, because, from our understanding, when one uses a directive such as “:- http_dispatch:http_handler(/, foo, []).”, and have a corresponding foo/1 predicate in the same file, the foo callable is in fact placed inside the http_dispatch module, with some mechanism of calling the originally defined foo predicate. When used with vanilla Prolog, it does not cause any issues. However, once one loads a file with such directives as a Logtalk file, and one does test out such a route, one immediately notices that (a) the dispatch predicate calls http_dispatch:foo on the root route, and that (b) whatever mechanism existed to enable the assertion of that predicate ceases to function when Logtalk is involved. It is likewise not possible to call a Logtalk object’s predicates from this directive, as it will give an error reporting that the :: operator poses a problem. So, one cannot simple do “:- http_dispatch:http_handler(/, my_obj::my_handler, []).”

The workaround we've found is the following: first create a predicate (outside any object) which in turn does a call to the relevant predicate (for instance to my_obj::my_handler with the same Request variable). Next, specify in the directive that the predicate to be called must explicitly be in the user module, as such: “:- http_dispatch:http_handler(/, user:foo, []).” And a predicate “foo(_R) :- my_obj::my_handler(_R).”, to perform this handling of server interaction.

We have prepared the two following GitHub gists containing a very simple proof of concept code to illustrate the issue:
- Vanilla SWI code: https://gist.github.com/kaiser185/302a6 ... e8a56fb505
- Logtalk Code: https://gist.github.com/kaiser185/25467 ... 9cfa1f92ad

Our questions are the following:

1. Is there a more elegant solution to include http server functionality within Logtalk?

2. Is it correct to assume that these issues are tied to the use of term-expansion mechanisms by both libraries and Logtalk at compilation time?

3. Is there a more elegant mechanism to make use of such libraries, in particular when they might, for instance redefine Logtalk specific operators or predicates and use complex directives and term expansions?

4. Since we encountered a similar problem when we tried to simultaneously used Logtalk with the Fabio Riguzzi's CPLInt probabilistic logic programming SWI-Prolog extension, http://ml.unife.it/cplint/, that, like Logtalk and SWI's http library, also extends the Prolog syntax with new constructs using term expansions, we are wondering whether we just stumbled upon two instances of the more general yet unsolved problem of a missing mechanism to compose multiple independently developed Prolog extensions and explicitly control the interactions between their respective term-expansion usages so that they work seamlessly together without term-expansions clashes.

Paulo Moura
Logtalk developer
Posts: 533
Joined: Sat May 05, 2007 8:35 am
Location: Portugal
Contact:

Re: Term expansion conflicts with SWI libraries and addons

Post by Paulo Moura »

JacquesRobin wrote:
Thu Aug 27, 2020 8:10 am
1. Is there a more elegant solution to include http server functionality within Logtalk?
The issue you found is caused by the Logtalk message sending control construct, ::/2, being handled as a predicate by (SWI-)Prolog and thus not being correctly processed when used as a closure in the http_handler/3 predicate (which, btw, is not a directive but simply a predicate being called as a directive). I.e. SWI-Prolog constructs a ::/3 goal from the closure instead of adding the request argument to the message argument of the ::/2 control construct. The elegant solution is to use a lambda expression. Something like:

Code: Select all

:- use_module(library(yall)).
:- use_module(library(apply_macros)).

:- http_dispatch:http_handler(/, [Request]>>(http_server::say_hi(Request)), []).
:- http_dispatch:http_handler(root(sam), [Request]>>(http_server::say_hi_sam(Request)), []).
JacquesRobin wrote:
Thu Aug 27, 2020 8:10 am
2. Is it correct to assume that these issues are tied to the use of term-expansion mechanisms by both libraries and Logtalk at compilation time?
No. Just an issue of Prolog being oblivious of Logtalk control constructs as explained above.
JacquesRobin wrote:
Thu Aug 27, 2020 8:10 am
3. Is there a more elegant mechanism to make use of such libraries, in particular when they might, for instance redefine Logtalk specific operators or predicates and use complex directives and term expansions?
Operators are local to Logtalk objects (and categories) and are also local to SWI-Prolog modules. Thus, when possible, declare the predicate locally.

A few SWI-Prolog libraries rely on term-expansions that require the predicates and directives to be used in a module (e.g. the persistency library). Those library predicates cannot usually be used from within Logtalk objects. In other cases, it's possible to use the solution described at:

https://logtalk.org/using_tools_with_pr ... -mechanism

Note that there isn't any Prolog term-expansion mechanism standard, which precludes default solutions for these issues.
JacquesRobin wrote:
Thu Aug 27, 2020 8:10 am
4. Since we encountered a similar problem when we tried to simultaneously used Logtalk with the Fabio Riguzzi's CPLInt probabilistic logic programming SWI-Prolog extension, http://ml.unife.it/cplint/, that, like Logtalk and SWI's http library, also extends the Prolog syntax with new constructs using term expansions, we are wondering whether we just stumbled upon two instances of the more general yet unsolved problem of a missing mechanism to compose multiple independently developed Prolog extensions and explicitly control the interactions between their respective term-expansion usages so that they work seamlessly together without term-expansions clashes.
Can you provide an example (similar to the HTTP libraries example in the gists) of what you're trying to accomplish using CPLint from within Logtalk objects?
Paulo Moura
Logtalk developer

Locked