
doy at tozt
Aug 17, 2012, 6:00 PM
Post #17 of 140
(186 views)
Permalink
|
|
Re: fixing smartmatch just hard enough (and when, too)
[In reply to]
|
|
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
|