REQ: Help with hash reference to a module

J

Joe

Hello all,

Old C programmer here. Trying to pass a reference to a hash to a sub
routine in a module.
Have seen many posts about references, nothing seems to work in the case
of modules.

The following example currently returns the error:
Type of arg 3 to MYSTUFF::parseAssociative must be hash (not reference
construct
or) at main.pl line 9, near "%myListeners )"
Execution of main.pl aborted due to compilation errors.


I would like it to say:
L= adam, hello0
L= Nothing, hello1
L= Something, hello2

Here are the two files:

test.pl
------------------------------------------------
use MYSTUFF;

my %myListeners;
my $test1 = "Nothing";
my $test2 = "Something";

$myListeners{"adam"} = "Hello0";

MYSTUFF::myWorst( $test1, $test2, \%myListeners );

foreach $listener (sort(keys %myListeners)) {
print "L= $listener, $myListeners{$listener}\n";
}

exit;
------------------------------------------------


MYSTUFF.pm
------------------------------------------------
package MYSTUFF;

sub myWorst ($$\%) {

my ($first, $second, %refArray) = @_;

$refArray{$first} = "hello1";
$refArray{$second} = "hello2";

}

1;
 
I

ioneabu

Joe said:
Hello all,

Old C programmer here. Trying to pass a reference to a hash to a sub
routine in a module.
Have seen many posts about references, nothing seems to work in the case
of modules.

The following example currently returns the error:
Type of arg 3 to MYSTUFF::parseAssociative must be hash (not reference
construct
or) at main.pl line 9, near "%myListeners )"
Execution of main.pl aborted due to compilation errors.


I would like it to say:
L= adam, hello0
L= Nothing, hello1
L= Something, hello2

Here are the two files:

test.pl
------------------------------------------------
use MYSTUFF;

my %myListeners;
my $test1 = "Nothing";
my $test2 = "Something";

$myListeners{"adam"} = "Hello0";

MYSTUFF::myWorst( $test1, $test2, \%myListeners );

foreach $listener (sort(keys %myListeners)) {
print "L= $listener, $myListeners{$listener}\n";
}

exit;
------------------------------------------------


MYSTUFF.pm
------------------------------------------------
package MYSTUFF;

sub myWorst ($$\%) {

my ($first, $second, %refArray) = @_;

$refArray{$first} = "hello1";
$refArray{$second} = "hello2";

}

1;

try this:

#!/usr/bin/perl

use strict;
use warnings;

package MYSTUFF;

#the forced parameters thing here
#is something I need to read up on too.
sub myWorst ($$\%) {
my ($first, $second, $refArray) = @_;
${$refArray}{$first} = "hello1";
${$refArray}{$second} = "hello2";
}

package main;

my %myListeners;
my $test1 = "Nothing";
my $test2 = "Something";

$myListeners{"adam"} = "Hello0";

#looks like you use hash and it is passed by reference
#due to the parameter list thing you did above
MYSTUFF::myWorst( $test1, $test2, %myListeners );

foreach my $listener (sort(keys %myListeners)) {
print "L= $listener, $myListeners{$listener}\n";
}
 
S

Sherm Pendley

Joe said:
Old C programmer here. Trying to pass a reference to a hash to a sub
routine in a module.

The problem is how you've declared your sub, not the fact that it's in a
module. You've declared it as taking a hash, but passing it a hash
reference.
sub myWorst ($$\%) {

The subroutine declared here takes a hash as its third argument, and passes
it by reference. You'd call it like this:

myWorst($foo, $bar, %baz);

Inside myWorst(), you'd fetch the arguments like this:

my ($foo, $bar, $baz) = @_;

Note that in the above, $baz is a reference to %baz - that happens
automagically, as a result of the backslash in the prototype.

If you want to explicitly pass a reference, as opposed to having one created
for you automagically, you need to declare the argument as a scalar:

sub myWorst ($$$) {

Then you can call your sub the way you want to:

myWorst($foo, $bar, $bazRef);

You can find more about prototypes in "perldoc perlsub".

sherm--
 
C

Chris Mattern

Joe said:
Hello all,

Old C programmer here. Trying to pass a reference to a hash to a sub
routine in a module.
Have seen many posts about references, nothing seems to work in the case
of modules.

The following example currently returns the error:
Type of arg 3 to MYSTUFF::parseAssociative must be hash (not reference
construct
or) at main.pl line 9, near "%myListeners )"
Execution of main.pl aborted due to compilation errors.


I would like it to say:
L= adam, hello0
L= Nothing, hello1
L= Something, hello2

Here are the two files:

test.pl
------------------------------------------------
use MYSTUFF;

my %myListeners;
my $test1 = "Nothing";
my $test2 = "Something";

$myListeners{"adam"} = "Hello0";

MYSTUFF::myWorst( $test1, $test2, \%myListeners );

foreach $listener (sort(keys %myListeners)) {
print "L= $listener, $myListeners{$listener}\n";
}

exit;
------------------------------------------------


MYSTUFF.pm
------------------------------------------------
package MYSTUFF;

sub myWorst ($$\%) {

my ($first, $second, %refArray) = @_;

$refArray{$first} = "hello1";
$refArray{$second} = "hello2";

}

1;

You're passing a reference just fine. What you're NOT doing
is *dereferencing* it--your subroutine treats it as if it
were a hash instead of a reference to one. Your assignment
statement should be:

my ($first, $second, $refArray) = @_;

since a reference is always itself a scalar, regardless of what
it may point to.

Then, you have to dereference the reference when you want
to use the hash:

$$refArray{$first} = "hello1";
$$refArray{$second} = "hello2";

--
Christopher Mattern

"Which one you figure tracked us?"
"The ugly one, sir."
"...Could you be more specific?"
 
S

Sherm Pendley

Chris said:
You're passing a reference just fine.

.... to a subroutine which has been explicitly prototyped as taking a hash as
its third argument. Hence the error Joe mentioned:
The following example currently returns the error:
Type of arg 3 to MYSTUFF::parseAssociative must be hash

You're right about dereferencing the passed-in reference though. That would
be the next issue to address, after fixing the prototype so that the sub
will take a reference in the first place.

sherm--
 
J

Joe

thank you, that worked the way I was hoping.


thanks everyone else too.




(e-mail address removed) wrote in @z14g2000cwz.googlegroups.com:
 
B

Bill Smith

Joe said:
Hello all,

Old C programmer here. Trying to pass a reference to a hash to a sub
routine in a module.
Have seen many posts about references, nothing seems to work in the case
of modules.




The "Old C Programmer" probably thinks that perl prototypes mean the
same thing as "C" function prototypes. Although they appear similar,
the intent is quite different.

Refer to the prototype section of perldoc perlsub.

"...Because the intent of this feature is primarily to let you
define subroutines that work like built-in functions,..."

Unlike "C", they provide only a limit compile-time type checking. The
effect depends on the use (or non-use) of ampersand and parens in the
call. (I never can remember these rules. They are documented in detail
in the section referenced above.) I strongly recommend against routine
use of perl prototypes.

I do not see your error, but I suspect that your attempt to use
prototypes contributes to it.


Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,111
Latest member
KetoBurn
Top