Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.99k stars 559 forks source link

Many, many given bugs #11360

Open p5pRT opened 13 years ago

p5pRT commented 13 years ago

Migrated from rt.perl.org#90886 (status was 'open')

Searchable as RT90886$

p5pRT commented 13 years ago

From tchrist@perl.com

I had intended to remove the "emulating case structures" bits from the documenation in favor of the switch feature. I have now decided against doing so. That's because the old case-emulation stuff is understandable\, reliable\, and predictable\, whereas the new bits are none of those things.

These first two statements about it each put the lie to the other​:

  | Most of the power comes from implicit smart matching​:   | when($foo)   | is exactly equivalent to   | when($_ ~~ $foo)

vs​:

  | Most of the time\, "when(EXPR)" is treated as an implicit   | smart match of $_\, i.e. "$_ ~~ EXPR".

Those cannot both be true. And they are not. The first is lying. The second is insufficient\, even with elaboration\, to explain what is really going on.

Here is the elaboration\, which I feel does more harm than help​:

  | But when EXPR is one of the below exceptional cases\, it is   | used directly as a boolean​:   |   | * a subroutine or method call

Does that includes builtins\, or just user-defined functions? Is something like scalar() a subroutine call? Is an eval("")? How about eval{} or do{}? Is not() a subroutine call? It certainly appears to be\, since it can be imported and has a prototype of ($). That makes it a subroutine call in my book.

  | * a regular expression match\, i.e. "/REGEX/" or "$foo =~ /REGEX/"\, or   | a negated regular expression match ("!/REGEX/" or "$foo !~   | /REGEX/").

What about substitution and transliteration\, whether with or without "=~"? Are those included? Why or why not? What happens if you use "$foo =~ EXPR" insteads of "$foo =~ /pat/"? Does that count\, too? And what is $foo? Does it have to be a simple\, unsubscripted scalar variable\, or is it also a scalar EXPR? Can you use "EXPR =~ /pat/" and "EXPR =~ EXPR" and "EXPR != EXPR"?

  | * a comparison such as "$_ \< 10" or "$x eq "abc"" (or of course "$_ ~~   | $c")

Whoa there. Define all such comparision operators to which this applies. Precisely where in the source code is implemented?
And where is it documented?  
  | * "defined(...)"\, "exists(...)"\, or "eof(...)"

AHAH!! It is *NOT* builtins! What a wonderful insanity.
How can one possibly know? Where exactly is this 3-times-nested exception list of exceptional exceptions precisely defined?

Enquiring minds want to know.  
  | * a negated expression "!(...)" or "not (...)"\, or a logical   | exclusive-or "(...) xor (...)".

Oh\, for goodness sake. What the heck is that about? Is it only a logical negated expression\, or is it also a numeric one and a bitwise one? Can I use "~(...)"? What about "(...) ^ (...)"? Why or why not? Remember those can be strings\, too. And that bitwise operators are often required in case statements in C\, so why not here?

  | * a filetest operator\, with the exception of "-s"\, "-M"\, "-A"\, and   | "-C"\, that return numerical values\, not boolean ones.

Say what? They all return numeric values\, not boolean ones. Witness​:

  % perl -wE 'printf "%d\n"\, -d "/"'   1   % perl -wE 'printf "%d\n"\, -f "/"'   0

I got no warning\, and therefore those are numeric results.

If -s is exempted\, why is its complementary operator\, -z\, not exempt?

How the devil is someone supposed to know these? How can you dump out a when clause to show what it is *REALLY* doing?????

  | * the ".." and "..." flip-flop operators.

I believe that means an EXPR involving the two scalar flip-flop operators\, not just the operator itself\, because I don't know how you would use that. And that it does not extend to thing with the ".." and "..." operators. Or does it? Can you say

  when(1..10)

Is that really

  when ( ($. == 1) .. ($. == 10) )

or is that really

  when ([ 1 .. 10 ])

or is it

  when (scalar(() = (1 .. 10)))

And why? How can you tell?

  | In those cases the value of EXPR is used directly as a boolean.

Having been evaluated in scalar context\, presumably\, just like 99% of the EXPRs in the perldoc. Is this correct\, or not?

  | Furthermore\, Perl inspects the operands of the binary boolean operators   | to decide whether to use smart matching for each one by applying the   | above test to the operands​:   |   | * If EXPR is "... && ..." or "... and ..."\, the test is applied   | recursively to both operands. If *both* operands pass the test\, then   | the expression is treated as boolean; otherwise\, smart matching is   | used.

Hold on -- *RECURSIVELY*? Can you show me a couple of examples of bhot cases; that is\, a couple where it does apply when this rule is applied recursively\, and a couple where it does not? And does the recursion apply to the entire thing\, or is it only about logical conjunctions? Are these rules applied in a particular order? Why are only short-circuiting conjunctions special\, and not non-short-circuiting one (&)?

  | * If EXPR is "... || ..."\, "... // ..." or "... or ..."\, the test is   | applied recursively to the first operand (which may be a   | higher-precedence AND operator\, for example). If the first operand   | is to use smart matching\, then both operands will do so; if it is   | not\, then the second argument will not be either.

Wait a second\, are you saying that in the disjunctive case\, unlike the conjunctive case\, it does not matter whether the right operand looks like it "should" use smartmatching\, you just go ahead and do it anyway no matter what? And that you do not do so in the conjunctive case?

You have to be kidding me\, right?

I again want to know about the non-short circuiting disjunctives\, | and ^.

  | These rules look complicated\,

That's because they *are* complicated. Hellishly\, punishingly complicated.

  | but usually they will do what you want.

No\, they usually do *not*. That's my whole problem. I keep having situations where THEY DO NOT DO WHAT I WANT\, and I'll be damned if I can figure out why\, or even what they're really doing.

I'll skip the remainder\, which is filled with errors both of omission and of commission. Plus a lot of it doesn't even belong here in the first place​: once corrected\, it needs to go in perlop.

All the above\, and many more besides\, are to be considered bugs in given.

--tom

  "GIVEN DELENDA EST"

p5pRT commented 13 years ago

From @cpansprout

On Tue May 17 09​:29​:14 2011\, tom christiansen wrote​:

But when EXPR is one of the below exceptional cases\, it is used directly as a boolean​:
* a subroutine or method call

Does that includes builtins\, or just user-defined functions? Is something like scalar() a subroutine call? Is an eval("")? How about eval{} or do{}? Is not() a subroutine call? It certainly appears to be\, since it can be imported and has a prototype of ($). That makes it a subroutine call in my book.

