buffoonUser
buffoonUser

Reputation: 1

How to write Prolog - defining basic operators?

I'm fairly new to Prolog and I want to create a predicate that behaves as follows

calculate(add(1, sub(4,1)),Result).
Result = 4.

This is doing: 1 + (4 - 1) = 4

I'm familiar with predicates but I don't know where to start in terms of being able to write an add//2 predicate/operator.

Any help or suggestions are much appreciated.

Upvotes: 0

Views: 67

Answers (2)

Paulo Moura
Paulo Moura

Reputation: 18663

With a small change on the representation of numbers, we can write a nice solution. The change is to represent the number N as number(N)` to avoid a defaulty representation (meaning, "it's a number by default if it's not an operation):

calculate(number(Number), Number).
calculate(add(Expression1, Expression2), Result) :-
    calculate(Expression1, Result1),
    calculate(Expression2, Result2),
    Result is Result1 + Result2.
calculate(sub(Expression1, Expression2), Result) :-
    calculate(Expression1, Result1),
    calculate(Expression2, Result2),
    Result is Result1 - Result2.

Sample call:

| ?- calculate(add(number(1), sub(number(4), number(1))), Result).

Result = 4
yes

Upvotes: 2

David Tonhofer
David Tonhofer

Reputation: 15316

You are still thinking in terms of functions

z = f(x,y): "f(x,y) returns (is replaced by/ is reduced to) value z ..."

Predicates relate values to other values:

p_f(x,y,z): "predicate p_ makes a relation/connection/links values (x,y,z) such that z = f(x,y)"

So to pipeline evaluation (mathematical notation (g°f)(x,y) )

g(f(x,y))

you have to write (not respecting the Prolog convention that 'variables' are written in uppercase here):

p_f(x,y,a),p_g(a,b)

And think in terms of information flowing into this expression through p_f(x,y,_), getting transferred to p_g/2 via p_f(_,_,a), p_g(a,_) and flowing out of the expression via p_g(a,b).

And p_f/3 or p_g/2 will fail (return false, not in any of their arguments, but as a whole) if they are unable to relate their arguments and there will be no result.

Using predicates has the advantage that for p_f(x,y) you can request x if y is known, y if x is known, or pairs of valid (x,y) (as long as that is computationally possible and the predicate has been correctly coded). Or for a predicate add/3:

  • add(2,3,X) -> X = 5
  • add(2,3,5) -> true
  • add(X,3,5) -> X = 2
  • add(1,3,5) -> false
  • add(X,Y,5) -> X = 2, Y = 3; X = 3, Y = 2; ... ad infinitum
  • add(X,Y,Z) -> same as above only even more unrestrained

See also: Prolog ~ Splitting a number into a list

Upvotes: 2

Related Questions