in reply to Understanding variable scope in perl

Hey Guys. This is so frustrating. I added some code as suggested:
push( @next_cell_arr, $protein_matrix[$row][$col+1] );# - note: 'right +' cell is first element of array push( @next_cell_arr, $protein_matrix[$row+1][$col+1] );# - no +te: 'diagonal' cell is second element of array push( @next_cell_arr, $protein_matrix[$row+1][$col] );# - note +: 'bottom' cell is third element of array # - debug $arr_len = scalar @next_cell_arr; for( $var = 0; $var < $arr_len; $var++ ){ print $next_cell_arr[$var]; print "\n"; } print "\n\n"; #exit; # - debug # - if all values are equal, then the sequence gets a match of + suffers a mismatch (diagonal move), and not a gap penalty. This als +o saves me from having to compute the max of the three cells my $val1 = $next_cell_arr[0] || die "val1 is undefined!!\n"; my $val2 = $next_cell_arr[1] || die "val2 is undefined!!\n"; my $val3 = $next_cell_arr[2] || die "val3 is undefined!!\n";
When I run my code, $val1 is indeed not being defined, but the debug loop, right above, $next_cell_arr[0] is displaying the correct value. This makes absolutely no sense to me. Something so incredibly simple is not working here. EDIT: By the way, I always use the -w flag, but adding 'use warnings' might be easier

Replies are listed 'Best First'.
Re^2: Understanding variable scope in perl
by graff (Chancellor) on Sep 29, 2005 at 21:58 UTC
    Regarding this kind of logic:
    my $val1 = $next_cell_arr[0] || die "val1 is undefined!!\n";
    You need to understand a subtle difference between things that evaluate to false, and things that are "undefined". In a nutshell:
    use strict; my $val1; # this creates a named storage location for a scalar value, # but DOES NOT ASSIGN A VALUE -- its value is undefined. my $val2 = 0; # creates a named scalar and assigns a value, so it's d +efined # but the value will evaluate to FALSE in a # boolean sense my $val3 = ''; # similar to $val2: it's defined, it evaluates to false # in boolean tests, but in "reality", it's an # "empty string" (which $val2 is not) print "val3 is an empty string\n" if ( $val3 eq '' ); print "val2 is an empty string\n" if ( $val2 eq '' ); print "val1 is (like) an empty string\n" if ( $val1 eq ''); # this third test would generate a warning in "perl -w" my $i = 1; for ( $val1, $val2, $val3 ) { print "val$i evaluates to false\n" if ( ! $_ ); print "val$i is undefined\n" if ( ! defined( $_ )); $i++; }
    Now, bear in mind that the "||" operator applies a boolean test: the expression that follows it is evaluated only if the expression that precedes it evaluates to false. Do you have empty strings or zeros in your matrix cells?

    Based on the original statement of the problem, are you sure that the very first thing ever pushed onto your "@next_cell_arr" array is a defined value? Are you sure that the array is empty before you do the first of your three pushes from "@protein_matrix"?

      The answer to your questions are yes and yes. Just before I push values from my '@protein_matrix' to my '@next_cell_arr' matrix, I have debug code that shows all the values of my '@protein_matrix', becaue I did some computations in it before hand. When I didn't have the '|| die' code in there, perl threw errors stating that I'm trying to use uninitialized values.
Re^2: Understanding variable scope in perl
by liverpole (Monsignor) on Sep 29, 2005 at 19:14 UTC
    So, to follow the previous advice, what happens when you *also* put "use strict;" in your program?
      sorry, I just came from class. when I add 'use strict', perl throws a lot of compilation errors asserting that almost all of my global symbols require explicit package naming. I guess it means that I need to prefix everything with main::, no?
        No worries!

        Actually, no, you don't need to prefix everything with "main::", though that would certainly be one way to go about it.

        Better to make global only the few things that you really want to have global, by putting them at the top of your program, and prefixing them with my:

        # My global variables (Actually, these should really be constants...) my $boiling_point_fahrenheit = 212; my $known_other_universes = 0; my $answer_to_everything = 42;
        You should make everything else local (actually lexically-scoped) with my prefixing it.

        A good test of whether a given variable should be global or not:  if you were convert most or all of the subroutines in the program into separate packages, and import them to the main program as objects, would the variable be one that you'd like to retain in the main program (global!), or pass to the constructor or one of the methods of some object? (lexical!)

        So, go back and fix all of the errors that you get, and then let me know:  what kind of output do you get now??

Re^2: Understanding variable scope in perl
by kwaping (Priest) on Sep 29, 2005 at 19:13 UTC
    Try changing that || die to or die. It has to do with operator precedence (perldoc perlop for more info).
      I know what you're saying, but I don't believe it matters here.   Try commenting out either Dying(3) or Dying(4) below...
      #!/usr/bin/perl -w # Strict use strict; use warnings; # Assign $x my $x = 123; # Next 2 lines prove $x is defined. defined $x or die "Dying(1) because (defined \$x or die)\n"; defined $x || die "Dying(2) because (defined \$x || die)\n"; # Make $x undefined undef $x; # Doesn't matter which of the next 2 lines is commented-out (either wo +rks fine) defined $x || die "Dying(3) because (defined \$x || die)\n"; defined $x or die "Dying(4) because (defined \$x or die)\n";