The statements inside the label executes even if the condition fails.Can anyone explain what I'm doing here wrong? - perl

my $a =10;
my $b =200;
my $c,$d;
goto UP if ($a > 20);
$d = $c + $b;
print "$d\n";
UP:
$c = $b -$a;
print "$c\n";
The above statements inside the label executes even if the condition fails.

It seems like you are mixing up how the labels and goto work. In fact, goto should never be used for flow control. It's really confusing.
This is how your code runs at the moment:
As you can see, the last two statements (those are after your UP label) are always executed. Perl will check the condition, and if it is true, skip ahead. If the condition is false, it runs the two statements following immediately, and then runs the label and the rest.
Labels don't make subroutines in Perl. They just give a line a name. The line of code is still executed normally.
If you want to do one or the other instead, you need an if-else construct. That's done like this in Perl.
my $a = 10;
my $b = 200;
my ( $c, $d );
if ($a > 20) {
$c = $b -$a;
print "$c\n";
} else {
$d = $c + $b;
print "$d\n";
}
Since you seem to insist on goto, you can make that work, but you need to tell it to stop execution.
my $a =10;
my $b =200;
my $c,$d;
goto UP if ($a > 20);
$d = $c + $b;
print "$d\n";
exit; # <------------- this stops execution and ends the program
UP:
$c = $b -$a;
print "$c\n";
Of course your code won't do much, because both $c and $d are undef.
You should really turn on use strict and use warnings, and fix the problems both of these pragmata will show you.
Also note that $a and $b are reserved variables to be used inside sort.

The code you posted is equivalent to the following:[1]
A: my $a = 10;
B: my $b = 200;
C: my ($c, $d);
D: goto G if $a > 20;
E: $d = $a + $b;
F: print "$d\n";
G: $c = $b - $a;
H: print "$c\n";
As this better demonstrates, code execution doesn't stop once a label is encountered.
To emulate an if-then-else structure, you'd use
my $a = 10;
my $b = 200;
$a > 20 and goto ELSE;
my $d = $a + $b;
print "$d\n";
goto END;
ELSE:
my $c = $b - $a;
print "$c\n";
END:
You probably know this, but the following is a lot clearer and provides better scoping:
my $a = 10;
my $b = 200;
if ($a <= 20) {
my $d = $a + $b;
print "$d\n";
} else {
my $c = $b - $a;
print "$c\n";
}
After a couple of off-topic fixes

Related

what is the usage of \& and $expr->()

