2
#!/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?

Borodin
  • 126,100
  • 9
  • 70
  • 144
sarthak
  • 774
  • 1
  • 11
  • 27

3 Answers3

3

EXPLANATION

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.


SOLUTION

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) {
    ...
  }
}
Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
2

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.

Borodin
  • 126,100
  • 9
  • 70
  • 144
1

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

Demo

Also see: Perl 5.20 and the fate of smart matching and given-when?

Community
  • 1
  • 1
Chankey Pathak
  • 21,187
  • 12
  • 85
  • 133
  • Sadly, from 5.18 Perl also gains the experimental warnings for given and when, as your "Also see" link describes. :( – kmarsh Oct 14 '15 at 13:52