On Thu, Aug 23, 2012 at 7:53 PM, Damian Conway <damian@conway.org> wrote: > The argument for the ordering I've proposed to prefer the RHS object's > ~~-overloading is that every other (non-overloaded) case in the > smartmatch table dispatches solely on the RHS type. So, for consistency > and predictability of *use*, I believe overloaded ~~ should favour the > RHS object's overloading (if any) and fallback to the LHS object's > overloading only if necessary. > But the semantics of LHS and RHS are different because smartmatch is non-commutative. For a LHS object, the only semantically correct thing to do is to transform one's own value and smartmatch it against the RHS comparator (or possibly a suitable transformation of it [1]). For a RHS object, there is no clear meaning for what it means to match, therefore it's free to do any sort of comparison to the LHS value, which may or may not involve smartmatching and may or may not invoke the smartmatch overload on the LHS. Let's take as an example an Error class whose objects have both a string and a numerical value. (Let's assume that it's not *actually* a dualvar, since that's a different Pandora's box.) The class overloads q{0+} and q{""}. The author overloads ~~ to always smartmatch as a number. Imagine another class, which implements a length smartmatch, meaning that ~~ is overridden to check if the length of the LHS is greater than some limit set in the constructor. E.g. <<$max_length = Length::Max->(8) >> Then consider: $error ~~ $max_length If the LHS overload is processed first, the numeric value gets smartmatched against the RHS, which does a length check of the numeric value against the limit and we effectively get this: length($error->number) > $limit If the RHS overload is processed first, the LHS gets checked for length, which triggers stringification of the LHS (and thus the q{""} overload) and we effectively get this: length($error->string) > $limit Avoiding that requires the RHS overload to implement its logic in a subroutine and smartmatch the LHS against the subroutine (or something equally clever), thus triggering LHS smartmatch logic and we effectively get this: sub { length(shift) > $limit } -> ( $error->number ) Whatever it does, it *must* give the LHS a chance to trigger its smartmatch overloading. (Requiring a subroutine is also inefficient.) Thus, since a proper RHS overload must trigger a LHS overload anyway, then the LHS override should trigger first, which simplifies the operation of RHS overloading. David [1] The "problem" with LHS overloading is that the RHS gets passed in a variable and if we can't tell whether that was originally a number or a string, we don't know whether to smartmatch a scalar RHS as 0+$rhs or "$rhs". But if the LHS knows it should match as string or number, then it can force that onto a simple RHS scalar value and wind up doing the right thing.Thread Previous | Thread Next