This means that core overrides no longer work. :-(

  when(chr 3) { }

is not the same as

  use subs 'chr';   sub chr($) { CORE​::chr shift }   when(chr 3) { }

Furthermore\, Perl inspects the operands of the binary boolean operators to decide whether to use smart matching for each one by applying the above test to the operands​:
* If EXPR is "... && ..." or "... and ..."\, the test is applied
recursively to both operands. If *both* operands pass the

test\, then | the expression is treated as boolean; otherwise\, smart matching is | used.

I really thought that meant when("foo" || "bar") would mean when($_ ~~ "foo" || $_ ~~ "bar").

But now I’ve found out that it means when($_ ~~ ("foo" || "bar")).

| but usually they will do what you want.

No\, they usually do *not*. That's my whole problem.

One of the examples given right after that\, of how they will do what you want\, is​:

  when ([qw(foo bar)] && /baz/) { ... }

which uses smart-matching. That gives this​:

$ perl5.14.0 -lE' given("foo"){ print "match" when ["foo"\,"bar"] }' match $ perl5.14.0 -lE' given("foo"){ print "match" when ["foo"\,"bar"] && /foo/ }' $ perl5.14.0 -lE' given("1foo"){ print "match" when ["foo"\,"bar"] && /foo/ }' match

I cannot see how that does what anyone wants.

The thot plickens.

"GIVEN DELENDA EST"

Indeed.

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

p5pRT commented 13 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 13 years ago

From @cpansprout

This is from Tom Christiansen at 8915.1306099936@​chthon\, but RT is having trouble picking up anything right now​:

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org wrote   on Sun\, 22 May 2011 14​:05​:17 PDT​:

This means that core overrides no longer work. :-( when(chr 3) { } is not the same as use subs 'chr'; sub chr($) { CORE​::chr shift } when(chr 3) { }

Youch!

I really thought that meant when("foo" || "bar") would mean when($_ ~~ "foo" || $_ ~~ "bar").

I did\, too.

But now I’ve found out that it means when($_ ~~ ("foo" || "bar")).

| but usually they will do what you want.

No\, they usually do *not*. That's my whole problem.

One of the examples given right after that\, of how they will do what you want\, is​:

when \(\[qw\(foo bar\)\] && /baz/\) \{ \.\.\. \}

which uses smart-matching. That gives this​:

$ perl5.14.0 -lE' given("foo"){ print "match" when ["foo"\,"bar"] }' match $ perl5.14.0 -lE' given("foo"){ print "match" when ["foo"\,"bar"] && /foo/ }' $ perl5.14.0 -lE' given("1foo"){ print "match" when ["foo"\,"bar"] && /foo/ }' match

I cannot see how that does what anyone wants.

Perhaps it's just emergent behavior\, not something anyone intended.

The thot plickens.

"GIVEN DELENDA EST"

Indeed.

Why does it seem that everyone who looks at comes to the same conclusion?

Perhaps because the contrary opinion is one of contentedness\, which is always less heard than its opposite sentiment? Dunno.

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

And try again when\, in 5.20? Although the time elapsed between 5.20 and 5.10 (when the first broken version appeared) is likely to be shorter than that of 5.10 to 5.0\, it still seems cruelly long.

A clean slate is good\, but I don't know what we'd manage to get away with it. I get the feeling there is no will to correct past errors\, just to begrudgingly live with forevermore.

I don't know that we can ever remove anything anymore. There has to be some way to get there\, but no clear path suggests itself.

Are we doing users disservice to document this stuff? The smart match examples I provided (well\, or tried) were the first ones ever\, after 4 years. But now I feel like I'm just encouraging people to use it\, which will make it even harder to undo or fix or change anything.

--tom

p5pRT commented 13 years ago

From @cpansprout

Tom Christiansen wrote​:

I don't know that we can ever remove anything anymore. There has to be some way to get there\, but no clear path suggests itself.

Would it be possible to mark these features as experimental ex post facto? Then we can change them.

Are we doing users disservice to document this stuff? The smart match examples I provided (well\, or tried) were the first ones ever\, after 4 years. But now I feel like I'm just encouraging people to use it\, which will make it even harder to undo or fix or change anything.

Maybe you shouldn’t give too many examples. Explain clearly how it breaks the equivalence of foo and foo() (if it has been declared) and how core overriding\, || and && are broken. That should scare people away. :-)

Perhaps a sentence like this could go somewhere​:

Smart match and C\ are smart\, not because they guess what you mean\, but because\, even when you think you have mastered them\, they will still outsmart you.

:-)

p5pRT commented 13 years ago

From @sciurius

Chip Salzenberg \rev\.chip@&#8203;gmail\.com writes​:

On Sun\, May 22\, 2011 at 2​:05 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

+1

+1

(Bonus points for 5.14.1 deprecation.)

-- Johan

p5pRT commented 13 years ago

From @tux

On Mon\, 23 May 2011 09​:22​:01 +0200\, Johan Vromans \jvromans@&#8203;squirrel\.nl wrote​:

Chip Salzenberg \rev\.chip@&#8203;gmail\.com writes​:

On Sun\, May 22\, 2011 at 2​:05 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

I don't think I agree with deprecation.

I would agree with simplification

"given" is the only sensible replacement for the ultimately broken Switch module. Switch doesn't work e.g. when any part of the script after the 'use Switch' has // (defined-or).

I had to rewrite production code to move to given/when because of Switch' broken-ness. I however just use "simple cases

given ($scalar) {

  when ("string") ...

  when (m/regex/) ...

  when ($_ \< 100) ...

deprecating this means that there is no transition at all. Switch is broken beyond usefulness. given/when is broken beyond imagination. I don't know what is worse.

-- H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/ using 5.00307 through 5.12 and porting perl5.13.x on HP-UX 10.20\, 11.00\, 11.11\, 11.23 and 11.31\, OpenSuSE 10.1\, 11.0 .. 11.3 and AIX 5.2 and 5.3. http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/ http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

p5pRT commented 13 years ago

From @Leont

On Sun\, May 22\, 2011 at 11​:05 PM\, Father Chrysostomos via RT \perlbug\-followup@&#8203;perl\.org wrote​:

    "GIVEN DELENDA EST"

Indeed.

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

I think deprecating it entirely would be a bit of an overkill​: pattern matching is a rather useful feature. I would propose to make ÂŤwhen fooÂť *always* do smartmatching. That would cut out most of the insanity while retaining most of the useful functionality of it. It would still allow you to support the 'boolean' cases by explicitly using ~~ overloading​:

  perl -lE' given("foo"){ print "match" when all_of(["foo"\,"bar"]\, qr/foo/) }'

Leon

p5pRT commented 13 years ago

From @sciurius

Tom Christiansen \tchrist@&#8203;perl\.com writes​:

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

And try again when\, in 5.20? Although the time elapsed between 5.20 and 5.10 (when the first broken version appeared) is likely to be shorter than that of 5.10 to 5.0\, it still seems cruelly long.

It is also possible to define better semantics for given/when/smartmatch and enable these with feature 5.16.

But\, as Tom pointed out\, first steps are​: what do we want it to do\, and do we want to fix this.

-- Johan

p5pRT commented 13 years ago

From @ap

* Johan Vromans \jvromans@&#8203;squirrel\.nl [2011-05-23 13​:05]​:

It is also possible to define better semantics for given/when/smartmatch and enable these with feature 5.16.

Wouldn’t that effectively mean the insane semantics have to be maintained and supported forever?

p5pRT commented 13 years ago

From @sciurius

"H.Merijn Brand" \h\.m\.brand@&#8203;xs4all\.nl writes​:

"given" is the only sensible replacement for the ultimately broken Switch module. Switch doesn't work e.g. when any part of the script after the 'use Switch' has // (defined-or).

I had to rewrite production code to move to given/when because of Switch' broken-ness. ... deprecating this means that there is no transition at all.

Funny...

For 20 years\, Perl didn't have a switch. The official statement was that it didn't need it since there were so many alternative ways to write it.

Then Perl6 got a switch\, and Perl5 got a switch emulation\, that was broken\, and later a builtin kludge\, that is also broken.

And now suddenly we cannot live without switch anymore?

-- Johan

p5pRT commented 13 years ago

From @chipdude

On 5/23/2011 10​:21 AM\, Johan Vromans wrote​:

And now suddenly we cannot live without switch anymore?

+100

I like the visual clarity of given/when\, but the semantic mess overwhelms it. Off with its head. Meanwhile\, the only part of smart match I really want is a nice "in"/"any" operator. The rest should join given/when in the graveyard.

p5pRT commented 13 years ago

From tchrist@perl.com

Johan Vromans \jvromans@&#8203;squirrel\.nl wrote   on Mon\, 23 May 2011 19​:21​:04 +0200​:

"H.Merijn Brand" \h\.m\.brand@&#8203;xs4all\.nl writes​:

"given" is the only sensible replacement for the ultimately broken Switch module. Switch doesn't work e.g. when any part of the script after the 'use Switch' has // (defined-or).

I had to rewrite production code to move to given/when because of Switch' broken-ness. ... deprecating this means that there is no transition at all.

Funny...

For 20 years\, Perl didn't have a switch. The official statement was that it didn't need it since there were so many alternative ways to write it.

Then Perl6 got a switch\, and Perl5 got a switch emulation\, that was broken\, and later a builtin kludge\, that is also broken.

And now suddenly we cannot live without switch anymore?

Well\, it is embarrassing to explain this stuff to people​:

  ARG​: while (@​ARGV && $ARGV[0] =~ s/^-(?=.)//) {   OPT​: for (shift @​ARGV) {

  m/^$/ && do { next ARG; };   m/^-$/ && do { last ARG; };

  s/^0// && do { $nullpaths++; redo OPT; };   s/^f// && do { $force++; redo OPT; };   s/^l// && do { $reslinking++; redo OPT; };   s/^I// && do { $inspect++; redo OPT; };   s/^i// && do { $careful++; redo OPT; };   s/^v// && do { $verbose++; redo OPT; };   s/^V// && do { $verbose += 2; redo OPT; }; # like two -v's   s/^m// && do { $renaming++; redo OPT; };   s/^n// && do { $nonono++; redo OPT; };   s/^N// && do { $nonono += 2; redo OPT; }; # like two -n's   s/^q// && do { $quiet++; redo OPT; };

  s/^F(.*)//s && do { push @​flist\, $1 || shift @​ARGV; redo OPT; };

  usage("Unknown option​: $_");   }   }

