Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Modern exposition of "case" or Switch in perl 5.34?

by symgryph (Sexton)
on Jul 02, 2021 at 22:11 UTC ( [id://11134604]=perlquestion: print w/replies, xml ) Need Help??

symgryph has asked for the wisdom of the Perl Monks concerning the following question:

I have read a lot about NOT using the 'switch' statement of yore, but saw some comments on using 'when' instead. Is there a modern howto on doing a case like construct in perl 5.34? thomas
"Two Wheels good, Four wheels bad."
  • Comment on Modern exposition of "case" or Switch in perl 5.34?

Replies are listed 'Best First'.
Re: Modern exposition of "case" or Switch in perl 5.34?
by kcott (Archbishop) on Jul 03, 2021 at 01:58 UTC

    G'day symgryph,

    "I have read a lot about NOT using the 'switch' statement of yore, ..."

    You need to be a bit careful with terminology. Perl does not have nor, as far as I know, has ever had a 'switch' statement. It does have "The 'switch' feature". There is a CPAN Switch module which provides a 'switch' function. I'm going to assume that you're talking about the Switch module.

    The BUGS and LIMITATIONS sections of Switch both provide a number of reasons to avoid it. I would strongly recommend against using it in production code.

    "... but saw some comments on using 'when' instead."

    I'll assume that's from the Switch BUGS section: "In general, use given/when instead.".

    When that was written, it was probably an entirely reasonable statement; however, in 5.18.0 'given', 'when, and the associated '~~' operator, were made experimental: "perl5180delta: The smartmatch family of features are now experimental". At 5.34.0 they remain experimental:

    $ perl -v | head -2 | tail -1 This is perl 5, version 34, subversion 0 (v5.34.0) built for cygwin-th +read-multi $ perl -E 'say 1~~2 ? "yes" : "no"' Smartmatch is experimental at -e line 1. no $ perl -E 'my $x = 1; given ($x) { when (2) { say "yes" } default { sa +y "no" } }' given is experimental at -e line 1. when is experimental at -e line 1. no

    Again, I would not use these in production code.

    "Is there a modern howto on doing a case like construct in perl 5.34?"

    — Ken

      At 5.34.0 they remain experimental

      And not for no reason. The design of smartmatch is considered fundamentally broken. They want to abandon this experiment, or at least redesign smart matching. The removal of smartmatching is being held back, at least for now, by the number of users of the experimental feature.

      Seeking work! You can reach me at ikegami@adaelis.com

        "The removal of smartmatching is being held back, at least for now, by the number of users of the experimental feature."

        Yes. Many, including myself, used smartmatch when it was first introduced in 5.10 (when it was not experimental). When it was made experimental in 5.18, many (again, including myself) simply followed the workaround provided in perl5180delta:

        no if $] >= 5.018, warnings => "experimental::smartmatch";

        This removed the copious "experimental" warnings and the code continued to run, without any problems, as it had done previously.

        The result is that now there is a large body of code in CPAN, as well as commercial and private libraries, that use smartmatch. I certainly have private code, still in current use, that uses it; it's entirely possible that commercial code which I wrote prior to 5.18 also included it.

        I suppose the lesson to be learnt here is to make all new features experimental until substantial in-the-field testing indicates no problems. This does seem to be the case for many features (e.g. try/catch in 5.34) but not all (e.g. chained comparisons in 5.32).

        — Ken

        The removal of smartmatching is being held back, at least for now, by the number of users of the experimental feature

        Perhaps that shows how useful in demand the feature is.

Re: Modern exposition of "case" or Switch in perl 5.34?
by Fletch (Bishop) on Jul 03, 2021 at 02:47 UTC
Re: Modern exposition of "case" or Switch in perl 5.34?
by LanX (Saint) on Jul 03, 2021 at 13:20 UTC
    > I have read a lot about NOT using the switch statement of yore,

    Seems like you are referring to use Switch which is a source filter and strongly discouraged.

    > but saw some comments on using when instead.

    This is most likely referring to given/when activated with use feature "switch" or use 5.10

    see https://perldoc.perl.org/perlsyn#Switch-Statements

    but also the limitations listed in

    https://perldoc.perl.org/perlsyn#Experimental-Details-on-given-and-when

    Short version

      You can use given/when as long as you stick to the simple to predict patterns. Because when is based on ~~ Smartmatch-Operator (which is already too smart) unless it is not (sigh)

    workarounds

    Most ppl I know - me included - prefer simpler workarounds depending on the use case like:

    a) For multiple tests till it fits

    • chained boolean tests
      • if/elsif/else
      • && do {} patterns with explicit last or next to break out °

    b) For faster direct lookup of the case (i.e. the comparison operation is always equality eq or == )

    • hashes for values
    • hash-dispatch tables for code
    • goto CASE_LABEL (plus explicit last or next to break out °)

    As you can see is switch trying to be overly clever and to cover a multitude of cases and optimizations.

    It would really help to know your explicit use case.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    °) I originally wrote "explicit break", but as Athanasius msged me are "break statement only for given/when constructs". Thanks Athanasius++ :)

