Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello all.

As a user of a perl script with no knowledge of perl, it's a bit tricky trying to locate the exact problem. So here I am seeking wisdom from PerlMonks. Posted below is the code snippet originally from https://github.com/mjpost/dptsg/scripts//annotate_spinal_grammar.pl

while (my $line = <>) { chomp $line; my $tree = build_subtree($line); walk_postorder($tree,[\&mark_heads,\&annotate]); #####offending line's below####### @{$tree->{children}}[0]->{label} =~ s/^\*//; # undo top-level merge print build_subtree_oneline($tree,1), $/; }

I've marked the offending line. Would appreciate being guided through resolving error "Can't use an undefined value as a HASH reference at dptsg/scripts/annotate_spinal_grammar.pl line xx, <> line 1."

Thank you.

Replies are listed 'Best First'.
Re: Can't use an undefined value as a HASH reference
by BrowserUk (Patriarch) on Aug 25, 2015 at 15:44 UTC

    It means that this part of that line:  @{ $tree->{children} }[ 0 ], which is the first element of an array, pointed at by the value of the element of the hash, pointed to by $tree, and keyed by the string 'children'; is undefined -- ie. has not been set -- thus when the code tries to use that undefined value as a hash reference ->{label}, you get the error message.

    All of which probably won't help you at all if you don't know Perl; even if you have some experience of other programming languages.

    What you will need to determine is whether:

    1. the code that build the tree is in error and is failing to construct the tree correctly;
    2. Of if the calling code is in error; by unconditionally expecting that array element to contains a hash reference that contains a key: label.

    And the first part of making that determination would be to inspect the source data from which the tree is constructed, and work out whether the undefined value should be set or not.

    If, it should, then the code that constructs the tree will need correcting; if it shouldn't, the the attempt to access the undefined value should be made conditional.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
    I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!

      Ok, yeah, gives an idea. Below is a portion of the build_tree() subroutine.

      sub build_subtree { my ($line,$lexicon) = @_; # minimal sanity check if ($line !~ /^\(.*\)\s*$/) { return undef; }

      And $line is: 1 , 4885

      It's not passing the sanity test.

        In that case, you could make either of two changes:

        1. Modify the sanity test to die if the input data is malformed.
        2. Modify the failing code to test for undef before attempting to dereference the hashref.

        But there is the school of thought termed the robustness principle, that goes Be conservative in what you send, be liberal in what you accept.

        I would do both: make the sanity test issue a warning (with file line number) and then return undef; and add a test for undef before dereferencing.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
        I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!
Re: Can't use an undefined value as a HASH reference
by stevieb (Canon) on Aug 25, 2015 at 15:38 UTC

    Print out your data to see if it is really what you think it is. Part of the data structure hasn't been populated.

    use Data::Dumper; ... print Dumper $tree->{children}[0]; # if the above produced more than "$VAR1 = {};" or "$VAR1 = undef;", p +ost # those results back here. If it didn't, perform the following # and post those results print Dumper $tree; ... @{$tree->{children}}[0]->{label} =~ s/^\*//;
      while (my $line = <>) { chomp $line; my $tree = build_subtree($line); print Dumper $tree->{children}[0]; print Dumper $tree; walk_postorder($tree,[\&mark_heads,\&annotate]); @{$tree->{children}}[0]->{label} =~ s/^\*//; # undo top-level merge print build_subtree_oneline($tree,1), $/; }

      I did have to use both prints. They gave output below.

      $VAR1 = undef; $VAR1 = { 'children' => [] };

      Not sure where to go from here. But would the $line input be the cause of the problem? The build_subtree($line) subroutine uses it as input.

      Also, the correct link to the original script is here: https://github.com/mjpost/dptsg/blob/master/scripts/annotate_spinal_grammar.pl

        Ok, so now take a step back, and tell us what data you are sending into your script, ie. how you are calling it and with what arguments (post a example snip from the input file).

        We need to know what is in $line. I can't get to the link with the rest of the code, so I'm unsure how build_subtree compiles its data, and what it expects to find. Do you have another link, or can you post the full code?