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

On request of a colleague I was playing around with an own implementation of switch as replacement for given/when

Surprisingly, I can use next within a sub to be able to fall thru to the next case, which leads to a nice syntax.

use strict; use warnings; use diagnostics; sub switch { no warnings 'exiting'; while (@_) { my ($case, $action) = splice @_,0,2; return $action->($case) if $_ ~~ $case; } } #no warnings 'exiting'; switch [1,2,3] => sub { print "bla" ; next}, 3 => sub { print "bla2" } for (3);

But I'm getting

Exiting subroutine via next at d:/Users/RolfLangsdorf/pm/switch.pl lin +e 18 (#1) (W exiting) You are exiting a subroutine by unconventional means, +such as a goto, or a loop control statement.

Obviously I can't dynamically disable the warning, because it's lexically scoped.

Uncommenting the #no warnings 'exiting' works, but would be acting for a much wider scope.

Question:

Is it possible to disable a certain warning in the dynamic scope?

Overwriting the warn handler does the trick ...

local $SIG{__WARN__} = sub { warn "$_[0]" unless $_[0] =~ /^Exiting subroutine via next/ } ;

... , but maybe there is a cleaner solution?

NB: this is experimental code and not meant for production! :)

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

Replies are listed 'Best First'.
Re: Disabling runtime warnings in dynamic scope? (no warnings 'exiting'; use warnings 'exiting';
by beech (Parson) on Apr 25, 2018 at 23:05 UTC

    Hi

    Find the right scope and tickle ${^WARNING_BITS}?

    $ perl -l #!/usr/bin/perl -- use strict; use warnings; use diagnostics; sub switch { no warnings 'exiting'; while (@_) { my ($case, $action) = splice @_,0,2; return $action->($case) if $_ ~~ $case; } } no warnings 'exiting'; switch [1,2,3] => sub { print "bla" ; next}, 3 => sub { print "bla2" } for (3); use warnings 'exiting'; switch [1,2,3] => sub { print "bla" ; next}, 3 => sub { print "bla2" } for (3); use warnings 'exiting'; switch [1,2,3] => sub { no warnings 'exiting'; print "bla" ; next}, 3 => sub { no warnings 'exiting'; print "bla2" } for (3); __END__ bla bla2 bla Exiting subroutine via next at - line 23 (#1) (W exiting) You are exiting a subroutine by unconventional means, +such as a goto, or a loop control statement. bla2 bla bla2
Re: Disabling runtime warnings in dynamic scope?
by choroba (Cardinal) on Apr 26, 2018 at 08:00 UTC
    Do you know Switch::Perlish? My patch is almost two years old, but I hope it still makes it work in the recent Perl.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      I've seen it. I'm experimenting on other ideas. ..

      Which patch for which problem?

      I can't see if I can easily replace the test condition to something different.

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

        The patch for the single problem reported in the distribution's bug tracker.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Disabling runtime warnings in dynamic scope?
by shmem (Chancellor) on Apr 26, 2018 at 09:04 UTC
    Is it possible to disable a certain warning in the dynamic scope?

    Which scope is dynamic here? All scopes here are determined at compile time.

    but maybe there is a cleaner solution?

    The most obvious clean solutions are

    { no warnings 'exiting'; switch [1,2,3] => sub { print "bla" ; next}, 3 => sub { print "bla2" } for (3); }

    or

    switch [1,2,3] => sub { print "bla" ; { no warnings 'exiting'; next } }, 3 => sub { print "bla2" } for (3);

    or even

    sub goNext { no warnings 'exiting'; next } switch [1,2,3] => sub { print "bla" ; goNext }, 3 => sub { print "bla2" } for (3);

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      > All scopes here are determined at compile time.

      Only lexical aka static scopes.

      Eg local has a dynamic scope .

      Check the definitions.

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

        Only lexical aka static scopes.

        Eg local has a dynamic scope.

        <edit>
        Because of LanX answer below:

        Well, local has no scope at all - it just masks a (package) global at runtime until the localizing goes out of (lexical) scope, but that's just nitpicking at wording perhaps. See also my/local, space/time (was: Re: The difference between my and local).

        local has a static scope. Localized variables have a dynamic scope.
        </edit>

        But here you answered the question for yourself. The warning bits are compiled into each lexical scope at compile time, and a local $^W = $my_bits doesn't change them at runtime for scopes further down.

        So there are two possibilities:

        1. localize $SIG{__WARN__} to propagate a runtime behavior
        2. compile and eval code to be called with a current $^W at runtime
        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'