{ |one, step, back| }

The Shape Example in Prolog

Contributed by Chris Rathman

Code for Prolog

File: shape.prolog

object(
   shape(X, Y), [
      (getx(X) :- X is X),

      (gety(Y) :- Y is Y),

      (moveto(_Shape, _X, _Y) :- fail),

      (rmoveto(_Shape, _X, _Y) :- fail),

      (draw :- fail)
   ]
).

File: rectangle.prolog

object(
   rectangle(X, Y, Width, Height), [
      (getwidth(W) :-
         W is Width),

      (getheight(H) :-
         H is Height),

      (setwidth(NewRectangle, NewWidth) :-
         NewRectangle = rectangle(X, Y, NewWidth, Height)),

      (setheight(NewRectangle, NewHeight) :-
         NewRectangle = rectangle(X, Y, Width, NewHeight)),

      (moveto(NewRectangle, NewX, NewY) :-
         NewRectangle = rectangle(NewX, NewY, Width, Height)),

      (rmoveto(NewRectangle, DeltaX, DeltaY) :-
         A is X + DeltaX,
         B is Y + DeltaY,
         NewRectangle = rectangle(A, B, Width, Height)),

      (draw :-
         write('Drawing a Rectangle at:('),
         write(X),
         write(','),
         write(Y),
         write('), width '),
         write(Width),
         write(', height '),
         write(Height),
         nl)
   ]
).

% set rectangle to inherit from shape class
isa(rectangle(X, Y, _WIDTH, _HEIGHT), shape(X, Y)).

File: circle.prolog

object(
   circle(X, Y, Radius), [
      (getradius(R) :-
         R is Radius),

      (setradius(NewCircle, NewRadius) :-
         NewCircle = circle(X, Y, NewRadius)),

      (moveto(NewCircle, NewX, NewY) :-
         NewCircle = circle(NewX, NewY, Radius)),

      (rmoveto(NewCircle, DeltaX, DeltaY) :-
         A is X + DeltaX,
         B is Y + DeltaY,
         NewCircle = circle(A, B, Radius)),

      (draw :-
         write('Drawing a Circle at:('),
         write(X),
         write(','),
         write(Y),
         write('), radius '),
         write(Radius),
         nl)
   ]
).

% set circle to inherit from shape class
isa(circle(X, Y, _RADIUS), shape(X, Y)).

File: polymorph.prolog

% iterate through a list and send message
drawloop([]) :- true.
drawloop([Shape|Tail]) :-
   Shape::draw,
   Shape::rmoveto(ShapeMoved, 100, 100),
   ShapeMoved::draw,
   drawloop(Tail).

polymorph :-
   % create a list containing various shape instances
   Scribble = [
      rectangle(10, 20, 5, 6),
      circle(15, 25, 8)],

   % iterate through the list and handle shapes polymorphically
   drawloop(Scribble),

   % handle rectangle and instance
   ARectangle = rectangle(0, 0, 15, 15),
   ARectangle::draw,
   ARectangle::setwidth(BRectangle, 30),
   BRectangle::draw.

File: Main.prolog

?- consult('/articles/poly/oop.html').
?- consult('/articles/poly/polymorph.html').
?- polymorph

Output

Drawing a Rectangle at:(10,20), width 5, height 6
Drawing a Rectangle at:(110,120), width 5, height 6
Drawing a Circle at:(15,25), radius 8
Drawing a Circle at:(115,125), radius 8
Drawing a Rectangle at:(0,0), width 15, height 15
Drawing a Rectangle at:(0,0), width 30, height 15

Yes