sub reduce(&#) {
my $expr = \&{shift #ARG};
my $result = shift #ARG;
while (scalar #ARG > 0) {
our $a = $result;
our $b = shift #ARG;
$result = $expr->();
}
return $result;
}
I cannot really understand some grammar in this code. Anyone can explain to me? like \& and $result = $expr->()
\&name returns a reference to the subroutine named name.
$code_ref->() calls the subroutine referenced by $code_ref.
$ perl -e'
sub f { CORE::say "Hi" }
my $code_ref = \&f;
$code_ref->();
'
Hi
In your case, shift #ARG returns a subroutine reference. \&{ $code_ref } simply returns the code ref. As such,
my $expr = \&{shift #ARG};
could have been written as
my $expr = shift #ARG;
Note that reduce's prototype allows it to be called as
reduce { ... } ...
but what is actually executed is
reduce( sub { ... }, ... )
Note that this version of reduce is buggy. You should use the one provided by List::Util.
local $a and local $b should have been used to avoid clobbering the values its caller might have in $a and $b.
This version of reduce expects its callback to have been compiled in the same package as reduce itself. Otherwise, the callback sub won't be able to simply use $a and $b.
Declaring the variables using our is actually completely useless in this version case since $a and $b are exempt from use strict; checks, and the undeclared use of $a and $b would access the very same package variables.
Having a look some List::Util::reduce() examples will probably help.
Let's take the first one:
$foo = reduce { $a > $b ? $a : $b } 1..10;
So reduce takes a BLOCK followed by a LIST, which the function signature declares: sub reduce(&#) {. The block in our case is the statement $a > $b ? $a : $b, while the list is 1..10. From the docs:
Reduces #list by calling "BLOCK" in a scalar context multiple times,
setting $a and $b each time. The first call will be with $a and $b set to
the first two elements of the list, subsequent calls will be done by
setting $a to the result of the previous call and $b to the next element
in the list.
Returns the result of the last call to the "BLOCK". If #list is empty then
"undef" is returned. If #list only contains one element then that element
is returned and "BLOCK" is not executed.
And now to an annotated version of the code:
$foo = reduce { $a > $b ? $a : $b } 1..10; # $foo will be set to 10
sub reduce(&#) {
# reduce() takes a BLOCK followed by a LIST
my $expr = \&{shift #ARG};
# $expr is now a subroutine reference, i.e.
# $expr = sub { $a > $b ? $a : $b };
# Start by setting $result to the first item in the list, 1
my $result = shift #ARG;
# While there are more items in the list...
while (scalar #ARG > 0) {
# Set $a to the current result
our $a = $result;
# Set $b to the next item in the list
our $b = shift #ARG;
# Set $result to the result of $a > $b ? $a : $b
$result = $expr->();
}
# List has now been reduced by the operation $a > $b ? $a : $b
return $result;
}

Perl: Change in Subroutine not printing outside of routine

So I want to change numbers that I pass into a subroutine, and then retain those numbers being changed, but it doesn't seem to work.
my $A = 0;
my $T = 0;
my $C = 0;
my $G = 0;
foreach my $bases in (keys %basereads){
count ($bases, $A, $T, $C, $G);
}
Here is my subroutine
sub count {
my $bases = shift;
my $A = shift;
my $T = shift;
my $C = shift;
my $G = shift;
for (my $i = 0; $i < length($bases); $i++){
print "$bases\t";
if (uc(substr($bases,$i,1)) eq 'A'){
$A++;
}elsif (uc(substr($bases,$i,1)) eq 'T'){
$T++;
} elsif (uc(substr($bases,$i,1)) eq 'G'){
$G++;
} elsif (uc(substr($bases,$i,1)) eq 'C'){
$C++;
} else { next; }
}
print "$A\t$C\t$T\t$G\n";
return my($bases, $A, $T, $C, $G);
}
after the subroutine, I want to stored the altered A, C, T, G into a hashmap. When I print bases and ATCG inside the subroutine, it prints, so I know the computer is running through the subroutine, but it's not saving it, and when I try to manipulate it outside the subroutine (after I've called it), it starts from zero (what I had defined the four bases as before). I'm new to Perl, so I'm a little weary of subroutines.
Could someone help?
Always include use strict; and use warnings; at the top of EVERY script.
With warnings enabled, you should've gotten the following messages:
"my" variable $bases masks earlier declaration in same scope at script.pl line ...
"my" variable $A masks earlier declaration in same scope at script.pl line ...
"my" variable $T masks earlier declaration in same scope at script.pl line ...
"my" variable $C masks earlier declaration in same scope at script.pl line ...
"my" variable $G masks earlier declaration in same scope at script.pl line ...
These are caused by the my before your return statement:
return my($bases, $A, $T, $C, $G);
Correct this by simply removing the my:
return ($bases, $A, $T, $C, $G);
And then you just need to capture your returned values
($bases, $A, $T, $C, $G) = count($bases, $A, $T, $C, $G);
Given that you're new to perl, I'm sure you won't be surprised that your code could be cleaned up further though. If one uses a hash, it makes it a lot easier to count various characters in a string, as demonstrated below:
use strict;
use warnings;
my $A = 0;
my $T = 0;
my $C = 0;
my $G = 0;
foreach my $bases (keys %basereads) {
my %counts;
for my $char (split //, $bases) {
$counts{$char}++;
}
$A += $counts{A};
$T += $counts{T};
$C += $counts{C};
$G += $counts{G};
}

Perl calculator reads in numbers will not do calculation

I have a problem with my simple calculator program. It is not performing the calculation with my if statement: it goes straight to the else.
#!/usr/bin/perl
print "enter a symbol operation symbol to and two numbers to make a calculation";
chomp($input = <>);
if ($input eq '+') {
$c = $a + $b;
print $c;
}
elsif ($input eq '-') {
$c = $a - $b;
print $c;
}
elsif ($input eq '*') {
$c = $a * $b;
print $c;
}
elsif ($input eq '/') {
$c = $a / $b;
print $c;
}
elsif ($input eq '%') {
$c = $a % $b;
print $c;
}
elsif ($input eq '**') {
$c = $a**$b;
print $c;
}
elsif ($input eq 'root') {
$c = sqrt($a);
$c = sqrt($b);
print $c;
}
else {
print " you messed up" . "$input" . "$a" . "$b";
}
To start off with, you need to add strict and warnings to the top of your script
#!/usr/bin/perl
use strict;
use warnings;
That is going to alert you to a lot of syntax errors, and force you to completely rethink/refactor your code. This is a good thing though.
One obvious thing is that $a and $b are never initialized at all. And your first if is missing the dollar sign before input.
I would change the capturing of your variables to the following:
print "enter a symbol operation symbol to and two numbers to make a calculation";
chomp(my $input = <>);
my ($operation, $x, $y) = split ' ', $input.
I'd also lean away from using $a and $b as variable names, as they are special variables used by perl's sort. Once your certain that you're getting your input properly, then start working the rest of your logic.
You forgot '$' sign in the first condition before input:
if($input eq '+'){
$c = $a + $b;
print $c;
my $a = shift(#ARGV); // first argument is a
my $b = shift(#ARGV); // second argument is b
my $input = shift(#ARGV); // third argument is an operator
if($input eq '+'){...
Also, I would recommend 'use strict' and 'use warnings' at the top unless you're proficient at Perl.

How to use variables in a equation using Perl

I'm trying to use possible variables in a equation with Perl.
For example:
#!/usr/bin/perl -w
$a = "yellow";
$b = "orange";
$c = "col1fl0ur";
$c = $a + $b;
print "$a + $b = $c \n";
I want to be able to state the value for each variable $a, $b, $c, then be able to say that
$a + $b = "col1fl0ur"
You may ask; whats the point? just print out col1fl0ur, butI want to be able to use many more variables as well, such as in this case:
#!/usr/bin/perl -w
###values###
$a = "yellow";
$b = "orange";
$c = "col1fl0ur";
$d = "derp";
$e = "oplo";
$f = "qwerty";
###defining the equation###
$c = $a + $b;
$d = $a + $c;
$f = $d + $c;
###Printing###
print "$a + $b = $c \n";
print "$a + $c = $d \n";
print "$d + $c = $f \n";
It would help a lot if you explained your real problem, but something like this may help.
Note that you should never use $a and $b in live code as they are reserved variable names.
use strict;
use warnings;
my ($a, $b, $c, $d, $e, $f) = qw( yellow orange col1fl0ur derp oplo qwerty );
### defining the equation ###
my %sum;
$sum{$a}{$b} = $c;
$sum{$a}{$c} = $d;
$sum{$d}{$c} = $f;
### Printing ###
for my $pair ([$a, $b], [$a, $c], [$d, $c]) {
my ($p1, $p2) = #$pair;
printf "%s + %s = %s\n", $p1, $p2, $sum{$p1}{$p2};
}
output
yellow + orange = col1fl0ur
yellow + col1fl0ur = derp
derp + col1fl0ur = qwerty
If you want $b + $a to be the same as $a + $b then you will have to say so explicitly. For example,
$sum{$a}{$b} = $c;
$sum{$b}{$a} = $c;
you may use Overload pragma..
You can create a new package as follows:
package Tst;
use overload "+" => \&myadd;
sub new {
my $class = shift;
my $value = shift;
return bless \$value => $class;
}
sub myadd {
my ($x, $y) = #_;
$x = ref($x) ? $$x : $x;
$y = ref($y) ? $$y : $y;
my $value = '';
if ($x eq 'yellow' and $y eq 'orange'){
$value = 'col1fl0ur';
}
return $value;
}
1
Then in your Main program, you can do the things you like:
use Tst;
my $a = Tst->new('yellow');
my $b = Tst->new('orange');
my $c = $a + $b;
say $c;
This prints out col1fl0ur.
Rather than assigning values to Perl variables ($a, $b, $c, etc.) you might consider creating a data structure that will suit your purposes (whatever they may be!?!). Borodin's answer takes a partial step in that direction.
This example takes that idea a bit farther: the terms in your "mathematical" system would not be linked to individual Perl variables; instead they would be components of a larger data structure.
use strict;
use warnings;
my %xs = (
a => 'yellow',
b => 'orange',
c => 'col1fl0ur',
d => 'foo',
e => 'bar',
f => 'fubb',
g => 'blub',
);
$xs{'a + b'} = $xs{c};
$xs{'a * c'} = $xs{d};
$xs{'d / c'} = $xs{f};
$xs{'a + b - d + f'} = $xs{g};
printf("%15s = %s\n", $_, $xs{$_}) for sort keys %xs;
Output:
a = yellow
a * c = foo
a + b = col1fl0ur
a + b - d + f = blub
b = orange
c = col1fl0ur
d = foo
d / c = fubb
e = bar
f = fubb
g = blub

What kind of syntactic sugar is available in Perl to reduce code for l/rvalue operators vs. if statements?

There's a bunch out there, as Perl is a pretty sugary language, but the most used statements in any language is the combination of if statements and setting values. I think I've found many of them, but there's still a few gaps. Ultimately, the goal would be to not have to write a variable name more than once:
Here's what I have so far:
$r ||= $s; # $r = $s unless ($r);
$r //= $s; # $r = $s unless (defined $r);
$r &&= $s; # $r = $s if ($r);
$r = $c ? $s : $t; # if ($c) { $r = $s } else { $r = $t }
$c ? $r : $s = $t; # if ($c) { $r = $t } else { $s = $t }
$r = $s || $t; # if ($s) { $r = $s } else { $r = $t }
$r = $s && $t; # if ($s) { $r = $t } else { $r = $s = undef, 0, untrue, etc. }
$c and return $r; # return $r if ($c);
$c or return $r; # return $r unless ($c);
$c and $r = $s; # $r = $s if ($c);
#$r{qw(a b c d)} # ($r->{a}, $r->{b}, $r->{c}, $r->{d})
Somebody also had a really interesting article on a "secret operator", shown here:
my #part = (
'http://example.net/app',
( 'admin' ) x!! $is_admin_link,
( $subsite ) x!! defined $subsite,
$mode,
( $id ) x!! defined $id,
( $submode ) x!! defined $submode,
);
However, what I've found to be missing from the list is:
$r <= $s; # read as "$r = min($r, $s);" except with short-circuiting
$r = $s if (defined $s); # what's the opposite of //?
$r and return $r # can that be done without repeating $r?
Is there anything else worth adding? What other conditional set variables are available to reduce the code? What else is missing?
These structures from your question could be written a little bit more clearly using the low precedence and and or keywords:
$c and return $r; # return $r if ($c);
$c or return $r; # return $r unless ($c);
$c and $r = $s; # $r = $s if ($c);
The nice thing about and and or is that unlike the statement modifier control words, and and or can be chained into compound expressions.
Another useful tool for syntactic sugar is using the for/foreach loop as a topicalizer over a single value. Consider the following:
$var = $new_value if defined $new_value;
vs
defined and $var = $_ for $new_value;
or things like:
$foo = "[$foo]";
$bar = "[$bar]";
$_ = "[$_]" for $foo, $bar;
the map function can also be used in this manner, and has a return value you can use.
There's also the left hand side ternary operator:
$cond ? $var1 : $var2 = "the value";
is equivalent to:
if ($cond) {
$var1 = "the value";
} else {
$var2 = "the value";
}
$r = $r < $s ? $r : $s;:
$r = $s if $r > $s;
or
use List::Util qw( min );
$r = min($r, $s);
or:
sub min_inplace {
my $min_ref = \shift;
for (#_) { $$min_ref = $_ if $$min_ref > $_; }
}
min_inplace($r, $s);
$r = $s if (defined $s);:
$r = $s // $r;
$r = $t; $r = $s if (defined $s);:
$r = $s // $t;
$r = !$s ? $s : $t;:
$r = $s && $t;
One of the biggest called for features in Perl was the switch statement. This finally appeared in Perl 5.10. I'm just using the example from the documentation:
use feature qw(say switch); #My preference
#use feature ":5.10"; #This does both "say" and "switch"
[...]
given($foo) {
when (undef) {
say '$foo is undefined';
}
when ("foo") {
say '$foo is the string "foo"';
}
when ([1,3,5,7,9]) {
say '$foo is an odd digit';
continue; # Fall through
}
when ($_ < 100) {
say '$foo is numerically less than 100';
}
when (\&complicated_check) {
say 'a complicated check for $foo is true';
}
default {
die q(I don't know what to do with $foo);
}
}
Why o' why did they go with given/when and not switch/case like you find in most languages is a mystery to me. And, why if the statement is given/when, do you specify it in use features as switch?
Alas, the people who made these decisions are at a higher plane than I am, so I have no right to even question these luminaries.
I avoid the more exotic stuff, and stick with the easiest to understand syntax. Imagine the person who has to go through your code and find a bug of add a feature, which would be easier for that person to understand:
$r &&= $s;
or
if ($r) {
$r = $s;
}
And, maybe I might realize that I really meant:
if (not defined $r) {
$r = $s;
}
And, in this case, I might even say:
$r = $s if not defined $r;
Although I don't usually like post-fixed if statements because people tend to miss the if part when glancing through the code.
Perl is compiled at runtime, and the compiler is fairly efficient. So, even though it's way cooler to write $r &&= $s and it earns it earns you more geek points and is less to type, it doesn't execute any faster. The biggest amount of time spent on code is on maintaining it, so I'd rather skip the fancy stuff and go for readability.
By the way, when I think of syntactic sugar, I think of things added to the language to improve readability. A great example is the -> operator:
${${${$employee_ref}[0]}{phone}}[0];
vs.
$employee_ref->[0]->{phone}->[0];
Of course, if you're storing data as a reference to a list to a hash to a list, you are probably better off using object oriented coding.
There's also:
$hash{$key||'foo'} = 1; # if($key) { $hash{$key} = 1 } else { $hash{'foo'} = 1 }