Re: Modern exposition of "case" or Switch in perl 5.34? (RFC)
by LanX (Saint) on Jul 03, 2021 at 16:22 UTC
    Here a meditation how to implement most of it in a pure functional and backwards compatible way:

    NB:

    • the choice of subnames is open to debate
    • This is very beta and not heavily tested against all edge cases
    • once this is stable for all edge cases it can be improved for performance
    the basic ideas are:
    • using for as a topicalizer
    • a routine once {} like do {} but breaking out
    • a routine check {} to explicitly define the criteria (in contrast to smartmatch)
    • routines case() and break {} for syntactic sugar

    use v5.12; use warnings; use subs qw/break/; #use Data::Dump qw/pp dd/; #use diagnostics; say "========= IMPLEMENTATION"; { my $check; sub check(&) { $check = shift; } sub case { my $code; if (ref $_[-1] eq "my_break") { #warn "my break"; $code = pop @_; } my $do; for my $val (@_) { $do ||= $check->($val); } if ($do){ if ($code) { once($code) } else { return $do } } return; } no warnings 'exiting'; sub once (&) { (shift)->(); next; } sub break(&) { return bless shift, "my_break" } } say "========= TESTS"; say "--- with basic logic"; for ( 0 .. 5 ) { $_< 1 and once { print "$_ smaller 1"}; $_< 3 and once { print "$_ smaller 3"}; $_ > 3 && $_ < 5 and once { print "$_ between 3 and 5"}; print "$_ has no match"; # else } continue { print "\n"; } say "--- with some syntactic sugar"; for ( 0 .. 5 ) { check { $_ < shift }; case 1 and once { print "$_ smaller 1"}; case 3 and once { print "$_ smaller 3"}; case 4,5 and once { print "$_ smaller 4 or 5"}; print "$_ has no match"; # else } continue { print "\n"; } say "--- with even MORE syntactic sugar"; for ( 0 .. 5 ) { check { $_ < shift }; case 1 => break { print "$_ smaller 1"}; case 3 => break { print "$_ smaller 3"}; case 4,5 => break { print "$_ smaller 4 or 5"}; print "$_ has no match"; } continue { print "\n"; }

    C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/do_once.pl ========= IMPLEMENTATION ========= TESTS --- with basic logic 0 smaller 1 1 smaller 3 2 smaller 3 3 has no match 4 between 3 and 5 5 has no match --- with some syntactic sugar 0 smaller 1 1 smaller 3 2 smaller 3 3 smaller 4 or 5 4 smaller 4 or 5 5 has no match --- with even MORE syntactic sugar 0 smaller 1 1 smaller 3 2 smaller 3 3 smaller 4 or 5 4 smaller 4 or 5 5 has no match Compilation finished at Sat Jul 3 18:15:36

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Re: Modern exposition of "case" or Switch in perl 5.34?
by hippo (Bishop) on Jul 14, 2021 at 12:46 UTC

    Switch::Plain is perhaps a contender. I am not aware of any negative opinions of it.


    🦛

Re: Modern exposition of "case" or Switch in perl 5.34?
by karlgoethebier (Abbot) on Jul 04, 2021 at 07:54 UTC

    You might consider to jump to a label as goto can be a different thing in Perl.

    «The Crux of the Biscuit is the Apostrophe»

Re: Modern exposition of "case" or Switch in perl 5.34?
by Marshall (Canon) on Jul 03, 2021 at 01:48 UTC
    I ask that you present an actual coding problem. There are many ways to implement what you seek in Perl.
    Perhaps present some pseudo code?
    edit: I just don't know that problem that you are trying to solve?
      I just don't know that problem that you are trying to solve

      It is possible that the OP is not trying to solve a problem but simply trying to learn from others.

      But, like you say, it is easier to provide that help with some example code...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11134604]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2024-04-20 01:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found