Forwarding this onto the list for Peter who’s having mail problems …
From: Peter Bacon D. [mailto:[email protected]]
Sent: Thursday, November 08, 2007 2:35 AM
To: John L. (DLR)
Subject: FW: Range#=== operator
I have noticed an interesting feature in the current snapshot. If you
test a numeric range against a non-numeric value, such as a string you
get a System.ArgumentException whereas other Ruby implentations return
false.
E.g.
IronRuby:
(1…5) === ‘x’
gives
System.ArgumentException: wrong number or type of arguments for `<=>’
CRuby:
(1…5) === ‘x’
gives
false
There are two interesting points here:
The first is that debugging code with lightweight code generation is
really difficult; tracking down what actually causes the exception to be
thrown is hidden by the DynamicSite layer. If you break on the
exception being thrown you have already lost the trace back to the
original problem. This is because the exception is not thrown directly
but via binding to an invocation site. Only by trawling through the
code and putting break points all over the place was I able to ascertain
that the problem is that when you apply the === operator to the Range
the begin and end attributes of Range have the <=> operator applied to
the argument (in this case you have something like FixNum <=>
MutableString) and the current system is unable to find a suitable
method to invoke. See RubyMethodGroupInfo.SetInvocationRuleInternal()
and RubyMethodGroupInfo.GetMethodCandidate(). I.E. There is no implicit
conversion between FixNum and MutableString. How do you guys debug
situations like this?
The second point is to do with this result itself. Are you aiming to
produce identical results to other Ruby implementations or are there
other criteria for correctness. Arguably the expression given above is
invalid as there is no correct type conversion. Equally false would
seem a reasonable result; certainly it is false that ‘x’ is in the range
of (1…5). If false is what you want, what is the accepted way of
dealing with the situation? Do you want to fiddle with the protocols
for type conversions? I imagine not. Is Range a specific case, in
which case you would code a specific version of <=> operator for it?
Interestingly the following code returns false as expected:
1 == ‘x’
gives
false
The difference here is that the == operator is being used directly to
test equality whereas early the <=> operator was being used to compare
the values previously.
Of interest, both IronRuby and CRuby throw argument exceptions/errors
for the following comparisons.
1 > ‘x’
and
1 < ‘x’
What are the correct semantics here? What do you think should be done
to deal with this discrepancy?
Regards,
Pet