user1709237
user1709237

Reputation:

How to pass a hash table by refrence Perl

I am currently trying to implement a suffix tree using Perl, however, when I attempt to set the reference for the tree function, the reference location is not set, if I pass the address via a string then check the text in the string vs the location of the hash table and they are different. Any help is appreciated!

use strict;
use warnings;
use Data::Dumper;

my $count = 0;
my $str; # holds the complete string
my %root;
# takes in all lines of code
open(IN, '<:encoding(UTF-8)', $ARGV[0]) or die "Could not open file '$ARGV[0]' $!\n";
while (<IN>) {
    chomp;
    # concatinates with string
    $str .= $_;
}
# closes input
close(IN);

#length of input string
my $l_size = length($str) - 1;
#recursively makes
sub tree {
    #recursive root
    my %treeRoot;
    #checking incomming data
    print "1 ".Dumper(\@_)."\n";
    #checking incomming data
    print "2 ".Dumper(\%root)."\n";
    #attempts to set tree's refrence
    \%treeRoot, $count = @_;
    #checking incomming data
    print "3 ".Dumper(\%root)."\n";
    #checking incomming data
    print "4 ".$count."\n";
    #leaf for each node
    my %leaf;
    for (my $i = 0; $i < $l_size; $i++) {
        #creates alphabet tree
        $treeRoot { substr($str, $i, 1) } = %leaf;
    }

    #checking incomming data
    print "5 ".Dumper(\%root)."\n";

    while ($count > 0) {
        #checking incomming data
        print "loop 6 ".Dumper(\%root)."\n";
        $count--;
        #checking incomming data
        print "loop 7 ".$count."\n";
        #recursion not implamented yet
        #tree(\$treeRoot{'a'}, $count);
    }
}

tree(\%root, 2);
#print Dumper(\%root);

Upvotes: 2

Views: 173

Answers (2)

TLP
TLP

Reputation: 67900

You need parentheses to disambiguate. This:

\%treeRoot, $count = @_;

means this:

\%treeRoot; 
$count = @_;

Because the assignment operator = has higher precedence than the comma operator ,. The warning that you got from running that code tells you this: Useless use of reference constructor in void context.

To pass the arguments correctly, you need parentheses:

(\%treeRoot, $count) = @_;

Unfortunately, this does not work, because you cannot assign to a reference this way. The following error tells you that: Can't modify reference constructor in list assignment.

So what you need is to pass the reference to a scalar:

my ($href, $count) = @_;
print $href->{'value'};

I think this method is a bit backwards, though. Passing variables by reference is likely to become a source of bugs. A more natural solution is to use the return value of the subroutine to assign values:

sub foo {
    my %hash;
    $hash{'value'} = ....
    ....
    return \%hash;
}

my $hashref = foo();
print $hashref->{'value'};

Upvotes: 3

Miller
Miller

Reputation: 35208

Your question isn't actually how to pass a hash reference, but how to receive it, as the following will not work:

\%treeRoot, $count = @_;

Basically, you need to assign your reference to a scalar like so:

use strict;
use warnings;

sub example_sub {
    my ($hashref, $count) = @_;

    # Add two values to the hash:
    $hashref->{newkey} = 'val';
    $hashref->{newkey2} = 'val2';
}

my %root;

example_sub(\%root, 2);

use Data::Dump;
dd \%root;

Outputs:

{ newkey => "val", newkey2 => "val2" }

If you don't want to modify your original hash, you can assign the values to a new hash within the sub:

my %newhash = %$hashref;

For more info on working with references, check out: perlref - Perl references and nested data structures

Upvotes: 0

Related Questions