Perl: LABEL defined inside the foreach loop, and issue coming on jumping to the LABEL using "goto LABEL" - perl

use strict;
use warnings;
my #content1=("sunTerio", "builds123", "build123_sunTerio", "glorai", "2131flow" , "build434_glorai");
my $tryVar;
&tty;
sub tty {
foreach my $we (7..9) {
$tryVar=1;
LABEL34: #### Line 12
foreach my $i (#content1) {
if (grep ((/sunTerio/i || /glorai/i), $i)) { #### Line 14
print "-----$i-----\n";
}
}
if ($tryVar) {
foreach my $r (1..5) {
if ($r == 2 ) {
$tryVar=0;
goto LABEL34;
}
}
}
}
}
Above is the code snippet. Here, when I am using "LABEL34" at the location where it is present (Line 12), then it is causing no issues. But when I am using "LABEL34" at the "Line 14", then it is causing issue with the (warning + error) message:
Use of "goto" to jump into a construct is deprecated at pl.pl line.
Can't "goto" into the middle of a foreach loop at pl.pl line 14.
Why is it so that when I am using LABEL34 at line 14, then only issue is coming; and not when the LABEL34 is at current position (Line 12), although both scenarios are under the foreach loop?
Thanks!

The foreach loop in question is this one:
foreach my $i (#content1) {
...
}
Jumping from outside of the foreach loop into its body makes no sense.
It makes no sense logically. A foreach loop body is executed for each item of a list. This loop body would be executed without an item.
It makes no sense practically. It would skip the evaluation of #content1 and the initialization of $i. Using $i would be undefined behaviour. And when you reach the end of the loop, what then? How can you check if you've reached the end of a list you never created in the first place?
It should ever have been allowed, and it was surely not intentional.
I can't suggest an alternative to placing the label on line 14 because you haven't said what you are trying to do. (I would normally be able to guess, but that simply makes no sense.)

Related

Perl while loop only looping once within a for loop

I'm new to perl and struggling with this. How can I make the following code iterate asterisk_Output each run of the for loop? At the moment it completes the while loop on the first iteration of the for loop but not on subsequent ones.
open(asterisk_Output, "/usr/sbin/asterisk -rx \"sip show registry\"|") or die $!;
foreach (#monitor_trunks){
while (my $line = <asterisk_Output>) {
#Perform some action... Such as comparing each line.
}
}
The only way I have got it working is by putting the top line within the for loop, but this is un necessary and make multiple calls to the external command.
At the end of your first loop, the file pointer is at the end of the file. You have to bring it back to beginning if you need another round.
You can try either to rewind the file:
seek(asterisk_Output,0,1);
or (if your logic allows it) to change foreach and while (so that you only read it once):
while (my $line = <asterisk_Output>){
foreach (#monitor_trunks) {
#Perform some action... Such as comparing each line.
}
}
The third option would be to read the whole file into an array and use it as an input for your loop:
#array = <asterisk_Output>;
foreach (#monitor_trunks){
for my $line (#array) {
#Perform some action...
}
}

C-style loops vs Perl loops (in Perl)

