Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Fall through loop

by b4swine (Pilgrim)
on Apr 28, 2016 at 13:33 UTC ( [id://1161770]=perlquestion: print w/replies, xml ) Need Help??

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

helloed monks,

Often I need to distinguish between a loop that ran to completion, and one that was aborted due to a last statement. For example, if I want to check if every element in a list is less than 0.5, I might write

my @list = (rand(1), rand(1), rand(1)); my $less=1; for (@list) { $less=0, last if $_>=0.5; }

At the end of this, $less will be true if all the members of the list were small, and false otherwise. I understand that this could have been done via grep in clever ways, but this is just an example. If we are doing a loop, is there a cleaner way to distinguish running a loop to completion from aborting via a last. If not, it would be a nice feature to have a system variable (or some better way), where one could write

for (@list) { last if $_ < 0.5; } my $less = $loop_ran_to_completion;

After thinking about it some more, here is an ugly looking solution, but without any temporary variables:

use Data::Dump; @list = (rand(1), rand(1), rand(1)); dd \@list; OUT: { ANY: { for (@list) { next ANY if $_ > 0.5; } # if all elements are small we come here print "All Small\n"; next OUT } # if any element is big we come here print "Some Big\n"; }

Replies are listed 'Best First'.
Re: Fall through loop
by Athanasius (Archbishop) on Apr 28, 2016 at 13:55 UTC

    Hello b4swine,

    I think you’re going to have to add a variable of your own; e.g.:

    #! perl use strict; use warnings; use Data::Dump; my $count = 0; my @list = (rand(1), rand(1), rand(1)); dd \@list; for (@list) { last if $_ < 0.5; ++$count; } if ($count < @list) { print "exited via last\n"; } else { print "ran to completion\n"; }

    Example output:

    23:49 >perl 1610_SoPW.pl [ 0.894318423773260207, 0.645644715844781558, 0.544934475599927026, ] ran to completion 23:51 >perl 1610_SoPW.pl [ 0.0333455559602988671, 0.597882601755799215, 0.918452691557956058, ] exited via last 23:51 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Fall through loop
by hippo (Bishop) on Apr 28, 2016 at 14:09 UTC

    You could throw an exception instead of using last:

    #!/usr/bin/env perl use strict; use warnings; use Try::Tiny; my @list = (rand(1), rand(1), rand(1)); my $less = 1; try { for (@list) { die if $_ >= 0.5; } } catch { $less = 0; }; print "$less\n";
Re: Fall through loop
by AnomalousMonk (Archbishop) on Apr 28, 2016 at 14:21 UTC
    ... this could have been done via grep in clever ways ...

    You may be thinking of something like:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @list = (rand(1), rand(1), rand(1)); dd \@list; ;; my $less = 1; for (@list) { $less = 0, last if $_ >= 0.5; } print 'for: all satisfy the condition' if $less; ;; my $any = grep { $_ >= 0.5 } @list; print 'grep: none fail the condition' if not $any; " [0.860137939453125, 0.796112060546875, 0.875457763671875] c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @list = (rand(1), rand(1), rand(1)); dd \@list; ;; my $less = 1; for (@list) { $less = 0, last if $_ >= 0.5; } print 'for: all satisfy the condition' if $less; ;; my $any = grep { $_ >= 0.5 } @list; print 'grep: none fail the condition' if not $any; " [0.134674072265625, 0.332855224609375, 0.4288330078125] for: all satisfy the condition grep: none fail the condition

    Because grep must continue to grind through all remaining elements of the list even after it is determined that the overall condition has failed, I'm not sure I would consider this "clever." Quick and dirty, yes, and useful as such.

    The for-loop approach has the advantage that it stops immediately when the overall condition is determined to have failed. The guts of List::MoreUtils  any() and  all() and their ilk are based on for-loops. An extra variable is a small price to pay.


    Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-04-24 17:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found