Menu

#30 Porting functional-style code from SWI Prolog

open
nobody
None
5
2023-12-14
2023-12-14
No

I am using XSB within a project that involves some data mining and probabilistic inductive logic programming, and I would like to provide some baselines. For this I would like to use Fabrizio Riguzzi's SWI-Prolog linear and logistic regression programs, which ultimately rely on his matrix library. Of course, I could use Janus or the C-interface to interface any other matrix library or spin my own C functions, but since I don't care about efficiency here I thought it might be easiest to simply port that library.

However, it is written in a very functional style, with clauses such as

matrix_div_scal(A,V,B):-
  maplist(maplist(div(V)),A,B).

Even if I import the maplists from the swi compatibility library in the matrix module, I get an error that "no predicate usermod:maplist/3" exists.
Tracing reveals that the outer maplist is recognised correctly and only the inner maplist is considered unknown.
To me, this seems to contradict "All occurrences of T/N in M are in a file are normally associated
with the same module" from the Manual, but I think I am just fundamentally misunderstanding module inference.

Is there any good practice advice as to how to approach a port using a lot of such functional programming constructs?

Discussion

  • David S. Warren

    David S. Warren - 2023-12-14

    I think I know what is going on. Note that the predicate/functor maplist appears both as maplist/3 as the outer call (as a predicate) and as maplist/1 (as the functor of the first argument to the outer call). Now the definition of maplist probably makes a call of the form call(P,X,Y). Now call/3 uses the module of the first argument to make the predicate symbol for the resulting call. So here the maplist/1 functor is not imported, so it is in usermod, and thuse the maplist/3 call is also to maplist in usermod.
    One way to fix this is to import maplist/1 from (wherever). Then the call/3 will calll maplist/3 in the correct module. (Even though that module does not define maplist/1, you can import it. It's only a problem is you really call maplist/1, and in this case you won't, so all should be fine.)
    I agree this is not optimal, but I know of no (reasonable) way to make call/3 know the right module to use for the call, in this case.

    (It's possible that the maplist definition is using some other way to construct the maplist/3 term from the maplist/1 term to make the call, and if so, it might lose the module in some other way, and then this proposed way to fix your problem might not work...)

     
    • Felix Weitkämper

      You were absolutely right! The "fake import" did fix the issue. What I have now done is just put explicit module qualifications on any predicate call within a maplist, and that also solved the problem.

       

      Last edit: Felix Weitkämper 2023-12-14
  • David S. Warren

    David S. Warren - 2023-12-14

    Yes, explicit module modifiers override the module associated with the symbol (at least in all places we remembered to add the necessary code :-).

     

Log in to post a comment.