On Wed, Oct 07, 2015 at 07:48:34AM +1100, Tony Cook wrote: > when { FOO } { ... } # braces not parentheses Ah sorry, completely failed to spot the new brace syntax! Anyway, I've been mulling this over, and I've come up with a radical new proposal for smartmatch. I will now expect this to be shot down in flames as people point out basic flaws I've overlooked. What I think we should do: 1. Get rid of the ~~ operator altogether, plus '~~' overloading. 2. Make when's behaviour entirely dependent on the *compile-time* class of of its arg. In particular, make 'when (FOO)' have exactly the following behaviours: FOO condition evaluates to -------------- ---------------------- literal undef !defined($_) numeric const $_ == FOO literal pattern $_ ~= FOO all else $_ eq FOO 3. when { FOO } has condition FOO. For example: use constant ANS => 42; use constant ME => "davem"; when (undef) # equivalent to when { !defined($_) } when (42) # equivalent to when { $_ == 42 } when (ANS) # equivalent to when { $_ == 42 } when (42.1) # equivalent to when { $_ == 42.1 } when ("42") # equivalent to when { $_ eq "42" } when ("davem") # equivalent to when { $_ eq "davem" } when (ME) # equivalent to when { $_ eq "davem" } when ($x) # equivalent to when { $_ eq $x } Rationale: I think 95% of what people actually *want* a smartmatch system for is so that they can write code of one of these three forms: given ($index) { when (undef) {...} when (0) {...} when (1) {...} when (INDEX_MAX) {...} } given ($string) { when (undef) {...} when ("foo") {...} when ("bar") {...} when (BAZ) {...} } given ($string) { when (undef) {...} when (/foo/) {...} when (/bar/) {...} } Since perl is about making easy things easy, I think that achieving the above forms should be our basic goal. If we don't do that, we've failed. Of course perl likes to make hard things possible too, but I think that is an auxiliary consideration for now. Why get rid of the smartmatch operator? I've never really seen the point of it, apart from being something that exposes the underlying mechanism of when(), c.f. readline() for <>. If we do keep it, then it should have exactly the same semantics as I've described above for when(). Then the condition for when(FOO) would be defined as always exactly equivalent to when { $_ ~~ expr }. Note that my proposal makes when/smartmatch behaviour entirely dependent on the *compile-time* nature of the RHS. There is no polymorphic dispatch of any kind. In particular for when($x) it makes no difference if $x is a qr// or an object or a code ref or is undef: the condition is always ($_ eq $x). I think the cases where someone has a var $x which could be any of the above and want perl to dispatch in varied and interesting ways based on its runtime type are are fairly rare, and can always be coded manually when really needed, e.g.: given (ref $x) { when (/CODE/) { $x->($_) } when (/REGEX/) { $_ =~ $x } } I think this removes most of the cognitive overhead of the smartmatch system and makes it genuinely useful. The only slightly tricky bit is how it decides whether to use == or eq. The internal compiler rules for given(FOO) would be in its entirety: Examine the child of op the when(). If it is: OP_UNDEF: compile to !defined($_) OP_CONST: if the const's value is IOK or NOK, compile as $_ == CONST OP_MATCH: $_ =~ FOO else: compile as $_ eq FOO From the user's perpective, the rule would be: if its a literal int or float like 1 or 1.1, use ==. If it's a constant, and the constant's value was a literal int/float or has been used as an int/float, use' ==', else use 'eq'. So these would have their obvious interpretations; use constant LIFE => 42; use constant FOO => "bar"; while these would be the tricky edge cases where the user might need to read the docs carefully: use constant ERR => $!; BEGIN { my $n = "42"; $n += 0 } use constant LIFE => $n; Finally, if the smartmatch operator were freed up, then maybe we could repurpose it as some sort of recursive grep operator that searches though nested arrays and hashes for something. That's just a vague thought though. Finally finally, regardless of what semantics we finally choose, perhaps we should use a new feature name for all this, e.g. use feature 'switch2'; with 'switch' becoming an error, so that existing code will noisily fail to compile rather than failing mysteriously on subtle changes to semantics. -- Little fly, thy summer's play my thoughtless hand has terminated with extreme prejudice. (with apologies to William Blake)Thread Previous | Thread Next