4

Is it possible to define a list, that consists of predicates and how do I call the predicates.

Also, is it possible to pass one predicate to another predicate (like passing atoms)?

Example:

pre1:- something.
pre2(Predicate1, List):-
    call(Predicate1),
    append([Predicate1], List, R),
    .....
false
  • 10,264
  • 13
  • 101
  • 209
Rob Fox
  • 5,355
  • 7
  • 37
  • 63
  • The answer I think you're looking for is here: http://stackoverflow.com/questions/8687306/best-way-to-define-predicate-in-prolog – aBogdan May 02 '12 at 08:28
  • @AndreiBogdan I added an example to better illustrate what I mean. – Rob Fox May 02 '12 at 08:33
  • 1
    You might want to read [this thing](http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%274.20%27,swi%28%27/doc/Manual/manipterm.html%27%29%29) – m09 May 02 '12 at 08:59
  • @Mog this is promising, yet I cant find any examples – Rob Fox May 02 '12 at 09:35
  • Can you explain what you want to achieve a bit more detailed? You already mention `call/1` in your example, so I can't see what else you need to know... – twinterer May 02 '12 at 09:44

1 Answers1

5

You can't store predicates in a list, but you can store terms (or functors) and call terms as goals.

Here's a predicate that tests whether a term has the properties described by a list of functors:

has_properties([], _).
has_properties([P|Ps], X) :-
    Goal =.. [P, X],            % construct goal P(X)
    call(Goal),
    has_properties(Ps, X).

Usage:

% is 4 a number, an integer and a foo?
?- has_properties([number, integer, foo], 4).

The answer to this query will depend on your definition of foo/1, of course. See my explanation of =.. if needed.

Edit: as @false reports in the comments, it's not necessary to use =.., since Goal =.. [P, X], call(Goal) can be replaced by call(P, X) will have the same effect. It might still be worthwhile learning about =.., though, as you may encounter it in other people's code.

Community
  • 1
  • 1
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • Thanks! This is exactly what I was looking for. Now I need to get a value from the Goal after calling it – Rob Fox May 02 '12 at 10:25
  • 3
    Please consider `call(P, X)` instead of `(=..)/2` and `call/1`! This is so much faster, cleaner and even more general! – false May 02 '12 at 10:31
  • 1
    @false: good point. However, the SWI manual suggests that `call/2` is not in ISO Prolog. – Fred Foo May 02 '12 at 10:33
  • @RobFox I used Goal =.. [_, Args] to access the argumeters – Rob Fox May 02 '12 at 10:35
  • 1
    @larsmans: That manual is clearly outdated. Since Cor.2:2012 it is ISO. Please refer to the [tag iso-prolog](http://stackoverflow.com/tags/iso-prolog/info)! – false May 02 '12 at 10:39
  • 2
    @larsmans: Here is the [up-to-date SWI manual](http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%274.9%27,swi%28%27/doc/Manual/metacall.html%27%29%29). Well, clearly a case why getting the standard is indispensable! – false May 02 '12 at 10:42
  • @false: amended the answer. I was indeed looking at the 5.10 manual, the version packaged in Debian. – Fred Foo May 02 '12 at 11:35
  • 2
    @larsmans: Your amendment needs a clarification: The version with `call(P,X)` is more general, so it is not the same effect. `P` does not need to be an atom! `P` can be for example `between(1,10)`. – false May 02 '12 at 11:55
  • @false: the OP didn't express a requirement qua currying, but yes, that's a nice extra. – Fred Foo May 02 '12 at 12:23
  • @larsmans: No curry involved! In FP this is partial application. – false May 02 '12 at 12:24