Tabling and the -> operator

So, I’ve never cared much for the -> operator.

I know it removes a choice point, but it’s always felt ‘not the prolog way’.

baz(X) :-
     ( bar(X) ->
       foo(X)
     ;
      mep(X)
    ).

So if I table bar, I should be able to write

baz(X) :-
     bar(X),
     foo(X).
baz(X) :-
     \+ bar(X),
     mep(X).

at no performance penalty?

this just feels purer somehow.

I did, thanks for the correction. Will fix in the original

If bar/1 is tabled, it should only be called once.

(Sorry for garble on this question, it’s been a long day).

If you are tabling bar/1 then you should use tnot/1 instead of \+.

1 Like

Well, you avoid double evaluation. You do pay a price in time (tabled execution needs to maintain tables and is thus slower if you get no profit from its reusing its tables) and notably in memory. Finally, truth maintenance is harder: if bar/1 somehow depends on anything buts its arguments you must be sure its tables are properly invalidated and recomputed. So, in general I don’t think this is a wise replacement.

2 Likes

If the condition is sufficiently ground, the if-then-else has a nice logical reading. (And it’s possible to extend this idea, using freeze/2 or when/2.)

It’s unfortunate that Prolog doesn’t have a way of marking the last clause as an “otherwise”.

1 Like

If you want to do an if in pure prolog (it is a little slower, but it works in all modes) you can do it with

if_/3 from library(reif):

:- use_module(library(reif)).
baz(X) :-
    if_(bar(X), foo(X), mep(X)).


foo(1) :- writeln(foo).
mep(2) :- writeln(mep).

% Notice you provide the boolean output of the condition as the 
% last output argument (this is called reifying the truth value)
bar(1,true).
bar(2,false).

query:

15 ?- baz(a).
false.

16 ?- baz(1).
foo
true.

17 ?- baz(2).
mep
true.

Notice you have to reify the truth or falsity of the condition (bar/2). This means you make the truth value be an output argument of the predicate. The value is true if the condition is true, or false if it is false.

Advantage is that it is pure:

18 ?- baz(X).
foo
X = 1 ;
mep
X = 2.
2 Likes

Is this the library(reif) to which you refer?
http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/swi/reif.pl
Is there documentation for it?

(And it’s not in a SWI-Prolog “pack”?)

I can not find it in a single place.

The best I can find are the links to SO answers from his SO user page which explain each predicate in detail with examples. Look at the info and scroll down to find some of the links.

Paragraph copied here on 09/09/2019 for those who can’t find the links.

Whose mind is not touched by such pure beauty? More: if_/3 , (=)/3 , memberd_t/3 , tfilter/3 , tmember/2 , (',')/3 , maplist/2,3,4... , closure/3 , closure0/3 , path/4 , λ , iso_dif/2 , memberd/2 , non_member/2 , all//1 , all_seq//2 , iwhen/2 , call_nub/1 , call_semidet/1 , call_nth/2 . You have more?

Yes, that’s the library; I find it very useful.

There is some more information in this paper:

I have no idea why it is not a pack yet.

I remember just going through the source and playing with it on the top level to get an understanding of it.