Scope of library(apply_macros)

Whats the scope of library(apply_macros). Somebody observed a drastic timing difference between SWI-Prolog 8.3.4 and SWI-Prolog 8.3.21. The predicate match2/3 is mutch faster in SWI-Prolog 8.3.4 than in SWI-Prolog 8.3.21.

I am a little bit investigating why this is so. I found that library(apply_macros) had a problem with a maplist. It did this one:

gimme_random_sequence(Length, Seq) :-
    length(Seq, Length),
    '__aux_maplist/2___aux_yall_8f8726bfc6600d3eda1280a41de9749e3ff1252c+0'(Seq).

But it didn’t do this one:

?- listing(match2/3).
match2(Seq1, Seq2, Count) :-
    (   maplist([X, Y, X-Y]>>true,
                Seq1,
                Seq2,
                Seq3)
    ->  aggregate_all(count,
                      ( member(X-X, Seq3),
                        X\='_'
                      ),
                      Count)
    ;   Count=0
    ).

Is this a bug or feature? Should I use a different variable name in the aggregate?

Open source:

Sequence Match Problem
https://gist.github.com/jburse/9fd22e8c3e8de6148fbd341817538ef6#file-sequence-pl

You should make sure that all related meta-predicates are loaded. So, for sanity

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

match2(Seq1, Seq2, Count) :-
   (   maplist([X,Y,X-Y]>>true, Seq1, Seq2, Seq3)
   ->  aggregate_all(count, (member(X-X, Seq3), X\='_'), Count)
   ;   Count = 0 ).
101 ?- listing(match2/3).
match2(Seq1, Seq2, Count) :-
    (   '__aux_maplist/4___aux_yall_0bb6d431494e13373fc7f7cf18d02cb8ec8e1313+0'(Seq1,
                                                                                Seq2,
                                                                                Seq3)
    ->  aggregate_all(count,
                      ( member(X-X, Seq3),
                        X\='_'
                      ),
                      Count)
    ;   Count=0
    ).

For speed, also prefer X \== c over X \= c. Were \= has to do quite a bit of work, \==, in particular against an atomic constant is a really simple test. As in most cases the negation makes little sense before X is sufficiently instantiated this is probably better anyway.

1 Like

Oh, the irony. I used:

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

Now the generator and transformer are very close:

?- test(100000).
% 374,146 inferences, 0.019 CPU in 0.019 seconds (99% CPU, 19379778 Lips)
% 174,145 inferences, 0.014 CPU in 0.014 seconds (99% CPU, 12400840 Lips)
true.

But I should do a better measure, with larger times durations.

Is this because the native member/2 doesn’t have to fight bifurcation backtracking?