2
votes

I have to write a project/3 predicate in prolog that returns true when the third argument is a list containing the Nth arguments of the first list elements. If a term has less than Nth arguments, then it must be ignored. I need to use a default predicate such as functor, arg or univ (=..).

some examples:

?-project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, [baz, 2, 3]).
  true

?-project([3 * sin(x), 40 + 2, cos(x), 42], 2, L2).
  L2 = [sin(x), 2]

The code i wrote:

project([], _, []):- !.
project([X | Xs], N, [Z | Zs]):-arg(N, X, Z), project(Xs, N, Zs).

if i try, for example:

?- project([40 + 2, 30 - 1], 2, X).
X = [2, 1].

The result is good. I don't understand how to add the "If a term has less than Nth arguments, then it must be ignored" part in the code.

ty all

1
At your first test case is at least a [ bracket missing.Ben373

1 Answers

1
votes

In your current attempt if the N is greater than the arity of the term then arg(N, X, Z) will fail and as a result project/3 will fail too:

?- project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, L).
false.

So you need to handle the case where calling arg(N, X, Z) fails due to N>arity of X and just ignore term X:

project([], _, []):- !.
project([X | Xs], N, L):- 
                ( 
                  arg(N, X, Z) 
                     -> L =[Z|Zs], project(Xs, N, Zs)
                  ;
                  project(Xs, N, L)
                ).

Now if you try:

?- project([foo(bar, baz), 40 + 2, sin(x), log(16, 2)], 2, L).
L = [baz, 2, 2].

You can see it succeeds returning the right answer!!