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

Looking for a good way to skip a set of operations, If one is TRUE ; Then Skip the rest. Also not sure if I really should have it on the last "IF", just to be consistent?

if($input_line =~ /UFRAME/){ @line_array=split(/,/, $input_line); #print "\n\n line_array = @line_array"; $UFRAME_index[$line_array[1]] = $line_array[1]; #print "\n\n UFRAME_index[$line_array[1]] = $UFRA +ME_index[$line_array[1]]"; $UFRAME_number[$line_array[1]] = $line_array[2]; #print "\n\n UFRAME_number[$line_array[1]] = $UFR +AME_number[$line_array[1]]"; $UFRAME_x[$line_array[1]] = sprintf("%.3f", $line_array[3]); #print "\n\n UFRAME_x[$line_array[1]] = $UFRAME_x +[$line_array[1]]"; if($UFRAME_x[$line_array[1]] != 0){ print "\n\n WARNING: UFRAME \[X\] value \($UFRAME_x[$l +ine_array[1]]\) is NOT ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } $UFRAME_y[$line_array[1]] = sprintf("%.3f", $line_array[4]); #print "\n\n UFRAME_y[$line_array[1]] = $UFRAME_y +[$line_array[1]]"; if($UFRAME_y[$line_array[1]] != 0){ print "\n\n WARNING: UFRAME \[Y\] value \($UFRAME_y[$l +ine_array[1]]\) is NOT ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } $UFRAME_z[$line_array[1]] = sprintf("%.3f", $line_array[5]); #print "\n\n UFRAME_z[$line_array[1]] = $UFRAME_z +[$line_array[1]]"; if($UFRAME_z[$line_array[1]] != 0){ print "\n\n WARNING: UFRAME \[Z\] value \($UFRAME_z[$l +ine_array[1]]\) is NOT ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } $UFRAME_Rx[$line_array[1]] = sprintf("%.3f", $line_array[6]); #print "\n\n UFRAME_Rx[$line_array[1]] = $UFRAME_ +Rx[$line_array[1]]"; if($UFRAME_Rx[$line_array[1]] != 0){ print "\n\n WARNING: UFRAME \[Rx\] value \($UFRAME_Rx[ +$line_array[1]]\) is NOT ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } $UFRAME_Ry[$line_array[1]] = sprintf("%.3f", $line_array[7]); #print "\n\n UFRAME_Ry[$line_array[1]] = $UFRAME_ +Ry[$line_array[1]]"; if($UFRAME_Ry[$line_array[1]] != 0){ print "\n\n WARNING: UFRAME \[Ry\] value \($UFRAME_Ry[ +$line_array[1]]\) is NOT ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } $UFRAME_Rz[$line_array[1]] = sprintf("%.3f", $line_array[8]); #print "\n\n UFRAME_Rz[$line_array[1]] = $UFRAME_ +Rz[$line_array[1]]"; if($UFRAME_Rz[$line_array[1]] == 0){ print "\n\n WARNING: UFRAME \[Rz\] value \($UFRAME_Rz[ +$line_array[1]]\) is ZERO \!"; $uframe_tilted = 1; #---------------- # JUMP FROM HERE #---------------- } #-------------- # JUMP TO HERE #-------------- if ($uframe_tilted == 1){ print "\n\n WARNING: UFRAME \[$UFRAME_number[$line_arr +ay[1]]\] is \"Offset or Tilted\" \!\n"; print "\n X \= $UFRAME_x[$line_array[1]]"; print "\n Y \= $UFRAME_y[$line_array[1]]"; print "\n Z \= $UFRAME_z[$line_array[1]]"; print "\n Rx \= $UFRAME_Rx[$line_array[1]]" +; print "\n Ry \= $UFRAME_Ry[$line_array[1]]" +; print "\n Rz \= $UFRAME_Rz[$line_array[1]]" +; print "\n\nPlease confirm UFRAME \[$UFRAME_number[$line_ar +ray[1]]\] values are CORRECT \[Yes\/No\] ?" ; $selection_chosen = <STDIN>; }

Replies are listed 'Best First'.
Re: Best way to "Skip" a set of operations
by Fletch (Bishop) on Jul 03, 2019 at 18:11 UTC

    Taking a step back, having several variables which differ in a suffix is a common red flag that you probably should be using a different data structure. A more common obvious occurrence would be $foo_1, $foo_2, $foo_3, ... which would indicate you may instead want an array @foo. In your case it looks like you should have a hash %UFRAME with references to arrays (aka "HoA"). See perldsc for more details.

    That being said were you using a more appropriate data structure your big mess 'o ifs could simplify down into something more like . . .

    my $uframe_tilted = undef; my %member_indexen; @member_index{ qw/ x y z Rx Ry Rz / } = ( 3 .. 8 ); if( $input_line =~ /UFRAME/ ) { MEMBERS: for my $member ( qw/ x y z Rx Ry Rz / ) { $UFRAME{$member}->[ $line_array[1] ] = sprintf( "%.3f", $line_array[ $member_index{ $member } ] ) if( $UFRAME{ $member }->[ $line_array[1] ] != 0 ) { $uframe_tilted = 1; last MEMBERS; } } }

    Update: Tweaked wording. Also slightly complicating things is that your comparison isn't always ... != 0 but ... == 0 in one case. There's several ways to handle that; one way would be to define a comparison sub that does the right thing based on which hash member you're looking at, then your check would be something like if( _is_frame_tilted( $member, $UFRAME{$member}->{$line_array[1] ) { $uframe_tilted = 1; last MEMBERS; }

    sub _is_frame_tilted { my( $member, $value ) = @_; if( $member eq 'Rz' ) { return $value == 0; } else { return $value != 0; } }

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Best way to "Skip" a set of operations
by choroba (Cardinal) on Jul 03, 2019 at 18:06 UTC
    If you are in a while loop, you can just call next. The part after JUMP HERE should then go to a continue block so it gets executed every time, even when you call next.
    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; my $i = 1; while ($i <= 10) { say $i; if ($i % 2) { say 'Skipping an odd number.'; next } } continue { ++$i; }
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Side note:

      > If you are in a while loop, you can call ...(loop control)

      No need for an explicit while loop, any nacked surrounding block is fine.

      main::(-e:1): 0 DB<1> print 1 ; { last; print 2 }; print 3 13 DB<2>

      See also perlsyn#Basic-BLOCKs

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Best way to "Skip" a set of operations
by hippo (Archbishop) on Jul 03, 2019 at 18:10 UTC

    You seem to be performing the same operation on different variables half a dozen times. Why not use a subroutine instead? You might also be interested in this post regarding all those backslashes.

Re: Best way to "Skip" a set of operations
by kcott (Archbishop) on Jul 04, 2019 at 07:16 UTC

    G'day thnksnw,

    You can do what you want using a label. Here's an example:

    #!/usr/bin/env perl use strict; use warnings; for (qw{1 two -3 3.4 zero 0}) { print "$_ is ", get_num_type($_), "\n"; } sub get_num_type { my ($num) = @_; my $num_type; NUM_TYPE_TEST: { if ($num !~ /^-?\d+$/) { $num_type = 'non-integer'; last NUM_TYPE_TEST; } if ($num < 0) { $num_type = 'negative'; last NUM_TYPE_TEST; } if ($num == 0) { $num_type = 'zero'; last NUM_TYPE_TEST; } if ($num > 0) { $num_type = 'positive'; last NUM_TYPE_TEST; } } return $num_type; }

    Output:

    1 is positive two is non-integer -3 is negative 3.4 is non-integer zero is non-integer 0 is zero

    Do note that this may not be the best course of action in your case; however, as you just posted a swathe of code out of context, I'm in no position to tell. I do see that you're splitting $input_line on a comma: if you're working with CSV files, consider using Text::CSV (which will run faster if you have Text::CSV_XS installed).

    — Ken

Re: Best way to "Skip" a set of operations
by Marshall (Canon) on Jul 04, 2019 at 04:58 UTC
    I see many flaws in this logic. Can you give use say 5 lines of UFRAME input data? And your expected output for those 5 line of input?

    I am not sure what you intend with the format spec %.3f?
    That rounds the floating point input to 3 decimal places like this:

    use strict; use warnings; foreach (3.5, 2.6888, 8.25 ,8, 1249.7999999999999999) { printf("%.3f\n", $_); } __END__ 3.500 2.689 note <= rounding up from 2.6888 8.250 8.000 1249.800 <= note rounded up from 7999999999999
    Update: I am not sure what you desire.
    This is some simple code that uses "match regex global" to get the numbers from lines that start with UFRAME.
    use strict; use warnings; while (my $line = <DATA>) { if ($line =~ m/^UFRAME/) { my @numbers = $line =~ /([\d.]+)/g; print "UFRAME numbers: @numbers\n"; @numbers = map{sprintf "%.3f",$_}@numbers; print "UFRAME numbers with 3 decimal points: @numbers\n\n"; } } =prints: UFRAME numbers: 3.0 5.6 7.9000999 43.08999 UFRAME numbers with 3 decimal points: 3.000 5.600 7.900 43.090 UFRAME numbers: 2.57777 32.000 54 1 UFRAME numbers with 3 decimal points: 2.578 32.000 54.000 1.000 =cut __DATA__ nonsense UFRAME 3.0, 5.6, 7.9000999, 43.08999 BS UFRAME 2.57777, 32.000,54,1
    Update:

    Just as a simple formulation of your code, consider this and how to get what you want out of it.

    #!/usr/bin/perl use strict; use warnings; #data format #UFRAME,index,number,x,y,z while (my $line =<DATA>) { next unless $line =~ /UFRAME/; chomp $line; my (undef,$index,$number,@coordinates) = split /,/,$line; print "Index=$index, Number=$number, Coordinates =@coordinates\n"; warn_coordinate_zero(@coordinates); } sub warn_coordinate_zero { my (@corrdinates)= @_; print " X value is not zero\n" if (shift @corrdinates); print " Y value is not zero\n" if (shift @corrdinates); print " Z value is not zero\n" if (shift @corrdinates); } =Prints Index=32, Number=14, Coordinates =0 0 0 Index=32, Number=99, Coordinates =0 0 45 Z value is not zero Index=32, Number=959, Coordinates =65 0 0 X value is not zero Index=32, Number=959, Coordinates =99 0 23 X value is not zero Z value is not zero =cut __DATA__ UFRAME,32,14,0,0,0 BOGUS UFRAME,32,99,0,0,45 UFRAME,32,959,65,0,0 UFRAME,32,959,99,0,23