How to pass hash as sub parameter?

R

Rui Maciel

I want to pass a hash to a sub through as a sub parameter. In order to do so I've written the
following sub:


<code>
sub print_http(;%)
{
if(@_ != 0)
{
my (%params) = $_[0]; # line 15
print "Content-Type: ";
exists $params{"type"} ? print $params{"type"}: print "text/html"; #line 17
print "; ";
exists $params{"charset"} ? print $params{"charset"}: print "charset=ISO-8859-1";
}
else
{
print "Content-Type: text/html; charset=ISO-8859-1";
}
print "\n\n";
}
</code>


Yet, it throws the following error messages:

test.pl: Odd number of elements in hash assignment at ./index.pl line 15.
test.pl: Use of uninitialized value $params{"type"} in print at ./index.pl line 17.


What am I doing wrong? And what's the best way to pass a hash to a sub?


Thanks in advance,
Rui Maciel
 
S

sreservoir

I want to pass a hash to a sub through as a sub parameter. In order to do so I've written the
following sub:


<code>
sub print_http(;%)
{
if(@_ != 0)
{
my (%params) = $_[0]; # line 15
print "Content-Type: ";
exists $params{"type"} ? print $params{"type"}: print "text/html"; #line 17
print "; ";
exists $params{"charset"} ? print $params{"charset"}: print "charset=ISO-8859-1";
}
else
{
print "Content-Type: text/html; charset=ISO-8859-1";
}
print "\n\n";
}
</code>


Yet, it throws the following error messages:

test.pl: Odd number of elements in hash assignment at ./index.pl line 15.
test.pl: Use of uninitialized value $params{"type"} in print at ./index.pl line 17.


What am I doing wrong? And what's the best way to pass a hash to a sub?

% doesn't actually check parameters. you'll have to use carp and do
checking manually.
 
J

Jürgen Exner

Rui Maciel said:
I want to pass a hash to a sub through as a sub parameter. In order to do so I've written the
following sub: [...]
my (%params) = $_[0]; # line 15

$_[0] is a single scalar ...
Yet, it throws the following error messages:

test.pl: Odd number of elements in hash assignment at ./index.pl line 15.

.... and a single scalar is certainly an odd number of elements.
What am I doing wrong?

Are you passing a hash ref or the hash itself as argument? In the first
case dereference $_[0] before assigning to %params, in the second case
just assign the whole array @_ to %params.
Either way, assigning just the first element is wrong.
And what's the best way to pass a hash to a sub?

There is no single answer to that question, both methods are valid. It
really depends on what you want to do, e.g. modify the hash or the
content of the hash, how large is the hash, are there other parameters
for the sub, ...

jue

jue
 
S

sln

I want to pass a hash to a sub through as a sub parameter.
You don't pass a hash, either a reference to one, or a listized hash.
In order to do so I've written the
following sub:


<code>
sub print_http(;%)
You prototype here ...
{
if(@_ != 0)
But here, if @_ is empty, a prototype mismatch message appears
{
my (%params) = $_[0]; # line 15
print "Content-Type: ";
exists $params{"type"} ? print $params{"type"}: print "text/html"; #line 17
print "; ";
exists $params{"charset"} ? print $params{"charset"}: print "charset=ISO-8859-1";
}
else
{
print "Content-Type: text/html; charset=ISO-8859-1";
}
print "\n\n";
}
</code>


Yet, it throws the following error messages:

test.pl: Odd number of elements in hash assignment at ./index.pl line 15.
test.pl: Use of uninitialized value $params{"type"} in print at ./index.pl line 17.


What am I doing wrong? And what's the best way to pass a hash to a sub?


Thanks in advance,
Rui Maciel

If you are going to prototype and accept the possible mismatch message,
you have to check for the eveness or accept the warning or:

sub print_http(;%){
if (@_%2) {
print "not even-sized list\n";
return;
}
...
}

Or, without a prototype is better:
sub print_http {
if (@_%2) {
print "not even-sized list\n";
return;
}
...
}

The other option is to pass a hash reference.

-sln
 
R

Rui Maciel

sreservoir said:
% doesn't actually check parameters. you'll have to use carp and do
checking manually.

Now that's a turn-off. I was under the impression that providing a function prototype would be
enough for this. So how is it possible to write a Perl sub which enforces the types of it's
arguments?


Rui Maciel
 
R

Randal L. Schwartz

Rui> Now that's a turn-off. I was under the impression that providing a
Rui> function prototype would be enough for this. So how is it possible
Rui> to write a Perl sub which enforces the types of it's arguments?

Yes. Use MooseX::Declare.
 
J

Jürgen Exner

Rui Maciel said:
Now that's a turn-off. I was under the impression that providing a function prototype would be
enough for this. So how is it possible to write a Perl sub which enforces the types of it's
arguments?

The only type of argument you can pass to a Perl sub are scalars which
are passed as a flat list.
Therefore your question is meaningless: there is one and only one type
of argument.

jue
 
S

Skye Shaw!@#$

Now that's a turn-off.  I was under the impression that providing a function prototype would be
enough for this.  So how is it possible to write a Perl sub which enforces the types of it's
arguments?

die "usage: print_http(HASH)" unless @_ and @_ % 2 == 0;
die "usage: print_http(ARRAYREF)" unless isa $_[0], 'ARRAY';

