Some observations and questions on Joy equivalence

Nick Forde — 2002-11-30 18:57:29

Is the definition of equivalence in Joy documented anywhere? I haven't
been able to find any references to it in Manfred's papers. Whilst
using the 'in' and 'has' atoms I got some unexpected results which
prompted me to look at their implementation along with '=' and
'equals'. I have found some inconsistencies but need to know their
intended behaviour before I can resolve the problems.

The Joy interpreter implements '=' and 'equals' something like the
following:

(1) `atom: '=' function: eql_() args: x1, x2
----------------------------------------------
PROCEDURE eql_
IF (type(x1) == boolean) OR (type(x1) == char) OR (type(x1) == integer))
IF (floating point comparison possible)
RETURN result of floating point comparison
ELSE
RETURN result of integer comparison
IF (type(x1) == float)
IF (floating point comparison possible)
RETURN result of floating point comparison
ELSE
RETURN false
IF (type(x1) == set)
RETURN result of bitwise comparison
IF (type(x1) == list)
RETURN error
ELSE
IF (type(y1) == list)
RETURN error
ELSE
RETURN result of string comparison
ENDPROC

(2) atom: 'equal' function: equal_() args: x1, x2
---------------------------------------------------
PROCEDURE equal_
IF (type(x1) == boolean) OR (type(x1) == char) OR (type(x1) == integer))
IF NOT (type(x2) == boolean) OR (type(x2) == char) OR (type(x2) == integer))
RETURN false
ELSE
RETURN result of integer comparison
IF (type(x1) == set)
IF (type(x2) != set)
RETURN false
ELSE
RETURN result of integer comparison
IF (type(x1) == list)
IF (type(x2) != list)
RETURN false
ELSE
RETURN result of recursing using equal_list_aux procedure
ELSE
RETURN result of string comparison
ENDPROC

Of these atoms I assume that the intention is '=' should be the
coarsest or least discriminating of the two. It doesn't enforce type
equivalence and will not do recursive comparison over lists. The
current implementation does, however, have some problems:

[] 0 = --> true
0 [] = --> error
"f" "r" fopen stdin = --> true
stdin stdout = --> true

i.e. the list type checking isn't quite strict enough and there isn't
any support for file types.

The 'equal' atom takes a more thorough approach by insisting largely
on type equivalence (except with boolean, chars and integers). It will
also allow list comparisons. It too has some problems:

"f" "r" fopen stdin equal --> true
stdin stdout equal --> true
1.0 0.1 equal --> true

i.e. there is no file or float type support.

The 'in' and 'has' atoms use the following implementation:

(3) atom: 'in/has' function: in_()/has_() args: a1, x2
--------------------------------------------------------
PROCEDURE in_
IF (type(a1) == set)
RETURN result of bitwise and with x2
IF (type(a1) == string)
FOREACH character in a1
IF (match found)
RETURN true
ELSE
RETURN false
IF (type(a1) == list)
FOREACH element in list
IF (integer match found)
RETURN true
ELSE
RETURN false
ELSE
RETURN error
ENDPROC

As you can see from the above the equality test here is similar,
although not the same, as that implemented by '='. For example:

["a" "b" "c"] "a" has --> false

I suggest that the best solution to this problem is that 'in' and
'has' should be using the same code as '=' or 'equal'. So, what is the
desired behaviour of these atoms?

Also, does it make sense in Joy to add another equality atom similar
to 'eq?' in scheme which does pointer comparisons? I imagine that this
would be of very limited applicability due to the way data is accessed
in Joy through stack manipulation, but I'm not sure. Perhaps a
stricter test which insists on equal types in all cases would be
useful?

Regards,

Nick.

Manfred von Thun — 2002-12-02 06:24:13

On Sat, 30 Nov 2002, Nick Forde wrote:

> Is the definition of equivalence in Joy documented anywhere? I haven't
> been able to find any references to it in Manfred's papers. Whilst
> using the 'in' and 'has' atoms I got some unexpected results which
> prompted me to look at their implementation along with '=' and
> 'equals'. I have found some inconsistencies but need to know their
> intended behaviour before I can resolve the problems.

It is years since I wrote those parts of the implementation,
and presumably my original intentions are not all that relevant
any more. Suffice it to say that for '=' and 'equals' I must
have had Scheme's 'eq', 'eql' and 'equal' in mind.
Also, much the same problems will be present with the comparators
such as < <= > >=
What a mess. Sorry.

> The Joy interpreter implements '=' and 'equals' something like the
> following:

[ ... pseudo code for '=' and 'equals' ]

> Of these atoms I assume that the intention is '=' should be the
> coarsest or least discriminating of the two. It doesn't enforce type
> equivalence and will not do recursive comparison over lists.

Something like that, yes. But that may or may not be a good idea.
Unfortunately I do not have my Scheme SICP with me here, which
could provide some ideas. I am very happy to hear your suggestions
about this.

> The
> current implementation does, however, have some problems:
>
> [] 0 = --> true
> 0 [] = --> error
> "f" "r" fopen stdin = --> true
> stdin stdout = --> true
>
> i.e. the list type checking isn't quite strict enough and there isn't
> any support for file types.

AAARRRGH ! You are right, of course.

> The 'equal' atom takes a more thorough approach by insisting largely
> on type equivalence (except with boolean, chars and integers). It will
> also allow list comparisons. It too has some problems:
>
> "f" "r" fopen stdin equal --> true
> stdin stdout equal --> true
> 1.0 0.1 equal --> true
>
> i.e. there is no file or float type support.

More AAARGH !

> The 'in' and 'has' atoms use the following implementation:

[ ... pseudocode for in/has ]

> As you can see from the above the equality test here is similar,
> although not the same, as that implemented by '='. For example:
>
> ["a" "b" "c"] "a" has --> false
>
> I suggest that the best solution to this problem is that 'in' and
> 'has' should be using the same code as '=' or 'equal'.

I quite agree. That would be the most consistent solution. But it
is not entirely clear to me which choice should be made.

There is one other possibility: introduce two combinators 'c-in'
and 'c-has' which take an additional quotation parameter that
computes a relation, such as any of the following:
obviously: [=] [equals] [<] [>] [<=] [=>]
but also : [in] [has] [divides] ... [any-relation!]
These two combinators might be quite useful. But of course things
like '[=] c-has' or '[equals] c-has' would be less efficient than
'has'. So I think one would want to have 'in' and 'has' with
the relational parameter built in.

> So, what is the
> desired behaviour of these atoms?

I would be guided by Scheme or Lisp, but both are at home.
But more than that I would be happy to go by your suggestions
and what others in the group might say.

> Also, does it make sense in Joy to add another equality atom similar
> to 'eq?' in scheme which does pointer comparisons? I imagine that this
> would be of very limited applicability due to the way data is accessed
> in Joy through stack manipulation, but I'm not sure.

Yes, I do remember thinking about this explicitly. I decided against
it because I thought it does not belong into a pure language.

> Perhaps a
> stricter test which insists on equal types in all cases would be
> useful?

Yes, '[] 0 =' should really give an error. Maybe I had in mind that
the 'null' predicate does not distinguish, so '=' should not either.

Thanks a lot for that.

- Manfred

> Regards,
>
> Nick.