Reputation: 794
#!/usr/bin/perl -w
use warnings;
use diagnostics;
use Switch;
open FH, "<$ARGV[0]" or die "$!";
sub commandType{
print "comm entered for $_";
switch($_){
case("add") {print "this is add\n"}
case("sub") {print "this is sub\n"}
case("neg") {print "this is neg\n"}
case("eq") {print "this is eq\n"}
case("gt") {print "this is gt\n"}
case("lt") {print "this is lt\n"}
case("and") {print "this is and\n"}
case("or") {print "this is or\n"}
case("not") {print "this is not\n"}
}
}
while(<FH>){
next if /^\s*\/\//;
next if /^\s*$/;
my $line = "$_";
$line =~ s/\s+$//;
print "$line\n";
commandType($line);
}
Here is my code which takes the input from the following file supplied to it through the command line:
// Pushes and adds two constants.
push constant 7
push constant 8
add
For each line of the file above the perl code will run the subroutine commandType
to check if it is among the given cases inside the subroutine and prints if it is. But even though the add command is present in the file above the code still does not print it. I am getting the following output:
push constant 7
comm entered for push constant 7
push constant 8
comm entered for push constant 8
add
comm entered for add`
Why is case "add" not printing anything?
Upvotes: 2
Views: 718
Reputation: 21676
Starting from Perl 5.10.1 (well, 5.10.0, but it didn't work right), you can say use feature "switch";
to enable an experimental switch feature. Under the "switch" feature, Perl gains the experimental keywords given
, when
, default
, continue
, and break
.
#!/usr/bin/perl
use strict;
use warnings;
use feature "switch";
while(my $line=<DATA>){
given ($line) {
when (/push/) { print 'found push' }
when (/add/) { print 'found add' }
}
}
__DATA__
push constant 7
push constant 8
add
Also see: Perl 5.20 and the fate of smart matching and given-when?
Upvotes: 1
Reputation: 126742
It isn't safe to use $_
as you would a normal variable. It has global scope and many built-in Perl operators act on it, so it is likely to be modified without any obvious reason.
In any case, the parameters passed to a subroutine are presented in @_
, not in $_
and it is random chance that it seems to contain the right value in this case.
Rewrite your commandType
subroutine like this and it should start behaving more sensibly
sub commandType {
my ($cmd) = @_;
print "comm entered for $cmd";
switch ($cmd) {
case 'add' { print "this is add\n" }
case 'sub' { print "this is sub\n" }
case 'neg' { print "this is neg\n" }
case 'eq' { print "this is eq\n" }
case 'gt' { print "this is gt\n" }
case 'lt' { print "this is lt\n" }
case 'and' { print "this is and\n" }
case 'or' { print "this is or\n" }
case 'not' { print "this is not\n" }
}
}
You must also always add use strict
at the top of every program, especially if you are asking for help with it. It will quickly report trivial errors that you may otherwise spend valuable time tracking down.
The Switch
module is also unsafe, and the built-in language construct given
/when
that has been available since version 10 has been marked as experimental because of a number of arcane shortcomings. You are much better off using a list of if
statements as described in the "Basic BLOCKs" section of perlsyn.
Upvotes: 2
Reputation: 63832
The problem is that $_
doesn't automatically refer to the first argument passed to a sub
, currently you are reading the same $_
as the one in your while-loop.
The value of $_
when inside commandType is the line read, still having the potential new-line attached to it, and since "add\n"
isn't equal to "add"
, your case isn't entered.
It would be preferred to change the contents of sub commandType
to the below:
sub commandType{
my $cmd = shift; # retrieve first argument
print "comm entered for $cmd";
switch($cmd) {
...
}
}
Upvotes: 3