But I know​: you have an answer for that one\, too. :)

--tom

p5pRT commented 13 years ago

From @chipdude

On 5/22/2011 2​:32 PM\, Tom Christiansen wrote​:

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org wrote on Sun\, 22 May 2011 14​:05​:17 PDT​:

"GIVEN DELENDA EST"

Indeed. Why does it seem that everyone who looks at comes to the same conclusion?

I think it's because the added value of given/when is universally seen as minimal. It doesn't take many flaws to make the entire feature appear a bad job. The comparable flaws in\, say\, regex implementation and syntax never prompted anyone to try to rip out regexes; too much value\, obviously worth saving.

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate. And try again when\, in 5.20?

I say never\, personally. I'm not going to fight people who want to rescue it\, but we *don't* need a switch construct. And we don't need a smart match\, just a good in/any.

Are we doing users disservice to document this stuff?

A good technical document has rigidly defined areas of doubt and uncertainty.

p5pRT commented 13 years ago

From @chipdude

On 5/23/2011 11​:59 AM\, Tom Christiansen wrote​:

Well\, it is embarrassing to explain this stuff to people​:

ARG&#8203;: while \(@&#8203;ARGV && $ARGV\[0\] =~ s/^\-\(?=\.\)//\) \{
OPT&#8203;:    for \(shift @&#8203;ARGV\) \{

    m/^$/        && do \{                                 next ARG; \};
    m/^\-$/       && do \{                                 last ARG; \};
    s/^0//       && do \{ $nullpaths\+\+;                   redo OPT; \};

...

Y'know\, in all seriousness\, I wouldn't find that embarrassing to explain. I'd find it fun! Think of the tools you'd be giving the audience\, all from one example​: the short-circuit behavior of bools\, do BLOCK\, next\, last\, redo\, labelled blocks\, using 'for' to alias $_\, etc.

But maybe that's just me.

p5pRT commented 13 years ago

From @sciurius

[Quoting Tom Christiansen\, on May 23 2011\, 12​:59\, in "Re​: [perl #90886] Ma"]

Well\, it is embarrassing to explain this stuff to people​:

ARG&#8203;: while \(@&#8203;ARGV && $ARGV\[0\] =~ s/^\-\(?=\.\)//\) \{
OPT&#8203;:    for \(shift @&#8203;ARGV\) \{

    m/^$/        && do \{    next ARG; \}

...

I think it hardly becomes more elegant when written with given/when blocks...

  when ( m/^-$/ ) { break; } # hopefully it's a given\, not foreach   when ( s/^0// ) { $nullpaths++; }

But I know​: you have an answer for that one\, too. :)

Now that you mention it :)

-- Johan

p5pRT commented 13 years ago

From @ap

* Reverend Chip \rev\.chip@&#8203;gmail\.com [2011-05-23 20​:55]​:

Meanwhile\, the only part of smart match I really want is a nice "in"/"any" operator.

Yes. I like that part too.

The rest of smartmatch can die in a fire as far as I care.

The rest should join given/when in the graveyard.

Personally I’d like a hypothetical `given` and a hypothetical `when` that do a lot less than their current incarnations​:

• A `when` that is nothing but an `if` which implicitly does   `next` after its block. That is the aspect of `when` I actually   like\, and like a lot. No too-clever-by-half special-casing of   conditional expression forms\, no smartmatch\, none of all that.

• A `given` that is nothing but a single-argument\, scalar-context   version of `foreach`\, because using a single-iteration loop for   aliasing is a baroque idiom – Perlishly baroque\, but baroque   nonetheless. (Does anyone actually think C’s `while(0)` macro   hackaround is anything but?)

Regards\, -- Aristotle Pagaltzis // \<http​://plasmasturm.org/>

p5pRT commented 13 years ago

From @abigail

On Tue\, May 24\, 2011 at 02​:11​:44AM +0200\, Aristotle Pagaltzis wrote​:

* Reverend Chip \rev\.chip@&#8203;gmail\.com [2011-05-23 20​:55]​:

Meanwhile\, the only part of smart match I really want is a nice "in"/"any" operator.

Yes. I like that part too.

The rest of smartmatch can die in a fire as far as I care.

The rest should join given/when in the graveyard.

Personally I’d like a hypothetical `given` and a hypothetical `when` that do a lot less than their current incarnations​:

• A `when` that is nothing but an `if` which implicitly does `next` after its block. That is the aspect of `when` I actually like\, and like a lot. No too-clever-by-half special-casing of conditional expression forms\, no smartmatch\, none of all that.

• A `given` that is nothing but a single-argument\, scalar-context version of `foreach`\, because using a single-iteration loop for aliasing is a baroque idiom – Perlishly baroque\, but baroque nonetheless. (Does anyone actually think C’s `while(0)` macro hackaround is anything but?)

All my uses of given/when so far are of the form​:

  given ($str) {   when ("foo") {...}   when ("bar") {...}   ...   }

and

  given ($number) {   when (1) {...}   when (2) {...}   ...   }

If I wanted an if\, I can already write​:

  if ($str eq "foo") {...}   elsif ($str eq "bar") {...}

and

  if ($number == 1) {...}   elsif ($number == 2) {...}

I don't see what usage turning 'when' into an 'if' gives me. (What would the point of the "given" be?). Just for the rare case you want to jump over some code\, and save typing 'next'? Because I can already write​:

  {   if ($str eq "foo") {...; next}   some_code;   if ($str eq "bar") {...; next}   more_code;   }

as the equivalent of

  given ($str) {   when ("foo") {...}   some_code;   when ("bar") {...}   default {more_code}   }

I like the smart matching behaviour that happens in given/when\, but I haven't felt the urge to write my given/whens in such a way that different whens inside the same given result in different types of matches. I'd write my code differently instead.

I've seen people posting examples in this thread which complicated\, given/when clauses\, who then complain "this is too hard to explain/ maintain/understand".

Well\, write it differently. Just because you can construct complicated code doesn't mean you have to.

Abigail

p5pRT commented 13 years ago

From aaronpriven@gmail.com

Hi -- I've been lurking in perl5-porters for a while. Lately I've been following the discussion behind given/when and smart matching.

I've been rereading the discussion and trying to identify the nub of the problem\, and have come to the conclusion that really\, there isn't one. Rather\, there are a bunch of issues around the feature\, somewhat unrelated. I'm not sure I've understood everything\, but here's what I've gathered people have issues with​:

1) given\, unlike foreach\, makes a copy rather than aliasing $_

2) given takes a reference to its argument -- given(@​a) is treated as given(\@​a) rather than given (scalar @​a).

At least sometimes. This is from 5.12.3​:

% perl -E '@​a = 0 .. 2; @​b = 0 .. 7; given (@​b) { say $_ }' ARRAY(0x825940) % perl -E '@​a = 0 .. 2; @​b = 0 .. 7; given (@​a\, @​b) { say $_ }' 8

Admittedly\, I can't think why you'd want that use of comma (as opposed to given ([@​a\, @​b]) )\, but...

On the other hand\, it does dereference this​:

% perl -E '@​a = 0 .. 2; @​b = 0 .. 7; given (@​{[@​a\, @​b]}) { say $_ }' ARRAY(0x8039e0)

so it's not about the "literalness" of the array\, I think. I may not be clear on what "literal array" means in the context of perlsyn.

3) when has an implicit next in a foreach block\, but an implicit break in a given block\, and can't be used in while or until blocks.

