trealla-prolog / trealla

A compact, efficient Prolog interpreter written in plain-old C.
MIT License
272 stars 13 forks source link

Feature request library(sequence) #606

Closed Jean-Luc-Picard-2021 closed 3 weeks ago

Jean-Luc-Picard-2021 commented 3 weeks ago

I see that Trealla Prolog has a few bifs such as call_nth/2, limit/2 and offset/2. These bifs are usually explained as inspired by the corresponding

SQL database querying language equivalents. But what about a distinct/1 meta predicate? The predicate is somehow missing:

$ ./tpl -v
Trealla Prolog (c) Infradig 2020-2024, v2.57.9-5-gcd77

$ ./tpl
?- distinct((X=1;X=2;X=1)).
   throw(error(existence_error(procedure,distinct/1),distinct/1)).

On the other hand in SWI-Prolog I get:

/* SWI-Prolog 9.3.11 */
?- distinct((X=1;X=2;X=1)).
X = 1 ;
X = 2 ;
false.
infradig commented 3 weeks ago

You could do distinct/1 something like...

distinct(Goal) :-
    distinct(Goal, Goal).

:- meta_predicate(distinct(0)).

distinct(Witness, Goal) :-
    term_variables(Witness, Vars),
    Witness1 =.. [v|Vars],
    setup_call_cleanup(
        true,
        (
            Goal,
            \+ clause('$distinct'(Witness1, Goal), _),
            assertz('$distinct'(Witness1, Goal))
        ),
        retractall('$distinct'(Witness1, _))
    ),
    true.

:- meta_predicate(distinct(0,0)).
Jean-Luc-Picard-2021 commented 3 weeks ago

I guess it will pass this test case, right?

/* SWI-Prolog, eagerness */
?- distinct(repeat), !.
true.

But it wont pass this test case, right?

/* SWI-Prolog, non-variant enumerating */
d(f(A,A)).
d(f(a,a)).
d(f(B,B)).

?- distinct(d(X)).
X = f(_70321, _70321);
X = f(a, a);
fail. 

And this test case will also fail, right?

/* SWI-Prolog, reentrant */
?- distinct((distinct(X=1);distinct(X=1))).
X = 1 ;
false.
infradig commented 3 weeks ago

Maybe for the future.