Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

v5.36 syntax error around given/when

by ibm1620 (Hermit)
on Jun 09, 2022 at 19:35 UTC ( [id://11144613]=perlquestion: print w/replies, xml ) Need Help??

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

I installed perl 5.36.0 and I tried updating my starting "template" to use v5.36; rather than use 5.010;:
#!/usr/bin/env perl use v5.36; # was 'use 5.010;' #use warnings; # unnecessary now! use strict; no if $] >= 5.018, warnings => "experimental::smartmatch"; use Getopt::Std; my %opts; getopts( 'hvi:', \%opts ) or die "getopts failed\n"; my $verbose; my $infile; while ( my ( $k, $v ) = each %opts ) { given ($k) { # <-- line 13 when ('h') { ...; } when ('v') { ++$verbose; } when ('i') { $infile = $v; } default { die "*** BUG: no handler for -$k.\n"; } } }
It now gets the following compilation errors:
syntax error at /Users/chap/private/perl/t0 line 13, near ") {" syntax error at /Users/chap/private/perl/t0 line 15, near ") {" Global symbol "$v" requires explicit package name (did you forget to d +eclare "my $v"?) at /Users/chap/private/perl/t0 line 16. Execution of /Users/chap/private/perl/t0 aborted due to compilation er +rors.
I know that given is still experimental (and unpopular), but I thought it was still supported by 5.36. Also, suddenly missing the declaration of $v is weird. Anyone know what's going on?

Update: also, what would be the modern way to write that loop?

Replies are listed 'Best First'.
Re: v5.36 syntax error around given/when
by kcott (Archbishop) on Jun 09, 2022 at 23:14 UTC

    G'day ibm1620,

    "I know that given is still experimental (and unpopular), but I thought it was still supported by 5.36."

    The release notes, perl5360delta, whose first section is "use v5.36", has:

    "... with this release, the experimental switch feature, present in every feature bundle since they were introduced in v5.10, has been removed from the v5.36 bundle. ..."

    See "perlsyn: Switch Statements" for more about the switch feature.

    — Ken

      Thanks! So, in order to allow my method of processing command line options to continue to work while using the v5.36 features, I can write:
      use v5.36; use feature qw/switch/; no warnings "experimental::smartmatch"; no warnings "experimental::for_list"; for my ( $opt, $val ) (%$opts ) { given ($opt) { when ('h') { HELP_MESSAGE(); } when ('v') { ++$verbose; } when ('r') { ++$recursive; } when ('c') { ++$confirm; } when ('f') { ++$force; } default { die "*** BUG: no handler for -$opt.\n"; } } }
      To me, this reads the best. I guess that if given goes away I'll replace it with for .. reluctantly, because "for" has always implied looping to me.
Re: v5.36 syntax error around given/when
by hippo (Bishop) on Jun 09, 2022 at 22:01 UTC
    what would be the modern way to write that loop?

    Assuming you are actually asking about the given statement rather than the loop which contains it, the answer is in the FAQ.


    🦛

      Thanks. I was actually talking about the while-loop as well, since it contains the declaration of $v that seems to have been ignored.

        The error about the undeclared $v comes after the 2 syntax errors. Once you see a syntax error all bets are off concerning the rest of the compilation. You need to fix the syntax errors first and only then worry about everything else.


        🦛

Re: v5.36 syntax error around given/when
by Anonymous Monk on Jun 10, 2022 at 14:17 UTC

    In this application you can replace the given/when with a dispatch table. Other changes you can make since you use v5.36;:

    • You no longer need use strict; -- this is implied by use v5.12; or above;
    • You can use the experimental for-list syntax, though for the moment you will need to silence the "experimental" warning;
    • You can either eliminate the no if ... or just disable the warnings for smartmatch unconditionally, depending on whether you use them elsewhere in your code.

    The each() built-in is discouraged because there is only a single iterator for a given hash, which can be reset in un-obvious ways -- see the docs for each() for details.

    My take on your boilerplate, with all the above incorporated, is:

    #!/usr/bin/env perl
    
    use v5.36;     # was 'use 5.010;'
    #use warnings; # unnecessary now!
    #use strict;   # unnecessary since 5.12.
    no warnings 'experimental::for_list';
    #no if $] >= 5.018, warnings =< "experimental::smartmatch";
    use Getopt::Std;
    my %opts;
    getopts( 'hvi:', \%opts ) or die "getopts failed\n";
    my $verbose;
    my $infile;
    for my ( $k, $v ) ( %opts ) {
        state $dispatch = {
    	h => sub { ...; },
    	v => sub { ++$verbose; },
    	i => sub { $infile = $_[1]; },
        };
        my $code = $dispatch->{$k}
    	or die "*** BUG: no handler for -$k.\n";
        $code->( $k, $v );
    }
    

    Note that the subroutines in the dispatch table do not close over your loop variables, so you must pass them in explicitly.

      Interesting!

      I made the following changes:

      #!/usr/bin/env perl use v5.36; no warnings 'experimental::for_list'; use Getopt::Std; my %opts; getopts( 'hvi:', \%opts ) or die "getopts failed\n"; my $verbose; my $infile; for my ( $k, $v ) ( %opts ) { state $dispatch = { h => sub { say 'HELP!'; exit }, v => sub { ++$verbose; }, i => sub ($file) { $infile = $file; }, }; my $code = $dispatch->{$k} or die "*** BUG: no handler for -$k.\n"; $code->( $v ); } say "infile = ", $infile // 'undefined';
      I couldn't see any reason to pass $k into the sub; also, made use of sub signature.
Re: v5.36 syntax error around given/when
by BillKSmith (Monsignor) on Jun 10, 2022 at 20:22 UTC
    I believe that the 'modern way' is to fall back to either a chain of elsif for simple choices such as this:
    while ( my ( $k, $v ) = each %opts ) { for ($k) { if (/h/) { ...; } elsif (/v/) { ++$verbose; } elsif (/i/) { $infile = $v; } else { die "*** BUG: no handler for -$k.\n"; } } }

    or a 'dispatch table' for more complex switches.

    while ( my ( $k, $v ) = each %opts ) { state %dispatch = ( h => sub{...;}, v => sub{ ++$verbose;}, i => sub{ $infile = $v; }, ); die "*** BUG: no handler for -$k.\n" if !exists $dispatch{$k}; &{$dispatch{$k}}; }
    Bill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-24 20:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found