14
votes

Is there any way to define constants in prolog?

I'd like to write something like

list1 :- [1, 2, 3].
list2 :- [4, 5, 6].

predicate(L) :- append(list1, list2, L).

The work-around I'm using now is

list1([1, 2, 3]).
list2([4, 5, 6]).

predicate(L) :-
    list1(L1),
    list2(L2),
    append(L1, L2, L).

but it's a bit clumsy to bind a "useless" variable like this every time I need to access the constant.

Another (even uglier) work around I suppose, would be to include cpp in the build-chain.

(In my actual application, the list is a large LUT used in many places.)

2
That's not a work-around. That's called fact-declaration. You declaring fact that list1/1 is successive goal if its argument is [1,2,3]. There is no variables in prolog, so you can assume that every "value" (atom or term) is constant and each "variable" (value name) is non-determinitict constant. Each "variable" (ex. L1) can hold even (1+2*3) and it will never be interpreted, because that's term (something like (1+(2*3)) and there is fact (7 is (1+(2*3)).). When you pass list1 as argument of append it is interpreted as atom. You can define myappend(list1,list2,[1,2,3,4,5,6]). - ony
I use fact-declaration as a work-around for not having constants. - aioobe

2 Answers

13
votes

I don't think you can do that in 'pure' Prolog (though some implementations may let you do something close, for example ECLiPSe has shelves).

The reason is:

1) You can't write things like

list1 :- [4, 5, 6].

or

list1 = [4, 5, 6].

Because right hand side and left hand side are both grounds terms which don't match.

2) You can't write things like

List1 :- [4, 5, 6].

or

List1 = [4, 5, 6].

because the left hand side is now a variable, but variables are only allowed in predicate heads/bodies.

What you could do is to define a multi-option predicate like:

myList([1, 2, 3]).
myList([4, 5, 6]).

and then retrieve all its values with bagof (or similar predicates):

predicate(L) :-
    bagof(ML, myList(ML), MLs),        
    concat(MLs, L).

MLs is the list of all ML values that satisfy myList(ML) and of course concat concatenates a list of lists.

4
votes

No, you can't do that in Prolog, and defining it via a predicate is the sensible thing to do.

Or better, encapsulate your lookup function in a predicate.

That said, if you really want to use preprocessing there is term_expansion/2, but it can make your code unreadable and messy if you are not careful.

You could also look into extensions of Prolog that include function notation (functional logic languages like Mercury). But these are even more exotic than Prolog.