Search code examples
prologdeclarative-programming

Prolog: I am stuck in an imperative mindset


I am taking a class on programming paradigms. Currently we are learning Prolog, and I am stuck in a different paradigm. One of the functions I'm trying to convert from imperative is a relatively simple function.

foo(A,B,C)
    if(A > B) C is 1
    if(A < B) C is -1
    if(A = B) C is 0

I could do this in Prolog pretty easily.

foo(A,B,C) :- sub(A-B,C).

sub(E, C) :- E = 0, C is 0.
sub(E, C) :- E > 0, C is 1.
sub(E, C) :- E < 0, C is -1.

The problem is, I can only use one "is" in the entire predicate (can't define a smaller predicate that calls Is and calls that instead or anything), and I cannot use Prolog's if/else constructs. I cannot figure out how to think about this problem in a declarative manner.

I thought maybe I could do something like C is (A-B)/abs(A-B), but that breaks on A=B, and would require 2 "is" statements. I am just stuck.


Solution

  • In order to program declaratively, we have to think about what we are trying to declare and then we can describe it. To this end, I would try to write the predicate so that it expresses why the value of C alternates between three possible states depending on the relative sizes of A and B. Here's a predicate with the same form that you describe with foo:

    comparison(A, B, less)     :-  A < B.
    comparison(A, B, equal)    :-  A =:= B. %% =:=/2 is "True if expression A evaluates to a number equal to B".
    comparison(A, B, greater)  :-  A > B.
    

    You don't need the front-end predicate foo/3. You might read the lines thus: "The comparison of A and B is <Value> if A is <relation> with regard to B." This program consists of three rules that describe the rule comparison/3. The '3' indicates that this rule defines a relation between the 3 elements given to it as arguments.

    You can query this program:

    ?- comparison(1,3, X).
    X = less ;
    false.