Question

just started programming with prolog and I'm having a few issues. The function I have is supposed to take a value X and copy it N number of times into M. My function returns a list of N number of memory locations. Here's the code, any ideas?

duple(N,_,M):- length(M,Q), N is Q.
duple(N,X,M):- append(X,M,Q), duple(N,X,Q).
Was it helpful?

Solution

Those are not memory adresses. Those are free variables. What you see is their internal names in your prolog system of choice. Then, as @chac pointed out (+1 btw), the third clause is not really making sense! Maybe you can try to tell us what you meant so that we can bring light about how to do it correctly.

I'm going to give you two implementations of your predicate to try to show you correct Prolog syntax:

duple1(N, X, L) :-
    length(L, N),
    maplist(=(X), L).

Here, in your duple1/3 predicate, we tell prolog that the length of the resulting list L is N, and then we tell it that each element of L should be unified with X for the predicate to hold.

Another to do that would be to build the resulting list "manually" through recursion:

duple2(0, _X, []).
duple2(N, X, [X|L]) :-
    N > 0,
    NewN is N - 1,
    duple1(NewN, X, L).

Though, note that because we use >/2, is and -/2, ie arithmetic, we prevent prolog from using this predicate in several ways, such as:

?- duple1(X, Y, [xyz, xyz]).
X = 2,
Y = xyz.

This worked before, in our first predicate!

Hope this was of some help.

OTHER TIPS

I suppose you call your predicate, for instance, in this way:

?- duple(3,xyz,L).

and you get

L = [_G289, _G292, _G295] ;
ERROR: Out of global stack

If you try

?- length(X,Y).
X = [],
Y = 0 ;
X = [_G299],
Y = 1 ;
X = [_G299, _G302],
Y = 2 ;
X = [_G299, _G302, _G305],
Y = 3 ;
X = [_G299, _G302, _G305, _G308],
Y = 4 .
...

you can see what's happening:

your query will match the specified *M*, displaying a list of M uninstantiated variables (memory locations), then continue backtracking and generating evee longer lists 'til there is stack space. Your second rule will never fire (and I don't really understand its purpose).

A generator is easier to write in this way:

duple(N,X,M) :- findall(X,between(1,N,_),M).

test:

?- duple(3,xyz,L).
L = [xyz, xyz, xyz].
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top