为什么Perl严格不允许我传递参数哈希?

时间:2010-05-26 14:35:15

标签: perl strict

我有一个perl子例程,我希望将参数作为哈希传递 (目的是根据参数'iconsize'包含一个css。)

我正在使用电话:

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

用于子程序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);
}

为什么会产生错误消息:

执行运行模式'start'时出错:undef错误 - 无法使用字符串(“iconsize”)作为HASH引用,而在第334行的CheckBar.pm中使用“strict refs” < / p>

我在这里做错了吗? 还有其他方法可以将我的数据('iconsize')作为哈希提交吗?

(我还是Perl的新手)

编辑:对我有用的解决方案。我没有改变电话,但我的功能是:

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,
        }
    );
}

4 个答案:

答案 0 :(得分:12)

您正在参数列表的第一个参数上使用散列解除引用运算符(%{ })。但是这个参数是不是哈希引用,它只是字符串'iconsize'。你可以通过以下两种方式之一做你想做的事:

传递匿名哈希引用:

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

或者继续传递正常列表,就像你现在一样,并相应地更改你的功能:

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

请注意,在此版本中,我们只是将参数列表直接分配给哈希(在提取$self之后)。这是有效的,因为name => value对的列表只是普通列表的语法糖。

我更喜欢第二种方法,因为没有特别好的理由构造匿名hashref然后立即取消引用它。

在这篇文章中还有一些关于它如何运作的好信息:Object-Oriented Perl constructor syntax

答案 1 :(得分:6)

您尝试使用字符串strict refs作为哈希引用,从而违反了iconsize

我想你只是想:

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

第一个参数将进入$self,其余参数通过从@_的其余部分中获取项目对来创建哈希。

答案 2 :(得分:4)

使用参数作为列表传递哈希

您需要使用@_变量而不是shift。像这样:

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

在perl中哈希和对哈希的引用之间存在差异。然后将'iconsize' => '32'作为参数传递,这意味着将 list 传递给perl,它可以被解释为 hash

使用参数作为哈希引用传递哈希

但是当你尝试%{ shift || {} } perl时,期望第二个参数是一个哈希引用。在这种情况下,您可以通过以下方式修复它:

get_function_bar_begin({ 'iconsize' => '32' }); ## make anonymous hash for params

答案 3 :(得分:1)

问题在于这一行:

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

这不会像你想象的那样传递散列引用,而是散列,它作为被调用者的列表出现。因此,当您执行%{ shift }时,您只需移动键'iconsize',而不是整个列表。解决方案实际上是使函数的第二行更简单:

my %template_params = @_;