tags:

views:

233

answers:

4

I hava a perl subroutine where i would like to pass parameters as a hash (the aim is to include a css depending on the parameter 'iconsize').

I am using the call:

get_function_bar_begin('iconsize' => '32');

for the subroutine get_function_bar_begin:

use strict;
...
sub get_function_bar_begin
{
    my $self = shift;
    my %template_params = %{ shift || {} };

    return $self->render_template('global/bars   /tmpl_incl_function_bar_begin.html',%template_params);
}

Why does this yield the error message:

Error executing run mode 'start': undef error - Can't use string ("iconsize") as a HASH ref while "strict refs" in use at CheckBar.pm at line 334

Am i doing something wrong here? Is there an other way to submit my data ('iconsize') as a hash?

(i am still new to Perl)

EDIT: Solution which worked for me. I didn't change the call, but my function:

sub get_function_bar_begin
{
    my $self = shift;
    my $paramref = shift;
    my %params = (ref($paramref) eq 'HASH') ? %$paramref : ();
    my $iconsize = $params{'iconsize'} || '';

    return $self->render_template('global/bars/tmpl_incl_function_bar_begin.html',
        {
            'iconsize'  => $iconsize,
        }
    );
}
+6  A: 

You're violating strict refs by trying to use the string iconsize as a hash reference.

I think you just want:

my( $self, %template_params ) = @_;

The first argument will go into $self and the rest create the hash by taking pairs of items from the rest of @_.

brian d foy
i still get "Odd number of elements in hash assignment at CheckBars.pm line 333."
Thariama
@Thariama: brian's example was for a method, but the way you're calling the function in the actual question was as a function (where there is no `$self` argument). You should probably read up on `perldoc perlsub` (http://perldoc.perl.org/perlsub.html).
Ether
thx, will do that
Thariama
thx brian for your answer - i got two of your books on my desk :)
Thariama
@Thariama: Having Brian's books on your desk is good, reading them is better ! :)
sebthebert
i am - i am, but still new to Perl
Thariama
+4  A: 

Passing hash with parameters as list

You need to use @_ variable instead of shift. Like this:

my %template_params = @_; ## convert key => value pairs into hash

There is different between hashes and references to hash in perl. Then you pass 'iconsize' => '32' as parameter this means list to perl, which can be interpreited as hash.

Passing hash with parameters as hash reference

But when you try %{ shift || {} } perl expect second parameter to be a hash references. In this case you can fix it in following way:

get_function_bar_begin({ 'iconsize' => '32' }); ## make anonymous hash for params
Ivan Nevostruev
i still get "Odd number of elements in hash assignment at CheckBars.pm line 333."
Thariama
`$self` is needed only for methods. Remove `my $self = shift;` line if you're calling function as `get_function_bar_begin(...)`. (Methods should be called as `$instance->method_name(...)`, but this is another story)
Ivan Nevostruev
thx for your answer
Thariama
+1  A: 

The problem is this line:

get_function_bar_begin('iconsize' => '32');

This does not pass a hash reference, as you seem to think, but a hash, which appears as a list to the callee. So when you do %{ shift }, you're only shifting the key 'iconsize', not the entire list. The solution is actually to make the second line of your function simpler:

my %template_params = @_;
JSBangs
It doesn't pass a hash at all, it passes a list. All subroutine arguments in Perl are lists.
friedo
what about $self?
Thariama
@Thariama, $self is passed as a hidden first argument to your function, assuming that it's called through a blessed reference (`$obj->get_function_bar_begin(@args)`. If you're not calling `get_function_bar_begin` through an object, then you shouldn't be shifting `$self` off of `@_`! This might be why you're also getting the error about "Odd number of elements in hash assignment".
JSBangs
thx for your answer
Thariama
+11  A: 

You are using the hash-dereferencing operator ( %{ } ) on the first argument of your parameter list. But that argument is not a hash reference, it's just the string 'iconsize'. You can do what you want by one of two ways:

Pass an anonymous hash reference:

get_function_bar_begin( { 'iconsize' => '32' } );

Or continue to pass a normal list, as you are right now, and change your function accordingly:

sub get_function_bar_begin {
    my $self = shift;
    my %template_params = @_;
}

Notice in this version that we simply assign the argument list directly to the hash (after extracting $self). This works because a list of name => value pairs is just syntactic sugar for a normal list.

I prefer the second method, since there's no particularly good reason to construct an anonymous hashref and then dereference it right away.

There's also some good information on how this works in this post: Object-Oriented Perl constructor syntax.

friedo
way one still gives me "undef error - Can't use string ("iconsize") as a HASH ref while "strict refs" in use",way two gives "Reference found where even-sized list expected at CheckBars.pm line 334"
Thariama
Thariama, you're doing things backwards. *Either* use `$self->get_function_bar_begin( { ... } )` and extract the reference with `%{ }` *OR* use `$self->get_function_bar_begin( ... )` and build the hash with `%params = @_`. The errors you're getting suggest you're trying to mix and match both approaches.
friedo
i tried both ways, but found a solution now (see my edited post)
Thariama