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

Re: fixing smartmatch just hard enough (and when, too)

Thread Previous | Thread Next
From:
Jesse Luehrs
Date:
August 17, 2012 18:00
Subject:
Re: fixing smartmatch just hard enough (and when, too)
Message ID:
20120818010025.GG11137@tozt.net
On Thu, Aug 16, 2012 at 05:58:16PM -0400, Ricardo Signes wrote:
> 
> So, last year I said "we really ought to cut most of smart match away."
> 
>   http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html
> 
> I've slept on it about 380 times, and I'm still for it.  Here's the new plan:

Yay!

> ## The New ~~ Operator
> 
>     $a      $b                  Meaning
>     ======= =======             ======================
>     Any     undef               ! defined $a
>     Any     ~~-overloaded       ~~ overloading is used
>     ~~-ol   Any                 ~~ overloading is used (reversed)
>     Any     CodeRef, &{}-ol     $b->($a)
>     Any     Regexp, qr-ol       $a =~ $b
>     Any     Simple              $a eq $b
>     Any     Any                 fatal
> 
> This is a nearly a subset of the current behavior.  Here are some major points:
> 
>   (1) This is ordered for the sake of knowing which overload to use first.
> 
>   (2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
>   used for stringwise equality.  I have not yet seen any convincing argument
>   that we can correctly intuit an eq/== behavior, so we pick one.
> 
>   Forcing numeric comparison can be done with things like the helpers found in
>   Smart::Match:  things to produce a CodeRef that has the correct behavior.
> 
>   (3) Container types (array, hash) are no longer treated specially.  They were
>   the most unintuitive case, and they get kicked out.  More on that later.

Mostly +1, but I'm still questionable about the ~~-ol/Any case. This
means that I still can't do "$thing ~~ sub { ... }" and get reliable and
predictable behavior. This may be less of an issue if that case was at
the bottom right above Any/Any, but I don't know if that would also make
it less useful for whatever you had in mind for it (where does autodie
use it?).

> This gets is back to what I've always said is the real power of ~~: a
> simple way to provide "a test" to run against a value, where the creator of the
> value know just how it will be used.  With one exception, we're dispatching
> entirely based on the rhs, and they're all obvious.
> 
> "Oh no!" you may cry, "What about $x~~@opts?  All I wanted was an `in`
> operator!"
> 
> ## Core Junctions
> 
> Well, that's why we have junctions.  Remember those?  Of course you do, they're
> fantastic.
> 
>   if ($x ~~ any( qw( John Paul Ringo ) )) {
>     tune_strings;
>   } else {
>     tap_drumps;
>   }
> 
> We already have very nice junctions in Perl6::Junction.  We bring that into the
> core (with a new name) and we get nice useful ways to put tests together.  We
> also get them anywhere else we want them.  For me, that's "all over the place."
> I bet it will be for lots of other people, too.

Definite +1.

> ## Backcompat and ~~
> 
> My anxiety over backward compatibility for ~~ is not gut-wrenching.  Still, it
> would be nice to do what we can.
> 
> After a lot of talk about making ~~ pluggable across different scopes, I think
> it's a non-starter.  It's just not the kind of thing we can plug this way,
> because of the way in which we expect it to be used.  If we expect users to
> pass a test from their code to some other code, they need to know how that code
> will use it.  It needs to be the same everywhere.
> 
> It would be nice to provide a best-effort backcompat with a deprecation warning
> when possible.  I'd like to know how good that effort can be.  Since the new
> table is in many ways a subset of the old one, I think it can be pretty good.
> 
>     As previously mentioned, the "switch" feature is considered highly
>     experimental; it is subject to change with little notice.  In
>     particular, both "given" and "when" have tricky behaviours that are
>     expected to change to become less tricky in the future.  Do not rely
>     upon their current (mis)implementations.
>     -- perlsyn
> 
> ## Fixing given and when
> 
> I think we already fixed given pretty hard.  I need to look at bit more at it,
> but let's take it as "fixed enough" for now.
> 
> when!
> 
> Oh, when, how you trouble me.
> 
> I propose that `when(X)` *always* means `$_ ~~ X`.  All of the special cases
> for parsing and interpreting the inside of when can go.  They can all be
> reduced to `when(sub{...})`.  I would also smile upon `when({...})` acting as a
> test block.  (Since you can't put a hashref on the rhs of ~~ anymore, there is
> no ambiguity.)

I like the concept, but "when ({ ... })" reads kind of weird. Everywhere
else in the language, ({ ... }) means a hashref - anything that means a
block has some kind of leading keyword inside any potential parentheses:
"(do { ... })", "(sub { ... })", etc. I think just leaving it as
"when (sub { ... })" is probably going to be the least confusing.

> The exceptions (from perlsyn's "Experimental Details on given and when") are:
> 
>   EXCEPTION             WAS                      IS NOW
>   1. subroutine call -- when (foo()))       --   when ({ foo() })
>   2. regex match     -- when ( /foo/ )      --   when (qr/foo/)
>                      -- when ( $_ !~ /foo/) --   when ( none( qr/foo/ ) )
>   3. smart match     -- when ($a ~~ $b)     --   when ({ $a ~~ $b })
>   4. comparison      -- when ($a lt $b)     --   when ({ $a lt $b })
>   5. some builtins   -- when (eof)          --   when ({ eof })
>   6. negation        -- when (! $x)         --   when ({ ! $x })
>   7. bool filetest   -- when (-r)           --   when ({ -r })
>   8. flip flops      -- when ($a .. $b)     --   when ({ $a .. $b })
>   9. conjunction     -- when ($a && $b)     --   when ( all( $a, $b ) )
>                                               or when ({ $a && $b })
>   0. disjunction     -- when ($a || $b)     --   when ( any( $a, $b ) )
>                                               or when ({ $a || $b })
> 
> Also, `when` should be valid inside an auto-topicalizing `while`, providing an
> implicit next, making its behavior more generic so that `when` can be used
> safely everywhere that it makes sense.

+1

> ## In Conclusion
> 
> I think this makes ~~ and given/when both totally predictable.  I've gone over
> this design quite a bit, and I think it turns these features from a liability
> to an asset.  I also think that we'll be able to eliminate quite a lot of
> documentation, which I take as a very good sign.  (A lot of that documentation
> includes things like "this part is really hard to understand.")
> 
> When ~~ works like this, I will use it all the time.

-doy

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