I feel like there is something I don't get about perl's looping mechanism.
It was my understanding that
for my $j (0 .. $#arr){...}
was functionally equivalent to:
for(my $i=0; $i<=$#arr; $i++){..}
However, in my code there seems to be some slight differences in the way they operate. specifically, the time in which they decide when to terminate. for example:
assume #arr is initialized with one variable in it.
These two blocks should do the same thing right?
for my $i (0 .. $#arr)
{
if(some condition that happens to be true)
{
push(#arr, $value);
}
}
and
for (my $i=0; $i<=$#arr; $i++)
{
if(some condition that happens to be true)
{
push(#arr, $value);
}
}
In execution however, even though a new value gets pushed in both cases, the first loop will stop after only one iteration.
Is this supposed to happen? if so why?
EDIT: Thank you for all of your answers, I am aware I can accomplish the same thing with other looping mechanisms. when I asked if there was a another syntax, I was specifically talking about using for. Obviously there isn't. as the syntax to do what I want is already achieved with the c style. I was only asking because I was told to avoid the c style but i still like my for loops.
$i<=$#arr is evaluated before each loop while (0 .. $#arr) is evaluated once before any loop.
As such, the first code doesn't "see" the changes to the #arr size.
Is there another syntax I can use that would force the evaluation after each iteration? (besides using c-style)
for (my $i=0; $i<=$#arr; $i++) {
...
}
is just another way of writing
my $i=0;
while ($i<=$#arr) {
...
} continue {
$i++;
}
(Except the scope of $i is slightly different.)
An alternative would be the do-while construct, although it is a little ungainly.
my $i;
do {
push #arr, $value if condition;
} while ( $i++ < #arr );

Perl explicit package in nested loops

I declared this array:
my #array
And in this code block...
for (my $i=0; $i<$j; $i++) {
do {
// stdout operations
} while (! ($arr != 1 ));
}
The error is specifically in the } while (! ($arr != 1 )); line.
Here's the specific error:
Global symbol "$arr" requires explicit package name at exer4bernal.pl line 71.
Why do I have this problem in 2 levels of nested loops? I never had this in only 1 level. What should I change to fix this? Thanks!
What you are seeing is totally unrelated to nesting of loop. What Perl is trying to tell you is that it doesn't know about the $arr variable. Did you mean #array or $#array?
Normally, you shouldn't be using do...while blocks. What is $arr? Where is that value declared? Where is it changed in your while loop? What is $j?
Actually, what are you trying to do with a double loop? This is usually considered bad programming because when you move from processing x elements to y elements, you increase your processing time by y2- (x * y);
Maybe this is more what you mean?
for my $index ( (0..$#array) ) {
next if $array[$index] = 1;
...
}
Note I got rid of that ugly C Style for loop and replaced it with one that's easier to understand.

Perl programming: continue block

I have just started learning Perl scripting language and have a question.
In Perl, what is the logical reason for having continue block work with while and do while loops, but not with for loop?
From http://perldoc.perl.org/functions/continue.html
If
there is a continue BLOCK attached to
a BLOCK (typically in a while or
foreach ), it is always executed just
before the conditional is about to be
evaluated again, just like the third
part of a for loop in C.
Meaning that in the for loop, the third argument IS the continue expression, e.g. for (initialization; condition; continue), so therefore it is not needed. On the other hand, if you use for in the foreach style, such as:
for (0 .. 10) {
print "$i\n";
} continue { $i++ }
It will be acceptable.
I suspect that the continue block isn't used in for loops since it is exactly equivalent to the for loop's 3rd expression (increment/decrement, etc.)
eg. the following blocks of code are mostly equivalent:
for ($i = 0; $i < 10; $i++)
{
}
$i = 0;
while ($i < 10)
{
}
continue
{
$i++;
}
You can use a continue block everywhere it makes sense: with while, until and foreach loops, as well as 'basic' blocks -- blocks that aren't part of another statement. Note that you can use the keyword for instead of foreach for the list iteration construct, and of course you can have a continue block in that case.
As everybody else said, for (;;) loops already have a continue part -- which one would you want to execute first?
continue blocks also don't work with do { ... } while ... because syntactically that's a very different thing (do is a builtin function taking a BLOCK as its argument, and the while part is a statement modifier). I suppose you could use the double curly construct with them (basic block inside argument block), if you really had to:
do {
{
...;
continue if $bad;
...;
}
continue {
...; # clean up
}
} while $more;

What's the difference between 'for' and 'foreach' in Perl?

I see these used interchangeably. What's the difference?
There is no difference. From perldoc perlsyn:
The foreach keyword is actually a synonym for the for keyword, so you can use foreach for readability or for for brevity.
I see these used interchangeably.
There is no difference other than that of syntax.
Ever since its introduction in perl-2.0, foreach has been synonymous with for. It's a nod to the C shell's foreach command.
In my own code, in the rare case that I'm using a C-style for-loop, I write
for (my $i = 0; $i < $n; ++$i)
but for iterating over an array, I spell out
foreach my $x (#a)
I find that it reads better in my head that way.
Four letters.
They're functionally identical, just spelled differently.
From http://perldoc.perl.org/perlsyn.html#Foreach-Loops
The foreach keyword is actually a synonym for the for keyword, so you
can use either. If VAR is omitted, $_ is set to each value.
# Perl's C-style
for (;;) {
# do something
}
for my $j (#array) {
print $j;
}
foreach my $j (#array) {
print $j;
}
However:
If any part of LIST is an array, foreach will get very confused if you
add or remove elements within the loop body, for example with splice.
So don't do that.
The foreach keyword is actually a synonym for the for keyword, so you can use foreach for readability or for for brevity. (Or because the Bourne shell is more familiar to you than csh, so writing for comes more naturally.) If VAR is omitted, $_ is set to each value.
There is a subtle difference (http://perldoc.perl.org/perlsyn.html#Foreach-Loops) :
The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn. If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop. This implicit localization occurs only in a foreach loop.
This program :
#!/usr/bin/perl -w
use strict;
my $var = 1;
for ($var=10;$var<=10;$var++) {
print $var."\n"; # print 10
foo(); # print 10
}
print $var."\n"; # print 11
foreach $var(100) {
print $var."\n"; # print 100
foo(); # print 11 !
}
sub foo {
print $var."\n";
}
will produce that :
10
10
11
100
11
In case of the "for" you can use the three steps.
1) Initialization
2) Condition Checking
3) Increment or decrement
But in case of "foreach" you are not able increment or decrement the value. It always take the increment value as 1.