Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

recursive call of current script

by feumw (Sexton)
on Jun 21, 2022 at 10:46 UTC ( [id://11144894]=perlquestion: print w/replies, xml ) Need Help??

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

We have a script which has a for-loop which kinda works like a switch. Depending on the parameter $sFunction we're running different code.
for ( $sFunction ) { /test1/ && do { # .... }; /test2/ && do { # .... }; }
I would like to call a different function in this loop before like
for ( $sFunction ) { /test1/ && do { # .... }; /test2/ && do { # here I want to call /test1/ part above ... # ... and then do different stuff here }; }
is there a clean way to do this rather then executing this script with a different arguement again?

Replies are listed 'Best First'.
Re: recursive call of current script
by haukex (Archbishop) on Jun 21, 2022 at 11:48 UTC

    The for is apparently just being used as a topicalizer here. So if you rewrite the first code example in "normal" Perl, it's

    if ( $sFunction =~ /test1/ ) { # ... } if ( $sFunction =~ /test2/ ) { # ... }

    So then it becomes more clear that one possibility of several for rewriting the logic is the following, where one could even consider to put $sFunction =~ /test2/ into a variable to avoid invoking the regex engine twice:

    if ( $sFunction =~ /test1/ || $sFunction =~ /test2/ ) { # ... if ( $sFunction =~ /test2/ ) { # ... } }

    Or, assuming your regexes have something in common like these example regexes, you can even write something like:

    if ( my ($num) = $sFunction =~ /test([12])/ ) { # ... if ( $num eq "2" ) { # ... } }
Re: recursive call of current script
by LanX (Saint) on Jun 21, 2022 at 10:57 UTC
    It depends.

    AFAIS you are not using next at the end of each block, so there is no explicit fall-through

    so one way is

    for ( $sFunction ) { /test1/ || /test2/ and do { # .... }; /test2/ and do { # will be executed too }; }

    another way is to use a subroutine

    my $do_test1 = sub { #... }; for ( $sFunction ) { /test1/ && $do_test1->(); /test2/ && do { $do_test1->(); # will be executed too }; }

    On a side note: why don't you use if or even if-elsif-else constructs?

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

      I didn't wrote the script originally, so I can't say why they did it this way. I'm gonna try both versions to see if this does the trick for us. But yeah using subroutines would already help. Didn't thought about that, colleague just asked me for ideas. Right now there's not enough time for us to rewrite this script. This would be a good workaround for us.
Re: recursive call of current script
by kcott (Archbishop) on Jun 21, 2022 at 22:42 UTC

    G'day feumw,

    With some realistic, example values for $sFunction, I may have provided a slightly different solution; however, in general, I'd probably tackle this with a dispatch table. Here's some example code showing the technique.

    #!/usr/bin/env perl use strict; use warnings; my %action_for; %action_for = ( test1 => sub { my ($input) = @_; print "*** Input: $input\n"; print "Test 1 code\n" }, test2 => sub { my ($input) = @_; $action_for{test1}->($input); print "Test 2 code\n"; }, ); my @tests = qw{ test1 test2 Atest1 test2B XYZ test1C test2D Etest1F Gtest2H }; /(test\d)/ && $action_for{$1}->($_) for @tests;

    Output:

    *** Input: test1 Test 1 code *** Input: test2 Test 1 code Test 2 code *** Input: Atest1 Test 1 code *** Input: test2B Test 1 code Test 2 code *** Input: test1C Test 1 code *** Input: test2D Test 1 code Test 2 code *** Input: Etest1F Test 1 code *** Input: Gtest2H Test 1 code Test 2 code

    — Ken

Re: recursive call of current script
by tybalt89 (Monsignor) on Jun 22, 2022 at 01:50 UTC

    Just wrap in a queue where you can add more things to the front. It does mean you will have to split some things into two parts, but still is just a fairly simple change.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11144894 use warnings; my @functionqueue = @ARGV ? @ARGV : qw( test1 test2 test1 ); # FIXME while( @functionqueue ) { for ( shift @functionqueue ) { /test1/ && do { print "test1 stuff\n"; }; /test2/ && do { print "test2 stuff\n"; unshift @functionqueue, qw( test1 secondpartof2 ); }; /secondpartof2/ && do { print "secondpartof2 stuff\n"; }; } }

    Outputs:

    test1 stuff test2 stuff test1 stuff secondpartof2 stuff test1 stuff
Re: recursive call of current script
by BillKSmith (Monsignor) on Jun 21, 2022 at 19:42 UTC
    This may not be the 'cleanest' solution, but it requires very little change to existing code. (Assumes that both regexes cannot match the same $sFunction. But I think that is implied by 'switch'.)
    for ( $sFunction ) { (/test1/ || /test2/) && do { # .... }; /test2/ && do { # .... }; }

    Sorry, Same as LanX's first solution. Comments apply.

    Bill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-03-29 11:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found