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

hello again dear monks it seems i have stumbled again on not knowing how to use switch statement properly. ok,so in response to these questions ive asked,i thank very much the people who answered me there http://perlmonks.org/?node_id=621046 http://perlmonks.org/?node_id=621054 http://perlmonks.org/?node_id=621013 and i have finally got a solution here it is:

use strict; use Switch; my $text="bla fred wilma fuck fred fuck wilma bla fred fredfred"; $text =~ s{(fred|wilma)} { my $replace_text; if($1 eq "fred") { $replace_text='wilma'; } else { $replace_text='fred'; }; $replace_text; }eg; print $text;

however to make the code i write more elegant i want to use switch instead of the if's statement but my code doesnt want to work. ive read perl documentation for switch already, no luck.

use strict; use Switch; my $text="bla fred wilma fuck fred fuck wilma bla fred fredfred"; $text =~ s{(fred|wilma)} { my $replace_text; switch($1) { case 'fred' {$replace_text='wilma'} case 'wilma' {$replace_text='fred'} }; $replace_text; }eg; print $text;

thank you

Replies are listed 'Best First'.
Re: regex switch trouble
by GrandFather (Saint) on Jun 14, 2007 at 01:02 UTC

    The bottom line is: "Don't use switch - it has issues".

    Often you can use a dispatch table instead, although in your sample a simple hash is all that is required:

    use warnings; use strict; my $text= 'bla fred wilma fred wilma bla fred fredfred'; my %replace = ( fred => 'wilma', wilma => 'fred', ); $text =~ s/(fred|wilma)/$replace{$1}/ge;

    Prints:

    bla wilma fred wilma fred bla wilma wilmawilma

    DWIM is Perl's answer to Gödel

      You can drop the /e too now that you're using a dispatch table. It's even faster that way.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: regex switch trouble
by Util (Priest) on Jun 14, 2007 at 01:07 UTC

    I don't know why the switch is not valid there, but anything that complex should be hoisted out of the replacement anyway. This works:

    use strict; use warnings; use Switch; my $text = 'bla fred wilma fuck fred fuck wilma bla fred fredfred'; sub replace_it { switch( $_[0] ) { case 'fred' { return 'wilma' } case 'wilma' { return 'fred' } die; }; } $text =~ s{(fred|wilma)}{replace_it($1)}eg; print $text;

      so is it because its embedded in the regex ? why is it so hard to implement switch in a proper manner ?
        When you put executable perl code into the replacement (right-hand) portion of  s///e, I think you are by nature using "eval" to execute that code. Therefore, you run up against this little detail described in the man page for Switch (under the section heading "LIMITATIONS"):
        Due to the way source filters work in Perl, you can't use Switch inside a string "eval".
        The reference to "source filters" there has to do with how the Switch module is implemented. When you use it, the code that ends up being executed is actually different in significant ways from the code that you wrote. That's why many people (including the author of the module) advise against using Switch in "production code" (i.e. for anything that needs to be rock-solid and readily maintainable).

        As GrandFather pointed out, there are better ways to do what you need to do in this case.

        Switch replaces the Perl parser with its own that understands the switch statement. However, Perl's parser is quite complex. Instead of re-implementing Perl, Switch takes some shortcuts which makes it malfunction in certain cases.
Re: regex switch trouble
by duncs (Beadle) on Jun 14, 2007 at 09:15 UTC
    I have used the Switch module myself in the past but found a couple of bugs with it (i.e. you have to fully specify all matches with a 'm' - m/match/ rather than /match/ else you get really strange errors, and line numbers are out when the compiler errors).

    I prefer to use the recommended method in the Camel (see also perldoc -q switch):

    SWITCH: foreach ($1) { m/^fred$/ && do {$replace_text='wilma'; last SWITCH}; m/^wilma$/ && do {$replace_text='fred'; last SWITCH}; do { die "Unknown check: $_\n" } }

    The code doesn't look as elegant as with the switch module, but I have had far fewer problems (and I will try Switch again sometime as I like it in principle).

      (and I will try Switch again sometime as I like it in principle).

      Wait for C<given>: guaranteed to be impressive, and very perlish in its own way, albeit not 5ish at all.