0

I'm working on an exercise whereby I'm trying to use the =.. predicate to write a procedure that removes all elements in List for which PredName(X) fails and returns the remaining list as Result:

filter(List, PredName, Result)

In this case with PredName being defined as:

test(N) :- atom(N).

For example:

?- filter([a,b,-6,7,A,-1,0,B], test, L).
L = [a,b,-6,7,-1,0],

I've got the following, but I'm not sure why I keep getting false as a result when testing with the example above:

test(N):-
    atomic(N).
filter([], _, []).
filter2([H|T], PredName, [H|S]):-
    Goal =.. [PredName, H],Goal,filter(T, PredName, S),!.
filter([H|T], PredName, S) :-
    filter2(T, PredName, S).

I got the above code from here.

Community
  • 1
  • 1
Zenadia Groenewald
  • 107
  • 1
  • 3
  • 12

2 Answers2

4

Did you try to compile the code?

I get:

Clauses of filter/3 are not together in the source-file

Why? Because you need to decide how to call the predicate: Either filter2/3 or filter/3. You are currently using both names.

Also, when you have code like:

Goal =.. [PredName, H],
Goal

Simply use call/2 instead. For example, the above can be equivalently written as:

call(PredName, H)

In summary:

  • decide on the predicate name and stick to it
  • don't use (=..)/2 for such cases
  • do use call/2.
mat
  • 40,498
  • 3
  • 51
  • 78
  • Yeah, compiled it. Got that until I compiled it a second time - didn't get it again. Also, I would use call/2 but the purpose of the exercise was to attempt it with =.. – Zenadia Groenewald Jul 29 '16 at 12:53
  • 1
    I'm knew that you had to use `(=..)/2`, but I still want to mention that `call/2` is more appropriate in this case, so that instructors who read this have a chance to give more useful exercises in the future. There are many good exercises where using `(=..)/2` does make sense, but this definitely isn't one of them. – mat Jul 29 '16 at 13:01
  • Fair point. Thanks anyway - the changes you proposed do work. – Zenadia Groenewald Jul 29 '16 at 13:14
  • 2
    @Zena: Note that with your current use of `(=..)/2`, you can only call predicates of arity 1. So you cannot call it with, say `>(1)`, thus `call(>(1), E)` and thus `>(1, E)` or simply `1 > E`. That's the big advantage of `call/2`. – false Jul 29 '16 at 17:43
0

Fixed it. Had a problem with the naming that I didn't catch before. Renamed filter2 to filter and it worked.

Zenadia Groenewald
  • 107
  • 1
  • 3
  • 12
  • 1
    Rather than add this as an answer, you should accept mat's answer since he pointed out the naming issue. – lurker Jul 29 '16 at 13:25