4) when does smart matching\, except when it doesn't\, and it's not easy to figure out when it doesn't

5) smart matching itself is confusing and potentially misleading (e.g.\, '03' ~~ '3')

6) Nobody's mentioned this\, and I could well be missing something\, but I can't figure out any circumstance when "default" blocks make sense. The only difference I can see between code in a default block and code outside one is that there's an implicit break-or-next after the default block -- but what's the point of having it *always\, unconditionally* skip to the end of the enclosing block? It's a fancy way of writing "if (0) { ... } " until the end of the block. Which seems pointless.

Maybe there are more\, but those are the ones I've seen here.

--

I mainly just want to speak out in favor of the idea of some kind of switch statement. No\, Perl 5 doesn't need a switch statement\, but then again it doesn't *need* lots of things that are really useful to have. (I mean\, how redundant is "say"?)

I find the alternatives\, such as cascaded ternary operators\, serial if/elsifs\, etc.\, all much less readable. I think many other people find switch statements useful too.

I don't know what I think about smart matching. I think the only time I've used ~~ as an operator is when I wanted is_an_element\, but I have used it quite a bit for that. I do prefer "$foo ~~ @​bar" to the alternatives of building a temporary hash\, or using List​::MoreUtils​::any.

I don't know whether smart match is too complicated to be useful\, but I do think its complexity should be judged separately from its ambiguity\, and the ambiguity of "when".

--

I am not the right person to design a proper Perl 5 switch statement\, but I would like to throw out some thoughts.

It seems to me that there are two basic kinds of "when"​: smart-match when and truth when. Perl 5 guesses which one we want\, depending on whether the result looks like a boolean.

There are also a number of different kinds of smart matching\, but the part that leads to ambiguity -- e.g\, '03' ~~ '3' is true -- is that there is string matching and numeric matching\, and Perl 5 guesses which one we want\, depending on whether the result looks like a number.

So depending on what Perl guesses\, we either get truth when\, string-smart-match when\, or number-smart-match when. It seems to me that that avoiding the guessing -- having the programmer specify\, in some way\, truth when\, string when\, and number when -- would avoid a big part of the problem.

