develooper Front page | perl.perl5.porters | Postings from March 2009

The smartmatch plan

Thread Next
From:
Rafael Garcia-Suarez
Date:
March 5, 2009 00:53
Subject:
The smartmatch plan
Message ID:
b77c1dce0903050053s4cd39878x664e25d5c9884c5a@mail.gmail.com
I just pushed a new branch "smartmatch" intended to gather the changes
to the semantics of ~~ and when() for 5.10.1 onwards. See
<http://perl5.git.perl.org/perl.git/log/refs/heads/smartmatch>.

Several problems were identified with 5.10.0's smart match; some of
which are already fixed in blead (e.g. the behaviour with objects that
don't overload ~~), some aren't. So I'm trying to build a smarter
smart match, more useful, ans also more in line with Perl 6 (but not
identical, since Perl 5 has less types, has no junctions and has no
hyperoperators).

The new smart match dispatch table is in as :

commit 202d7cbdf6efc5f9c138c4460dce6d5b72603d2b
Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com>
Date:   Wed Mar 4 21:14:10 2009 +0100

    The new smart match dispatch table for 5.10.1 onwards

    This /does/ break backwards compatibility. Changes to come are:

    - ~~ is no longer commutative. Dispatch is now done based on the
      (run-time) type of the right side argument.
    - The right side can be a ".." range, which will be treated specially,
      and no longer as a boolean operator (as in scalar context).
    - when() should treat "..." as a boolean operator.
    - Coderefs with an empty prototype are no longer special.
    - Any ~~ Array distributes the smart match test.
    - Comparing two coderefs is no longer a special case and does not
      perform referential equality. (Use \&foo ~~ "".\&bar for that.)

    This patch also documents that ~~ won't work on objects that don't
    overload it, except in the expression $object ~~ undef.

 pod/perlsyn.pod |   70 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 44 insertions(+), 26 deletions(-)

That's a lot of breaking backwards compatibility, but it's better to
break it now than to be cursed with a bad ~~ for the rest of Perl 5's
lifetime. Moreover, you'll notice that most common cases will not be
changed, or changed in dwimmy ways.

Comments are welcome, of course. (Esp. from Dave, the maint pumpking.)
Some more notes besides what's in the log message:

* Perl 6's ~~ is also non-commutative.

* I'm going to introduce the syntax $num ~~ 10..20. (mostly useful in
when() I expect)

* Entries for Code() were removed for the following reasons :
1. For a constant sub FOO :
1a. \&FOO is not useful
1b. FOO is constant folded, so the ~~ op will see the constant's value
2. For a non constant sub phase_of_moon() :
2a. $foo ~~ \&phase_of_moon will depend only on the phase of the moon,
exactly like the "Any ~~ Code" entry that calls $b->($a)
2b. We don't need Code() lower in the precende table if we dispatch
from the type of $b first

* Distributing the smart match test in arrays is _not_ what Perl 6
does, but at least it will enable us to get away correctly with mixed
expressions like $scalar ~~ ["string",42] (that currently warn.)

Other commits of interest:

commit f92e1a16ee2379315520131bbe3465eb837abfa3
Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com>
Date:   Wed Mar 4 19:33:31 2009 +0100

    Make // behave like || in when clauses

    (plus minor documentation updates about "when")

Remarks: when() does not automatically imply a smart match. The cases
where it does not are described in perlsyn: basically it's when it's
passed a boolean expression, like in C<when(/foo/ && $_ gt "bar")>. I
added // to the list of operators that construct a boolean expression
from the point of view of when().

That also implies that when(@foo && @bar) is not going to imply a
smart match -- because it's a boolean expression. Hence that other
commit:

commit aa2407c5c40c18416d30710d13b3c1423d0bb212
Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com>
Date:   Wed Mar 4 20:40:59 2009 +0100

    Remove TODO tests about && in when() clauses

    when() actually behaves as documented in perlsyn. It treats "E1 && E2"
    expressions as booleans only if E1 is boolean, and if not, it does the
    equivalent of the smart match expression "$_ ~~ (E1 && E2)". As long as
    the ~~ operator is not expected to distribute boolean expressions found
    on its right side, the current behaviour of perl is correct.

    So, should we expect ~~ to distribute boolean expressions ? Given that
    this would be rather complex to implement and test correctly with
    complex expressions, given that we don't expect =~ to distribute either,
    and given that when() is already quite smart regarding boolean
    operators, I see no motivation for that feature.

    This allows to close bug #50538 as "won't fix".

 t/op/switch.t |   65 +--------------------------------------------------------

I'll now work on the code and tests in the hope to Just Getting Things
Done for 5.10.1.

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