There's Params::Validate (http://search.cpan.org/~drolsky/Params-
Validate-0.95/lib/Params/Validate.pm)
though I think it is overkill for simple cases like yours.
 
R

Rui Maciel

You don't pass a hash, either a reference to one, or a listized hash.

Thanks for the help, sln. I was left with the impression that @_ stored a list of parameters in the
sense that if someone passed a set of arrays to a sub then @_ would be a list of lists. So, passing
two lists as parameters means that the sub only gets a long, concatenated list?


Thanks for the help,
Rui Maciel
 
R

Rui Maciel

J�rgen Exner said:
The only type of argument you can pass to a Perl sub are scalars which
are passed as a flat list.
Therefore your question is meaningless: there is one and only one type
of argument.

If it is meaningless then how do you explain Perl's function prototyping and it's explicit support
for array, hash, code and glob parameters?


Rui Maciel
 
J

Jürgen Exner

Rui Maciel said:
Thanks for the help, sln.

Oh, is that idiot still around? I had no idea....
I was left with the impression that @_ stored a list of parameters in the
sense that if someone passed a set of arrays to a sub then @_ would be a list of lists. So, passing
two lists as parameters means that the sub only gets a long, concatenated list?

perldoc perlsub:

The Perl model for function call and return values is simple: all
functions are passed as parameters one single flat list of scalars[..]
Any arrays or hashes in these call and return lists will
collapse, losing their identities--[...]

If you know of a way how to word this even more explicit then please let
us know.

jue
 
R

Rui Maciel

Randal said:
Rui> Now that's a turn-off. I was under the impression that providing a
Rui> function prototype would be enough for this. So how is it possible
Rui> to write a Perl sub which enforces the types of it's arguments?

Yes. Use MooseX::Declare.

Thanks for the tip, Randal. It looks promising. Nevertheless, I've never heard of Moose before,
which may quite possibly be due to the fact that I'm practically just starting out. So, do you
happen to know if Mosse has been widely adopted or is it an obscure feature of Perl?


Thanks for the help,
Rui Maciel
 
R

Rui Maciel

Tad said:
Can it be that you have not read even as far as the 2nd paragraph
of the description of Perl's subroutines?

If you happen to take the time to google "perl sub tutorial" you will learn that the first hit from
perl.org does not rank very high.


Rui Maciel
 
U

Uri Guttman

RM> If it is meaningless then how do you explain Perl's function
RM> prototyping and it's explicit support for array, hash, code and
RM> glob parameters?

because you haven't read the docs enough or correctly. prototypes are
misnamed and not what you seem to think they are. they are NOT for
verifying types of arguments passed to subs. they are mostly useful for
converting some types to known types. it allows you to declare a sub
that can look like a builtin - e.g. a push which takes an array (not an
array ref) as it first arg. normally a sub can't do that.

so stop with your ranting about what you think perl prototypes do and
learn what they actually do. most decent perl hackers avoid prototypes
and only use them when they do something important. checking param types
is done in other ways.

uri
 
R

Rui Maciel

J�rgen Exner said:
If you know of a way how to word this even more explicit then please let
us know.

Do you believe you are doing anyone any favours by posting condescending messages?


Rui Maciel
 
U

Uri Guttman

RM> If you happen to take the time to google "perl sub tutorial" you
RM> will learn that the first hit from perl.org does not rank very
RM> high.

and if you use google to learn programming, you must be very high!

perl has a very solid set of docs that come with it. you don't need
google to find them. try reading them and learn about perl's subs before
you go off on rants like this.

uri
 
U

Uri Guttman

RM> Do you believe you are doing anyone any favours by posting
RM> condescending messages?

pot meet kettle.

you have not been gracious at all in asking for help nor in how you
reply to answers. me thinks you are not going to do well in the
programming world with an attitude like that.

uri
 
R

Randal L. Schwartz

Rui> So, do you happen to know if Mosse has been widely adopted or is it
Rui> an obscure feature of Perl?

Yes.

:)
 
J

Jürgen Exner

Rui Maciel said:
Do you believe you are doing anyone any favours by posting condescending messages?

Obviously you did not understand that documentation, therefore I repeat
my request: if you know of a better way to describe that arguments for
Perl subs are flat lists then please let us know.

jue
 
J

Jürgen Exner

Rui Maciel said:
If you happen to take the time to google "perl sub tutorial"

Why would anybody do that?
you will learn that the first hit from
perl.org does not rank very high.

So? Neither does oreilly.com nor pick-your-favourite-domin for that
matter None of those domains have much to do with the documentation of
Perl subroutines.

If you are really searching Google for an online tutorial for Perl then
I honestly feel sorry for you: as has been discussed in this NG many
times the vast majority of those tutorials simply stink.
If you are familiar with programming then just use the standard Perl
documentation that comes with any Perl installation. Yes, it even has
tutorials for many non-trivial areas like references, regular
expressions, etc, etc.. If the standard documentation is missing, then
someone tried to save a few MBs of storage in a very wrong place.

And if you need to start at a lower level and begin with the basics then
I strongly suggest one of the beginner's books that are recommended in
the FAQ, see "perldoc -q books".

jue
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top