atom feed201 messages in org.perl.perl5-portersfixing smartmatch just hard enough (a...
FromSent OnAttachments
Ricardo SignesAug 16, 2012 2:58 pm 
David GoldenAug 16, 2012 3:19 pm 
Robert SedlacekAug 16, 2012 3:43 pm 
Leon TimmermansAug 17, 2012 3:13 am 
Ed AvisAug 17, 2012 3:39 am 
Ricardo SignesAug 17, 2012 4:42 am 
Eirik Berg HanssenAug 17, 2012 5:06 am 
Ed AvisAug 17, 2012 5:20 am 
David GoldenAug 17, 2012 5:50 am 
AbigailAug 17, 2012 6:21 am 
Xiao YafengAug 17, 2012 6:31 am 
Brad BaxterAug 17, 2012 8:35 am 
Ricardo SignesAug 17, 2012 8:49 am 
Chris PratherAug 17, 2012 9:37 am 
Jesse LuehrsAug 17, 2012 5:42 pm 
Ricardo SignesAug 17, 2012 5:42 pm 
Jesse LuehrsAug 17, 2012 6:00 pm 
AbigailAug 18, 2012 5:28 am 
AbigailAug 18, 2012 5:35 am 
Eric BrineAug 18, 2012 6:51 am 
Father ChrysostomosAug 19, 2012 12:16 pm 
Damian ConwayAug 19, 2012 2:42 pm 
Father ChrysostomosAug 19, 2012 5:44 pm 
Johan VromansAug 20, 2012 5:44 am 
Jesse LuehrsAug 20, 2012 5:45 am 
David GoldenAug 20, 2012 10:08 am 
175 later messages
Subject:fixing smartmatch just hard enough (and when, too)
From:Ricardo Signes (
Date:Aug 16, 2012 2:58:16 pm

So, last year I said "we really ought to cut most of smart match away."

I've slept on it about 380 times, and I'm still for it. Here's the new plan:

## 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.

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.

## 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.


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.)

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.

## 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.