develooper Front page | perl.perl5.porters | Postings from August 2017

Re: Revisiting smart match

Thread Previous | Thread Next
From:
Zefram
Date:
August 1, 2017 16:48
Subject:
Re: Revisiting smart match
Message ID:
20170801164828.GY9383@fysh.org
Sawyer X wrote:
>* RHS overloading should stay

RHS overloading should be the main way of determining what kind of
match to perform.  The list of matching rules needs to be very short:
overloading plus up to about three rules for more mundane RHS types.

>* LHS overloading breaks a faulty autodie API

My recollection is that it's *removing* LHS overloading that would break
a promoted API.  Regardless, LHS overloading needs to die, because its
behaviour is too surprising: it breaks the usability of any RHS type
against which LHS overloading could apply, but its existence doesn't
actually dissuade people from using such RHS types, so it just creates
bugs.  The type of match to perform needs to be fully determined by
the RHS.

Going even further, for comprehensibility we want the matching rules to
be fully disjoint.  It's no good having one rule for numbers on the RHS
and another for strings, because too many things are both.  It's even
problematic to have a rule for coderefs on the RHS, because a sub might
be blessed into a class with smartmatch overloading.  The rule could
be restricted to references to unblessed subs, but even that's a bit
confusing, as it'll lead to people assuming that any sub can be used as
a smartmatch object with semantics involving calling it.  And then what
about objects with a calling overload?  And so on.

Almost every proposed matching rule runs into some form of the above
confusion, because of Perl's pervasive use of "what type do you *want*
me to be?" semantics.  This is why the list of matching rules needs to
be very short.

So, my suggestion for the ruleset:

    0: RHS overloading
    1: undef on the RHS: !defined($lhs)
    2 (optional): plain string (defined, non-glob, non-regexp, non-ref
       scalar) on the RHS: $lhs eq $rhs
    3: anything else: croak "invalid smartmatcher"

The Regexp class should overload smartmatch to perform a regexp match.
MooseX::Types metaobjects should overload smartmatch to perform a type
membership test.

Also, there's a distinction to be made between the runtime semantics
of smartmatch and the parsing of the operator.  The above rules are
runtime ones.  Currently, the smartmatch operator modifies things a
bit: for example, an array (as in "@foo ~~ $bar" or "$foo ~~ @bar")
gets implicitly enreferenced.  That's not a great rule.  I think it
would be better for ~~ to just apply scalar context to both operands.

There's further complication about the when() construct, which is
inconsistent in how it uses the result of evaluating the expression
inside the parens.  Sometimes it treats the result as a truth value,
directly governing whether to execute its block, and sometimes it treats
the result as a smartmatcher, against which to implicitly match $_.
The decision is based on the top-level operator of the expression.
This is just confusing and should be ditched.  If you want smartmatching
with no extra typing, change the parens: when() can treat the expression
result as a truth value while when[] treats it as a smartmatcher.
We could add if[] while we're at it.

-zefram

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About