(Perl 6\, of course\, has strong typing that knows what everything is. Smart matching clearly would work better in that circumstance -- but for better or worse\, that's not Perl 5.)

--

Someone suggested replacing smart matching with an "in" keyword\, which would do some of what smart matching does. I think "is_an_element" was meant. OK\, that could be less complicated and easier to document\, if a lot less powerful\, than smart matching. Still\, an "in" keyword has to either assume string matching\, or have the same ambiguity as smart matching if it tries to guess whether it should use numeric or string comparison.

--

Thanks for listening.

-- Aaron Priven\, aaron@​priven.com

p5pRT commented 13 years ago

From @sciurius

Abigail \abigail@&#8203;abigail\.be writes​:

I've seen people posting examples in this thread which complicated\, given/when clauses\, who then complain "this is too hard to explain/ maintain/understand". Well\, write it differently. Just because you can construct complicated code doesn't mean you have to.

You're missing the point.

The problem is that you can write such complicated code because the given/when/smartmatch is complicated and higly anti-intuitive.

Let's assume we have an augmentation operator. It has a behaviour much like​:

  augmenting undef yields an empty string.   augmenting an integer number increments when positive\, decrements when   negative\, noop on zero.   augmenting a real number rounds it to the next higher integral.   augmenting an ASCII string upgrades it to UTF-8   augmenting a UTF-8 string puts a pair of U+201C and U+201D around it.   augmenting an array rotates it counter-clockwise for 1 element.   augmenting a hash lowcases all keys that are completely uppercase.   augmenting an object call the 'next' method\, or dies.

Now we have a very powerful (one might like to call it 'smart') operator but it's useless except for maybe one or two simple cases.

I consider the current given/when/smartmatch pretty much like that.

-- Johan

p5pRT commented 13 years ago

From vadim.konovalov@alcatel-lucent.com

From​: Johan Vromans Funny...

For 20 years\, Perl didn't have a switch. The official statement was that it didn't need it since there were so many alternative ways to write it.

Then Perl6 got a switch\, and Perl5 got a switch emulation\, that was broken\, and later a builtin kludge\, that is also broken.

And now suddenly we cannot live without switch anymore?

I always had an impression\, that 'switch' always was very requested by users - i.e. - novices often raised a question - "okay\, but how do I write switch statement" (one of perlfaq-s has section about this)

that is why Switch.pm appeared - but was not recommended to use because it was filter-based\, hence initially broken...

If designed correctly\, it would nicely complement the language...

Vadim.

p5pRT commented 13 years ago

From @wchristian

On Tue\, 24 May 2011 08​:01​:26 +0200\, Aaron Priven \aaronpriven@&#8203;gmail\.com wrote​:

It seems to me that that avoiding the guessing -- having the programmer specify\, in some way\, truth when\, string when\, and number when -- would avoid a big part of the problem.

This really seems to be the right path. I've been reading along and many things went over my head\, but the feeling that when really wants to be two separate things has been growing slowly.

-- With regards\, Christian Walde

p5pRT commented 13 years ago

From @sciurius

"Konovalov\, Vadim (Vadim)** CTR **" \vadim\.konovalov@&#8203;alcatel\-lucent\.com writes​:

If designed correctly\, it would nicely complement the language...

The nice complement has two aspects​: semantics and syntax.

As for syntax\, given/when adds very little. A nice switch syntax would be​:

  given ( \ ) {   \ : \; \; ... ;   \ : \; \; ... ;   ...   }

And\, while on the subject\, in an earlier life I've often used something similar to​:

  during ( \ ) {   \;   \;   ...;   }

meaning\, in current Perl​:

  while ( 1 ) {   \; last unless \;   \; last unless \;   ...   }

-- Johan

p5pRT commented 13 years ago

From zefram@fysh.org

Johan Vromans wrote​:

\ : \; \; ... ;

That's syntactically problematic\, risking confusion of \ with expression statements and labels. If you add a "case" keyword that could be resolved.

during ( \ ) { \; \;

That's syntactically fine.

Both of these proposals can be prototyped right now as modules on CPAN\, using the new syntax plugin facilities. I'd like to see such prototypes for all new syntax proposals for which it's possible.

-zefram

p5pRT commented 13 years ago

From @druud62

On 2011-05-23 20​:53\, Reverend Chip wrote​:

Meanwhile\, the only part of smart match I really want is a nice "in"/"any" operator. The rest should join given/when in the graveyard.

An 'in' with an optional code block\, wherein $a is left and $b is right.

-- Ruud

p5pRT commented 13 years ago

From @chipdude

On 5/24/2011 9​:14 AM\, Dr.Ruud wrote​:

On 2011-05-23 20​:53\, Reverend Chip wrote​:

Meanwhile\, the only part of smart match I really want is a nice "in"/"any" operator. The rest should join given/when in the graveyard.

An 'in' with an optional code block\, wherein $a is left and $b is right.

That's close enough to grep that I suspect we'd be better off just making grep short-circuitable to cover the given case. Like a yield or return or something.

But here's the core fault line that makes smart match dumb​: The Perl 5 way is that THE OPERATOR IMPOSES THE CONTEXT. The Data do not determine the meaning of the operator. The few exceptions that have snuck in are known problems (e.g. & | ^). As long as we return to that basic principle we'll do well.

I'm coming around to the idea that a junction-themed approach is be the most neat. Just one operator\, "any"\, could cover all these cases​:

  if ($foo == any(1\,2\,3))   if ($bar eq any("x"\,"y"\,"z"))   if ($baz =~ any(qr/a/\, qr/b/))

Now that's smart. An alternative is to create a variety of "in" symbolic operators via inflecting our existing operators; I think Perl 6 does this\, but let's not hold that against it. The main flaw is the enforced creation of arrayrefs\, unless we decide to use lists\, which in Perl 5 are a kludge so I'm not going to promote it. Here's the array version​:

  if ($foo ==^ [1\,2\,3])   if ($foo eq^ ["x"\,"y"\,"z"])   if ($foo =~^ [qr/a/\, qr/b/])

For great justice​:

  if (any($foo\,$bar) =~ any(qr/a/\, qr/b/))   if ([$foo\,$bar] ^=~^ [qr/a/\, qr/b/])

Making any of these schemes undef-safe is left as a problem for the reader.

p5pRT commented 13 years ago

From aaron@priven.com

On Tue\, May 24\, 2011 at 2​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

I'm coming around to the idea that a junction-themed approach is be the most neat. Just one operator\, "any"\, could cover all these cases​:

if ($foo == any(1\,2\,3)) if ($bar eq any("x"\,"y"\,"z")) if ($baz =~ any(qr/a/\, qr/b/))

So what occurred to me when I read this is that we have (m//) which means the same as ($_ =~ m//)\, and (s///) which means the same as ($_ =~ s///). Can (any(...)) without an operator mean the same as ($_ eq any(...)) ?

(It's not the same as void context -- the m// in "$a = m//" still compares against $_\, even though it's not in a void context. I'm not clear whether other comparison operators can be made to work the same as =~ in this way.)

If any() without an operator defaults to $_ eq any()\, we could have

topicalizer ($foo) {   do_something() when_true any('a'\,'b'\,'c'); }

and it would look very switchy.

Although you'd only get string matching. You'd still need $_ == any(1\,2\,3) and $_ =~ any (qr/a/\, qr/b/) for numeric and regex matching. (footnote *)

But I don't understand how junctions would work in Perl 5. We don't have them now\, right?

Is there a new kind of junction thingy\, or is a junction just an array? If it's just an array\, can a junction be put in a variable?

It would be awfully nice to be able to say

topicalizer( any(@​a) ) {   do_something if_or_when any('a'\,'b'\,'c') }

But if a junction is basically an array\, then $_ = any(1\,2\,3) would have to do the same thing as $_ = [1\,2\,3]\, and then I don't see how == and eq distinguish between referential equality and junction equality.

Or does $_ = any(1\,2\,3) do $_ = \(bless [1\,2\,3] \, 'JUNCTION') \, and then the operators know that JUNCTION objects are treated differently from unblessed arrayrefs or other objects?

--

(Footnote *)

Unless "any" really did work like "m"\, and the delimiter character determined what happened​: any('a'\,'b'\,'c')\, any[1\,2\,3]\, any/ qr/regex/ \, qr/regex/ / ... that's probably too weird.

Or maybe comparison and matching operators can be both unary-prefix and infix operators\, like - and +. The unary comparison operators would do exactly the same thing as the infix ones\, just without saying $_. Then we could have when_true ( == any (1\,2\,3)). And\, for that matter\, when_true (\< $a ) \, when_true (eq $a)\, etc. That's even more switchy. I have no idea if it could actually work.

-- Aaron Priven\, aaron@​priven.com

p5pRT commented 13 years ago

From @chipdude

On 5/24/2011 4​:17 PM\, Aaron Priven wrote​:

On Tue\, May 24\, 2011 at 2​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

I'm coming around to the idea that a junction-themed approach is be the most neat. Just one operator\, "any"\, could cover all these cases​:

if ($foo == any(1\,2\,3)) if ($bar eq any("x"\,"y"\,"z")) if ($baz =~ any(qr/a/\, qr/b/))

So what occurred to me when I read this is that we have (m//) which means the same as ($_ =~ m//)\, and (s///) which means the same as ($_ =~ s///). Can (any(...)) without an operator mean the same as ($_ eq any(...)) ?

I would say that's plausible but unknown now. I'll call it p=0.5.

But I don't understand how junctions would work in Perl 5. We don't have them now\, right?

Please note that I didn't say junctions per se\, but "junction-themed". I would expect in the first and most heavily used implementation cases\,   $foo == any(1\,2\,3) would actually be implmented as the equivalent of   scalar short_circuit_grep { $foo == $_ } 1\,2\,3 not as a real object.

Six important notes​:   1. A real Junction object would have to be constructed and destructed and go through overload processing etc. and I have NO interest in making Perl slower for no value.   2. More complex junction cases could be implemented later as real objects. but the point is to make common operations fast & easy\, not to becomes Smalltalk (or Perl 6 / Ruby).   3. People who disagree with my point (2) might try implementing use Junction qw( any all ) with C\<use overload '=='> etc. Who knows\, it might be cool.   3(a)​: There is no such thing as C\<use overload '=~'> but there damn well should be.   4. short_circuit_grep doesn't exist yet. Whether it would become visible at user is a separate question.   5. If we're doing 'any'\, we may as well do 'all' too. It won't be used nearly as much\, though.   6. Some special casing for undef might be important for usability reasons. Adding "defined($foo) && .." is a PITA.

Hm\, I wonder what   if ($a -> any('foo'\,'bar')) means? or   if ($a -> any(\&foo\, \&bar)) ? Not that it matters much\, the == eq =~ cases matter the most.

topicalizer( any(@​a) ) { do_something if_or_when any('a'\,'b'\,'c') }

Yes\, that's an argument in favor of (2) above. Personally I don't find it compelling\, but I could be in the minority.

Unless "any" really did work like "m"\, and the delimiter character determined what happened​: any('a'\,'b'\,'c')\, any[1\,2\,3]\, any/ qr/regex/ \, qr/regex/ / ... that's probably too weird.

Meh\, the delimiter is a sideshow. Number vs. string is the real problem\, and it's too easy in perl to accidentally stringify numbers and numberize strings. If you think using number syntax or string syntax solves the problem\, you really don't understand the problem. (NOTE this applies to whoever designed ~~ and given/when for Perl 5.)

Or maybe comparison and matching operators can be both unary-prefix and infix operators\, like - and +. The unary comparison operators would do exactly the same thing as the infix ones\, just without saying $_. Then we could have when_true ( == any (1\,2\,3)).

IMO\, no. My "Too Hokey To Live" telltale just lit up.

p5pRT commented 13 years ago

From @chipdude

On 5/24/2011 4​:17 PM\, Aaron Priven wrote​:

Or maybe comparison and matching operators can be both unary-prefix and infix operators\, like - and +. The unary comparison operators would do exactly the same thing as the infix ones\, just without saying $_. Then we could have when_true ( == any (1\,2\,3))

If that belonged in Perl\, then =~ would be a unary operator already. Not so much :-)

p5pRT commented 13 years ago

From @Leont

On Tue\, May 24\, 2011 at 11​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

But here's the core fault line that makes smart match dumb​: The Perl 5 way is that THE OPERATOR IMPOSES THE CONTEXT.  The Data do not determine the meaning of the operator.  The few exceptions that have snuck in are known problems (e.g. & | ^). As long as we return to that basic principle we'll do well.

I'm coming around to the idea that a junction-themed approach is be the most neat.  Just one operator\, "any"\, could cover all these cases​:

   if ($foo == any(1\,2\,3))    if ($bar eq any("x"\,"y"\,"z"))    if ($baz =~ any(qr/a/\, qr/b/))

Now that's smart.

There are a number of module that do such a thing\, such as Quantum​::Superpositions and Syntax​::Feature​::Junction. I can't comment on how well they work though.

An alternative is to create a variety of "in" symbolic operators via inflecting our existing operators; I think Perl 6 does this\, but let's not hold that against it.  The main flaw is the enforced creation of arrayrefs\, unless we decide to use lists\, which in Perl 5 are a kludge so I'm not going to promote it.  Here's the array version​:

   if ($foo ==^ [1\,2\,3])    if ($foo eq^ ["x"\,"y"\,"z"])    if ($foo =~^ [qr/a/\, qr/b/])

If you want a reliable comparison and aren't too religious about ~~ being evil\, you can trivially implement something like this​:

if ($foo ~~ any_number(1\,2\,3)) if ($foo ~~ any_string("x"\,"y"\,"z")) if ($foo ~~ any_regexp(qr/a/\, qr/b/))

Leon

p5pRT commented 13 years ago

From @chipdude

On 5/24/2011 5​:05 PM\, Leon Timmermans wrote​:

On Tue\, May 24\, 2011 at 11​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

if ($foo == any(1\,2\,3)) if ($bar eq any("x"\,"y"\,"z")) if ($baz =~ any(qr/a/\, qr/b/))

There are a number of module that do such a thing\, such as Quantum​::Superpositions and Syntax​::Feature​::Junction.

Quite. I initially though such modules irrelevant to this discussion. However\, I'm starting to realize that there are some questions only experiment can resolve. So such modules will make a good experimental basis. (BTW I mean experimentation in the context of fixing ~~ and given/when. As pure junction implementations\, they may be perfect already for all I know.)

We're gonna need C\<use overload '=~'> though.

If you want a reliable comparison and aren't too religious about ~~ being evil\, you can trivially implement something like this​:

if ($foo ~~ any_number(1\,2\,3)) if ($foo ~~ any_string("x"\,"y"\,"z")) if ($foo ~~ any_regexp(qr/a/\, qr/b/))

I appreciate that this could work\, but I see no significant advantage for all the extra typing (in both senses of the word).

In fairness it does have one insignificant advantage​: it can in theory represent multiple types of matches in a single object/operation​:

  if ($foo ~~ any(any_number(1)\, any_string("x")\, any_regexp(qr/a/)))

But frankly that's so rare and bizarre a case that forcing users to make a predicate subroutine instead (or just use grep) is a kindness\, not a burden.

p5pRT commented 13 years ago

From @cpansprout

On Tue May 24 17​:23​:31 2011\, rev.chip@​gmail.com wrote​:

On 5/24/2011 5​:05 PM\, Leon Timmermans wrote​:

On Tue\, May 24\, 2011 at 11​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

if ($foo == any(1\,2\,3)) if ($bar eq any("x"\,"y"\,"z")) if ($baz =~ any(qr/a/\, qr/b/))

There are a number of module that do such a thing\, such as Quantum​::Superpositions and Syntax​::Feature​::Junction.

Quite. I initially though such modules irrelevant to this discussion. However\, I'm starting to realize that there are some questions only experiment can resolve. So such modules will make a good experimental basis. (BTW I mean experimentation in the context of fixing ~~ and given/when. As pure junction implementations\, they may be perfect already for all I know.)

We're gonna need C\<use overload '=~'> though.

http​://perl5.git.perl.org/perl.git/commitdiff/9735207

If you want a reliable comparison and aren't too religious about ~~ being evil\, you can trivially implement something like this​:

if ($foo ~~ any_number(1\,2\,3)) if ($foo ~~ any_string("x"\,"y"\,"z")) if ($foo ~~ any_regexp(qr/a/\, qr/b/))

I appreciate that this could work\, but I see no significant advantage for all the extra typing (in both senses of the word).

In fairness it does have one insignificant advantage​: it can in theory represent multiple types of matches in a single object/operation​:

 if \($foo ~~ any\(any\_number\(1\)\, any\_string\("x"\)\,

any_regexp(qr/a/)))

But frankly that's so rare and bizarre a case that forcing users to make a predicate subroutine instead (or just use grep) is a kindness\, not a burden.

p5pRT commented 13 years ago

From @chipdude

On May 24\, 2011\, at 8​:38 PM\, "Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org wrote​:

On Tue May 24 17​:23​:31 2011\, rev.chip@​gmail.com wrote​:

On 5/24/2011 5​:05 PM\, Leon Timmermans wrote​:

On Tue\, May 24\, 2011 at 11​:05 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

if ($foo == any(1\,2\,3)) if ($bar eq any("x"\,"y"\,"z")) if ($baz =~ any(qr/a/\, qr/b/))

There are a number of module that do such a thing\, such as Quantum​::Superpositions and Syntax​::Feature​::Junction.

Quite. I initially though such modules irrelevant to this discussion. However\, I'm starting to realize that there are some questions only experiment can resolve. So such modules will make a good experimental basis. (BTW I mean experimentation in the context of fixing ~~ and given/when. As pure junction implementations\, they may be perfect already for all I know.)

We're gonna need C\<use overload '=~'> though.

http​://perl5.git.perl.org/perl.git/commitdiff/9735207

So. qr overload is actually =~ overload too. Fascinating...

p5pRT commented 13 years ago

From @tux

On Mon\, 23 May 2011 19​:21​:04 +0200\, Johan Vromans \jvromans@&#8203;squirrel\.nl wrote​:

"H.Merijn Brand" \h\.m\.brand@&#8203;xs4all\.nl writes​:

"given" is the only sensible replacement for the ultimately broken Switch module. Switch doesn't work e.g. when any part of the script after the 'use Switch' has // (defined-or).

I had to rewrite production code to move to given/when because of Switch' broken-ness. ... deprecating this means that there is no transition at all.

Funny...

For 20 years\, Perl didn't have a switch. The official statement was that it didn't need it since there were so many alternative ways to write it.

Then Perl6 got a switch\, and Perl5 got a switch emulation\, that was broken\, and later a builtin kludge\, that is also broken.

And now suddenly we cannot live without switch anymore?

Of course we can\, but we can live without a lot of useful things that got better or even first-time-implemented over time.

I refuse to do any production code that doesn't support defined-or I could live without given/when but Switch broke much more (for me) than given/when does

When "switch" lists get long\, and the one I was talking about is about 55 entries in a single given\, then I'd hate to be forced to use if/ifelse trees

-- H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/ using 5.00307 through 5.12 and porting perl5.13.x on HP-UX 10.20\, 11.00\, 11.11\, 11.23 and 11.31\, OpenSuSE 10.1\, 11.0 .. 11.3 and AIX 5.2 and 5.3. http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/ http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

p5pRT commented 13 years ago

From tchrist@perl.com

"H. Merijn Brand via RT" \perlbug\-followup@&#8203;perl\.org wrote   on Wed\, 25 May 2011 05​:49​:11 PDT​:

When "switch" lists get long\, and the one I was talking about is about 55 entries in a single given\, then I'd hate to be forced to use if/ifelse trees

Based on the principle that one should "represent similarities as data\, and differences in code"\, does that sort of thing call out for a big table\, perhaps a hash of function pointers?

Is the problem that the table entries (keys) aren't always the same thing\, but are sometimes strings\, sometimes numbers\, sometimes regexes\, etc?

--tom

p5pRT commented 13 years ago

From @tux

On Wed\, 25 May 2011 06​:56​:37 -0600\, Tom Christiansen \tchrist@&#8203;perl\.com wrote​:

"H. Merijn Brand via RT" \perlbug\-followup@&#8203;perl\.org wrote on Wed\, 25 May 2011 05​:49​:11 PDT​:

When "switch" lists get long\, and the one I was talking about is about 55 entries in a single given\, then I'd hate to be forced to use if/ifelse trees

Based on the principle that one should "represent similarities as data\, and differences in code"\, does that sort of thing call out for a big table\, perhaps a hash of function pointers?

Is the problem that the table entries (keys) aren't always the same thing\, but are sometimes strings\, sometimes numbers\, sometimes regexes\, etc?

In this case\, it is a wrapper around lp​:

$ grep -w when plp   when ("diac") {   when ("up") {   when (/^ soft \w* $/x) {   when ("noinit") {   when ("noff") {   when ("nolm") {   when ("nosz") {   when (/^(?​: noo | nodo )$/x) { # No (Default) Options   when (/^(?​: hand | bak1 )$/x) {   when (/^(?​: brief | bak2 )$/x) {   when (/^(?​: akte | bak3 )$/x) {   when (/^(?​: cas1 | bak4 )$/x) {   when (/^(?​: hci ([0-9]+) )$/x) {   when (/^(?​: sf | ff | manual )$/x) {   when (/^(?​: upper )$/x) {   when (/^(?​: lower )$/x) {   when (/^(?​: envelopp?e? )$/x) {   when (/^(?​: tra?y ([0-9]))$/x) {   when (/^(?​: af | alternate )$/x) {   when ("etiket") {   when ("ls") {   when (/^(?​: simplex | ss )$/x) {   when (/^(?​: duplex | ds | dleb )$/x) {   when (/^(?​: dseb )$/x) {   when ("a3") {   when ("a4") {   when ("a5") {   when ("a6") {   when ("b5") {   when (/^(?​: hco ([0-9]+) )$/x) {   when (/^l (?​: [4-9] | 1[0-2] )$/x) { # -ol4 .. -ol12   when (/^(?​: cx11 | ciso.* )$/x) {   when (/^cocrb?$/) {   when (/^p ( 8 | 1[0257] | 2[04] | 32 | rop )$/x) { # -op*   when (/^(?​: l | large )$/x) {   when (/^(?​: s | sm(all)? )$/x) {   when (/^(?​: t | tiny )$/x) {   when ("ola") {   when ("aanslag") {   when ("pocra3") {   when ("pocra4") {   when (/^ -?o? BSD h /x) { # No header. PASS verbatim to lp   when (/^ -?o? BSD /x) {   when (/^(?​: b | bin | binary )$/x) {   when (/^(?​: pdf | bindoc )$/x) {   when ("rbw") {   when (/^( nomacros | dam )$/x) {   when ("macros") {

-- H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/ using 5.00307 through 5.12 and porting perl5.13.x on HP-UX 10.20\, 11.00\, 11.11\, 11.23 and 11.31\, OpenSuSE 10.1\, 11.0 .. 11.3 and AIX 5.2 and 5.3. http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/ http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

p5pRT commented 13 years ago

From @Leont

On Wed\, May 25\, 2011 at 2​:22 AM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

I appreciate that this could work\, but I see no significant advantage for all the extra typing (in both senses of the word).

In fairness it does have one insignificant advantage​: it can in theory represent multiple types of matches in a single object/operation​:

    if ($foo ~~ any(any_number(1)\, any_string("x")\, any_regexp(qr/a/)))

But frankly that's so rare and bizarre a case that forcing users to make a predicate subroutine instead (or just use grep) is a kindness\, not a burden.

The real advantage is that you can compose them any way you want. You could make something like this​:

if $foo ~~ list(any('red'\, 'green'\, 'blue')\, all(integer\, positive\, uneven\, fibonacci\, prime)\, instance_of("DateTime"))

Leon

p5pRT commented 13 years ago

From @chipdude

On 5/25/2011 7​:05 AM\, Leon Timmermans wrote​:

On Wed\, May 25\, 2011 at 2​:22 AM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

I appreciate that this could work\, but I see no significant advantage for all the extra typing (in both senses of the word).

In fairness it does have one insignificant advantage​: it can in theory represent multiple types of matches in a single object/operation​:

if \($foo ~~ any\(any\_number\(1\)\, any\_string\("x"\)\, any\_regexp\(qr/a/\)\)\)

But frankly that's so rare and bizarre a case that forcing users to make a predicate subroutine instead (or just use grep) is a kindness\, not a burden. The real advantage is that you can compose them any way you want. You could make something like this​:

if $foo ~~ list(any('red'\, 'green'\, 'blue')\, all(integer\, positive\, uneven\, fibonacci\, prime)\, instance_of("DateTime"))

We don't need big data structures that describe any possible target object. We just want to write "$a == 1 || $a == 2 || $a == 3"
without having to type "$a ==" three times and without making our code slower.

Perl lacks any meaningful compile-time type checker and that's not going to change in the foreseeable future\, so "declarative" checks like you describe are\, without exception\, runtime procedural checks that just look different. The more you pretend otherwise the more you end up twisting the "declarative" system to become a fully procedural system with weird and unhelpful new syntax (while making things even *slower* to boot). Who needs that? See also the Moose type system\, Params​::Validate\, *​::Declare\, and the various signature implementations.

p5pRT commented 13 years ago

From aaron@priven.com

On Tue\, May 24\, 2011 at 5​:02 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

Unless "any" really did work like "m"\, and the delimiter character

determined what happened​: any('a'\,'b'\,'c')\, any[1\,2\,3]\, any/ qr/regex/ \, qr/regex/ / ... that's probably too weird.

Meh\, the delimiter is a sideshow. Number vs. string is the real problem\,

I want to clarify what I meant here. The idea was that right now\, there's no way to declare that something should be treated as a number or as a string\, except in the context of a particular operator or function. Anything being operated on by eq is treated as a string; anything being operated on by == is treated as a number. My thought was to try to come up with a shorter way of typing any_number() and any_string().

I'm pretty convinced by now that using delimiters is a terrible way of doing that; I apologize for suggesting it.

Or maybe comparison and matching operators can be both unary-prefix and infix operators\, like - and +. The unary comparison operators would do exactly the same thing as the infix ones\, just without saying $_.

I think this was probably clear in context\, but I meant here that the prefix operators would implicitly put $_ on the left side of the comparison.

Then we could have when_true ( == any (1\,2\,3)).

IMO\, no. My "Too Hokey To Live" telltale just lit up.

[and later...]

If that belonged in Perl\, then =~ would be a unary operator already.

Not so much :-)

But there is practically nothing that can go on the right side of =~ that doesn't already bind to $_ by default\, is there? m\, s\, tr. Unary =~ doesn't actually get us anything\, and so it's no wonder we don't have it.

I don't know if unary-comparisons-default-to-$_ is a good idea. It only saves\, I guess\, at most three characters of typing ($\, _\, space)\, and I suppose it might be confusing in complicated expressions. But I don't think it's "noticeably contrived"\, and I think would be simpler conceptually than something like smart-match.

Anyway\, I don't know what the answer to all this is. I'm not convinced that a "simple" switch feature is sufficient (that only allows scalars in the topicalizer\, or that only allows 'eq' comparisons)\, and at the same time\, now I realize the universe of possibilities is huge.

-- Aaron Priven\, aaron@​priven.com

p5pRT commented 13 years ago

From tchrist@perl.com

But there is practically nothing that can go on the right side of =~ that doesn't already bind to $_ by default\, is there? m\, s\, tr.

If it is not one of those three\, then it is taken to be a match on the (scalar) EXPR​:

  $foo =~ $bar   $foo =~ fn()

I use this plenty.

--tom

p5pRT commented 13 years ago

From @Leont

On Wed\, May 25\, 2011 at 8​:48 PM\, Reverend Chip \rev\.chip@&#8203;gmail\.com wrote​:

We don't need big data structures that describe any possible target object.  We just want to write    "$a == 1 || $a == 2 || $a == 3" without having to type "$a ==" three times and without making our code slower.

Well\, your 'we' doesn't include me then ;-)

p5pRT commented 13 years ago

From @cpansprout

On Mon May 23 00​:40​:35 2011\, hmbrand wrote​:

On Mon\, 23 May 2011 09​:22​:01 +0200\, Johan Vromans \jvromans@&#8203;squirrel\.nl wrote​:

Chip Salzenberg \rev\.chip@&#8203;gmail\.com writes​:

On Sun\, May 22\, 2011 at 2​:05 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

Maybe we should deprecate it in 5.16 and remove it in 5.18. That would give us a clean slate.

I don't think I agree with deprecation.

I would agree with simplification

How about this for a simplification​:

Only do implicit smart-match when the condition is one of these​:

• A string or number literal • A hash or array constructor ([] and {}) • A sigilled thingy ($foo @​bar &baz)

In all other cases\, don’t smart-match.

That would fix || and && and make them useful again. It would also fix core overrides.

"given" is the only sensible replacement for the ultimately broken Switch module. Switch doesn't work e.g. when any part of the script after the 'use Switch' has // (defined-or).

I had to rewrite production code to move to given/when because of Switch' broken-ness. I however just use "simple cases

given ($scalar) {

when \("string"\) \.\.\.

when \(m/regex/\) \.\.\.

when \($\_ \< 100\) \.\.\.

deprecating this means that there is no transition at all. Switch is broken beyond usefulness. given/when is broken beyond imagination. I don't know what is worse.

p5pRT commented 13 years ago

From schmorp@schmorp.de

On Tue\, May 17\, 2011 at 09​:29​:15AM -0700\, tchrist1 \perlbug\-followup@&#8203;perl\.org wrote​:

against doing so. That's because the old case-emulation stuff is understandable\, reliable\, and predictable\, whereas the new bits

Just accidentally stumbled over this thread - another thing that irked me is that given/when is the only non-dynamic control statement in perl.

For loops for example\, are dynamic\, that means I can write my own "last" statement​:

  sub last_if($) {   last if $_[0];   }

I recently tried that with given/when (for Coro​::MP\, to match erlang-style messages)\, but found that "when" completely changes semantics when it is not *syntactically* nested inside a given statement. That wasn't a showstopper\, as I have yet to find a useful application for smart-match - it certainly can't be used like matches in haskell\, erlang or anything else I would call "match" (as opposed to equality comparison)\, but I digress :)

It certainly was unexpected for given/when to have this static parsing behaviour.

One can argue about the trade-offs of dynamic "last" etc.\, but I think it's better to make all statement either static or dynamic\, and not all old control statements dynamic\, and the new ones static\, whether or not static is better.

(Probably this is all due to "we must be like perl6" - but maybe it's better to have a consistent perl5 than a weird perl5-and-a-half.)

--   The choice of a Deliantra\, the free code+content MORPG   -----==- _GNU_ http​://www.deliantra.net   ----==-- _ generation   ---==---(_)__ __ ____ __ Marc Lehmann   --==---/ / _ \/ // /\ \/ / schmorp@​schmorp.de   -=====/_/_//_/\_\,_/ /_/\_\

p5pRT commented 13 years ago

From @Leont

On Sun\, May 29\, 2011 at 11​:29 PM\, Father Chrysostomos via RT \perlbug\-followup@&#8203;perl\.org wrote​:

How about this for a simplification​:

Only do implicit smart-match when the condition is one of these​:

• A string or number literal • A hash or array constructor ([] and {}) • A sigilled thingy ($foo @​bar &baz)

In all other cases\, don’t smart-match.

That would fix || and && and make them useful again. It would also fix core overrides.

I personally disagree with the priority\, for me smartmatching is more valuable than boolean matching\, but there's a more fundamental issue with this solution. The core problem with when() is that it does two rather different things​: boolean-if-with-break and smartmatch-if-with-break but how it makes the distinction rather confusing. These different behaviors are both useful and breaking one to favor the other will not solve the real problem.

I think the only sane solution would be really simple​: split it up. Have one statement that always does boolean-if-with-break and another one that always does smartmatch-if-with-break\, that way there'll be no ambiguity left. There's no reason why these two need to share the same keyword.

Leon

p5pRT commented 13 years ago

From @sciurius

Leon Timmermans \fawaka@&#8203;gmail\.com writes​:

I think the only sane solution would be really simple​: split it up. Have one statement that always does boolean-if-with-break and another one that always does smartmatch-if-with-break\, that way there'll be no ambiguity left. There's no reason why these two need to share the same keyword.

Wouldn't it be easier to enforce boolean matching with !!\, e.g.

  when ( expr ) { ... smart ... }   when ( !!expr ) { ... boolean ... }

or even

  when ( !expr ) { ... boolean\, but negated ... }

-- Johan

p5pRT commented 13 years ago

From @klaus03

There is a rather long discussion in incident http​://rt.perl.org/rt3/Ticket/Display.html?id=90886 about the switch feature (given...when and smartmatching)

It begins on 17 Mai 2011​:

From​: Tom Christiansen \tchrist@&#8203;perl\.com I had intended to remove the "emulating case structures" bits from the documenation in favor of the switch feature. I have now decided against doing so. That's because the old case- emulation stuff is understandable\, reliable\, and predictable\, whereas the new bits are none of those things. ...

...and it stops (without a conclusion) on 30 Mai 2011

From​: Johan Vromans \jvromans@&#8203;squirrel\.nl

Leon Timmermans \fawaka@&#8203;gmail\.com writes​:

I think the only sane solution would be really simple​: split it up. Have one statement that always does boolean-if-with- break and another one that always does smartmatch-if-with- break\, that way there'll be no ambiguity left. There's no reason why these two need to share the same keyword.

Wouldn't it be easier to enforce boolean matching with !!\, e.g.

when ( expr ) { ... smart ... } when ( !!expr ) { ... boolean ... }

or even

when ( !expr ) { ... boolean\, but negated ... }

My question is quite simple​: is there any progress made on this topic since 30 may 2011 ?

-- Klaus

p5pRT commented 13 years ago

From @cpansprout

On Tue Oct 25 06​:25​:06 2011\, klaus03@​gmail.com wrote​:

There is a rather long discussion in incident http​://rt.perl.org/rt3/Ticket/Display.html?id=90886 about the switch feature (given...when and smartmatching)

It begins on 17 Mai 2011​:

From​: Tom Christiansen \tchrist@&#8203;perl\.com I had intended to remove the "emulating case structures" bits from the documenation in favor of the switch feature. I have now decided against doing so. That's because the old case- emulation stuff is understandable\, reliable\, and predictable\, whereas the new bits are none of those things. ...

...and it stops (without a conclusion) on 30 Mai 2011

From​: Johan Vromans \jvromans@&#8203;squirrel\.nl

Leon Timmermans \fawaka@&#8203;gmail\.com writes​:

I think the only sane solution would be really simple​: split it up. Have one statement that always does boolean-if-with- break and another one that always does smartmatch-if-with- break\, that way there'll be no ambiguity left. There's no reason why these two need to share the same keyword.

Wouldn't it be easier to enforce boolean matching with !!\, e.g.

when ( expr ) { ... smart ... } when ( !!expr ) { ... boolean ... }

or even

when ( !expr ) { ... boolean\, but negated ... }

My question is quite simple​: is there any progress made on this topic since 30 may 2011 ?

No\, not really. Nobody can agree on what smartmatch is meant/intended to do\, which to me signals a design flaw to begin with. Did the original implementor know what he intended it to do?

p5pRT commented 13 years ago

From tchrist@perl.com

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org wrote   on Tue\, 25 Oct 2011 08​:23​:29 PDT​:

On Tue Oct 25 06​:25​:06 2011\, klaus03@​gmail.com wrote​:

There is a rather long discussion in incident http​://rt.perl.org/rt3/Ticket/Display.html?id=90886 about the switch feature (given...when and smartmatching)

It begins on 17 Mai 2011​:

From​: Tom Christiansen \tchrist@&#8203;perl\.com I had intended to remove the "emulating case structures" bits from the documenation in favor of the switch feature. I have now decided against doing so. That's because the old case- emulation stuff is understandable\, reliable\, and predictable\, whereas the new bits are none of those things. ...

...and it stops (without a conclusion) on 30 Mai 2011

From​: Johan Vromans \jvromans@&#8203;squirrel\.nl

Leon Timmermans \fawaka@&#8203;gmail\.com writes​:

I think the only sane solution would be really simple​: split it up. Have one statement that always does boolean-if-with- break and another one that always does smartmatch-if-with- break\, that way there'll be no ambiguity left. There's no reason why these two need to share the same keyword.

Wouldn't it be easier to enforce boolean matching with !!\, e.g.

when ( expr ) { ... smart ... } when ( !!expr ) { ... boolean ... }

or even

when ( !expr ) { ... boolean\, but negated ... }

My question is quite simple​: is there any progress made on this topic since 30 may 2011 ?

No\, not really. Nobody can agree on what smartmatch is meant/intended to do\,

"Nobody can agree on what smartmatch is meant/intended to do"?
I do not believe that to be true\, as I'm sure Damian can agree with himself about his intent. :)

which to me signals a design flaw to begin with. Did the original implementor know what he intended it to do?

Better yet\, ask the original designer. Otherwise you risk enshrining quirks or bugs in the implementation as though they were a specification.

--tom

p5pRT commented 13 years ago

From @obra

My question is quite simple​: is there any progress made on this topic since 30 may 2011 ?

No\, not really. Nobody can agree on what smartmatch is meant/intended to do\, which to me signals a design flaw to begin with. Did the original implementor know what he intended it to do?

I'd argue that yes\, there is some progress. Jesse Luehrs did an initial pass at extracting smartmatch into a module and then implementing a "less-smart" smartmatch designed by rjbs that could be swapped out lexically.

I believe the right next step in the directioon of improving things is to figure out how to get Jesse's extraction of the core smartmatch implementation into core as a module.

The other big bit of progress (as mentioned by others) is that we've actually come to grips with how horribly broken the feature is and how much work it's going to be to unwind it to do it right.

-Jesse

--