Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog shortcut to creating a custom enumeration

Tags:

macros

prolog

I am trying to create a custom enumeration via a series of facts.

greater(X,Y) :- less (Y,X).

less(a,b).
less(b,c).
less(c,d).

This works fine, however there is significant repetition.

I'm trying to cut that down. Is there a way to use an array for a simple linear series of facts via a transformation?

transform([a,b,c,d])

resulting in the same less definitions.

I have already created a "less" definition that uses an array and the nextto/member function to test, however I cannot add exceptions or equivalent cases like I could with individual declarations. Hence my interest in shortcutting the simple case definition, and then the desire to supplement it with more definitions.

This reminds me of where defmacro in lisp is useful.

Thanks.

Edit:

I was able to generate one series using assert. It successfully defines everything, but returns an error. I get the impression this isn't the correct method.

set_less([]).
set_less([X,Y|L]):- assert( myless(X,Y) ) , set_less([Y|L]).
:- set_less([a,b,c,d]).

Output: 
Goal (directive) failed: user:set_less([a, b, c, d])

?- listing.

:- dynamic myless/2.

myless(a, b).
myless(b, c).
myless(c, d).

Second Edit:

mylist([a,b,c,d]).

set_less([]).
set_less([_]).  ----- Key!
set_less([X,Y|L]):- assert( myless(X,Y) ) , set_less([Y|L]).
:- set_less([a,b,c,d]).

That does work! Is this a good way to define custom enumerations? I see it works now, thanks!

like image 452
Demosthenex Avatar asked Sep 14 '25 04:09

Demosthenex


1 Answers

term_expansion(list_enumerate(Name,List), [mylist(Name,List)|Flist]) :-
    list_enumerate_to_list(List, Flist).

list_enumerate_to_list([], []).
list_enumerate_to_list([_], []).
list_enumerate_to_list([X,Y|Xs], [myless(X,Y)|Ys]) :-
        list_enumerate_to_list([Y|Xs], Ys).

list_enumerate(test,[a1,b1,c1,d1]).
list_enumerate(first,[a,b,c,d]).
list_enumerate(second,[f,e,g,h]).

testless(X,Y) :- myless(X,Y).
testless(X,Y) :- myless(X,Z) , testless(Z,Y).

Output---------------------------------------------------------------

?- listing.


myless(a1, b1).
myless(b1, c1).
myless(c1, d1).
myless(a, b).
myless(b, c).
myless(c, d).
myless(f, e).
myless(e, g).
myless(g, h).

?- testless(a1,c1).
true ;
false.

?- testless(X,c1).
X = b1 ;
X = a1 ;
false.

That works! Thanks to soupdragon on #prolog on freenode.

There are a few warnings at startup, but they can be ignored.

like image 143
Demosthenex Avatar answered Sep 16 '25 12:09

Demosthenex