Equality of Procedures
What does it mean when we say two objects are equal? It could mean
that both objects point to the
same location in memory or it could mean that both objects have the
same structure.
In Motto, the eq procedure
defines the first type of equality
and equal defines the second:
> "hello" def a > a def b > a b eq .s .c #t > a b equal .s .c #t > "hello" def c > a c eq .s .c #f > a c equal .s .c #t
Here both a and b point to the same location in memory. So eq
return true.
c, though structurally similar to a, points to a different
location. So a c equal return
true and a c eq return false.
As procedures are first-class objects in Motto, they too can be compared for equality:
> [2 *] def double1 > value double1 def double2 > value double1 value double2 eq .s .c #t > [2 *] def double3 > value double1 value double3 eq .s .c #f
(The compiler definition value is used to put the procedure object
on the stack without
executing it. This is similar to the #' operator in Common Lisp.).
As we can see, eq is consistent in its behaviour. What about
equal? Let us try equal
with the above procedures. It should return true for all comparisons
as all the
three procedures have the same internal structure:
> value double1 value double2 equal .s .c #t > value double1 value double3 equal .s .c #t
If we compare double1 to a procedure with the same behaviour but
with slight structural changes,
equal will return false:
> [def a 2 a *] def double4 > 10 double1 10 double4 .s .c 20 20 > value double1 value double4 equal .s .c #f
In a strict mathematical sense two functions are equal if for all possible inputs they produce the same output. This definition also assumes that the functions do not cause any side effects. It is easy to define a predicate for comparing two procedures in the context of a particular input:
> [def proc1 def proc2 [proc1] reduce-intact def result1 [proc2] reduce-intact def result2 .c ;; Clearing the stack is optional. result1 result2 equal] def equal-p > 10 value double1 value double4 equal-p .s .c > #t
equal-p take the definitions of two procedures and applies them to
the values on the stack.
If the results produced are the same, equal-p will return true.
The test should
be repeated with all possible inputs (if possible) to establish that
the procedures are equal indeed.
A few more usage samples of equal-p:
> [*] def mult1 > [def n def e [n 0 gt] [e n 1 - set n] loop] def replicate > [replicate [+] reduce] def mult2 > 2 3 mult1 .s .c 6 > 2 3 mult2 .s .c 12 > 2 3 value mult1 value mult2 equal-p .s .c #t > [+] def add1 > 2 3 add1 .s .c 5 > 2 3 value mult1 value add1 equal-p .s .c #f