简体   繁体   中英

How to call a predicate from another predicate in Prolog?

So I just started Prolog and I was wondering two things:

1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?

2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:

car([3,4,5,5], H). would return H = 3

cdr([3,4,5,5],L). would return L = [4,5,5]

and what I am asking is how can I do this:

car(cdr[3,4,5,5]))

??

As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions . Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.

In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo . You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:

remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).

Or something like that.

A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.

Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:

X is Y / gcd(Z, 4).

Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2 , sin/1 , etc. You can look them up in the documentation.

Arithmetic comparative operators function this way as well (using =:=/2 , >/2 , </2 , etc with numeric expressions). So if you say:

X < Y + Z

The Prolog will consider numerical evaluation of these arguments and then compare them.

So having said all that, Prolog does allow embedding of term structures. You could have something like:

car(cdr([1,2,3]))

as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:

car([H|_], H).
cdr([_|T], T).

proc_list(car(X), Result) :-
    proc_list(X, R1),
    car(R1, Result), !.
proc_list(cdr(X), Result) :-
    proc_list(X, R1),
    cdr(R1, Result), !.
proc_list(X, X).

The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.

Then:

| ?- proc_list(car(cdr([1,2,3])), R).

R = 2

yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).

R = 3

yes
| ?-

Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr . It can also be made more general using =.. and call , etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:

proc_list(Term, Result) :-
    Term =.. [Proc, X],               % Assumes terms have just one argument
    member(Proc, [car, cdr]),         % True only on recognized terms
    proc_list(X, R1),                 % Recursively process embedded term
    ProcCall =.. [Proc, R1, Result],  % Construct a calling term with Result
    call(ProcCall), !.
proc_list(X, X).

This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.

Prolog has a really different attitude to computing...

You don't define functions , but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).

car([H|_],H).
cdr([_|T],T).

car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).

but since lists' syntax is a core part of the language, a better definition could be

car_of_cdr([_,X|_], X).

Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...

:- use_module(support).

This means the module will use predicates written in other modules.

<module_name>:<predicate_name>(<atoms / Variables>).

This way you can call a predicate in another module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM