Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: improve ugly flow control

by Zaxo (Archbishop)
on Sep 19, 2004 at 07:41 UTC ( #392132=note: print w/replies, xml ) Need Help??

in reply to improve ugly flow control

Last Update: This is wrong. See below for details.

Here's a somewhat exotic construction that I think reads well. Assumes that do_something() returns true on success.

log_failure() unless grep { exists($hash{$_}) && do_something($_) .. 1 } @options;
or maybe better,
grep { exists($hash{$_}) && do_something($_) .. 1 } @options or log_failure();
Untested, but I think it's nearly right.

The flipflop is true for zero or one keys and the initiating condition is not evaluated again after it is first true.

Update: Tested now, and it's not right. Trying to fix it.

Another Update: Is this a bug in perl's flipflop op? In perl-5.8.4

$ perl -Mstrict -we'my $s=1;for(qw/foo bar baz/){ print if /b/..$s }' barbaz$ $ perl -Mstrict -we'my $s=1;for(qw/foo bar baz/){ print if $s../b/ }' $
I'm using a variable $s there because bart++ tells me that flipflop can play games with $. if bare integers are presented to it.

Final Update: There is no bug, except in my logic. Changing the right hand side of the flipflop to match anything (//) instead of fooling with constants, I find by printing the sequence numbers that the flipflop switches off ok, but switches on again next time around.

$ perl -e'for (qw/foo bar baz blah/){print int scalar(/b/..//)}' 0111$
Silly mistake on my part.

Here is a version that works, but it still needs that pesky $success variable I was trying to get rid of.

{ my $success; grep { ! $success && exists($hash{$_}) && do_something($_) .. ($success = 1) } @options or log_failure(); }
$success must be checked first to short-circuit the rest of the processing.

After Compline,

Replies are listed 'Best First'.
Re^2: improve ugly flow control
by Aristotle (Chancellor) on Sep 19, 2004 at 08:01 UTC

    Neat hack. Note that the grep will always iterate all of @options though. Also, you can remove the dependency on do_something()'s return value with a construct like

    exists $hash{ $_ } and ( do_something( $_ ), 1 )

    Makeshifts last the longest.

Re^2: improve ugly flow control
by Aristotle (Chancellor) on Sep 19, 2004 at 23:08 UTC

    In reply to the update:

    // does not match "anything". It is overloaded to reapply the last successfully matched pattern, in your case, /b/. You wouldn't notice that because all your test data past the successful match has a "b" in it… Changing that clearly reveals faulty logic: once the right side is true, and flipflop starts over on the left side again.

    $ perl -le'for( qw/foo bar baz blah/ ){ print int scalar( /b/ .. // ) +}' 0 1 1 1 $ perl -le'for( qw/foo bar baz quux/ ){ print int scalar( /b/ .. // ) +}' 0 1 1 0

    Now let's take a short trip to perlop:

    The value returned is either the empty string for false, or a sequence number (beginning with 1) for true. The sequence number is reset for each range encountered. The final sequence number in a range has the string "E0" appended to it, which doesn't affect its numeric value, but gives you something to search for if you want to exclude the endpoint. You can exclude the beginning point by waiting for the sequence number to be greater than 1.

    You want a right side that does not succeed. Because once it succeeds, you start over on the left side again!

    Now a simple, correct match-always pattern is /^/ or /(?=)/, and a simple match-never pattern is /$^/ or /(?!)/. Indeed, using a match-never pattern:

    $ perl -le'for( qw( foo bar baz quux ), "" ){ print int scalar( /b/ .. + /$^/ ) }' 0 1 2 3 4 $ perl -le'for( qw( foo bar baz quux ), "" ){ print int scalar( /baz/ +.. /$^/ ) }' 0 0 1 2 3

    Well, that sequence looks right. So that means you can say:

    log_failure() unless grep { ( exists $hash{$_} and ( do_something($_), 1 ) ) .. /$^/ } @options;

    Makeshifts last the longest.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://392132]
[tye]: -Mouse
[Corion]: Option a) would mean launching cmd.exe /k c:\path\to\ batchfile- launching-perl- script.cmd. Option b) would be to add pause as the last line of said batch file.
[LanX]: First day after holidays ... and already stressed by the fact that colleagues changed stuff without communication ... apparently I'm the only one trying to fight entropy
[Corion]: LanX: The command is always in the history if you typed it in before. If you didn't type the command into the command line, it will not be there. I think there is doskey which can stuff command lines into the history
LanX damns the cult of CB ;-)
[LanX]: please forget my last 3 posts
[LanX]: Yeah option a doesn't go into history
[LanX]: probably I need to teach the app to restart after C-c Kill
[Corion]: LanX: Maybe have an infinite-loop cmd file? Much easier than trying to manage that from within Perl IMO

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (9)
As of 2017-03-27 15:48 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (320 votes). Check out past polls.