使用变量名匹配可选的查询参数

时间:2017-02-03 12:49:37

标签: perl

我想创建一个可选查询参数的哈希值,有时会传递给我的子例程。有时会传入名为welcome的查询参数,值为1或0.

如果该变量存在,我想将其添加到哈希。

我已经创建了一个名为OPTIONAL_URL_PARAMS的配置值,它是一个可以传入的预期参数名称列表:

use constant OPTIONAL_URL_PARAMS => ("welcome")

到目前为止,我有:

my $tempParams = {};

if ( $optionalParam ) {

    foreach my $param (@{&OPTIONAL_URL_PARAMS}) {

        if ($optionalParam eq $self->{$param}) {

            $tempParams->{$param} = $optionalParam;
            $tempParams->{$param} =~ s/\s+//g; # strip whitespace 
        }   
    }
}

但是这会尝试使用$self->{$param}而不是其名称。即我希望欢迎与welcome匹配,但它试图匹配1。

我知道在哈希中你可以使用keys %hash的密钥,但有没有办法可以用常规变量做到这一点?

修改

我的子程序被间接调用:

my $url_handler = URL::Handler->new($param, $optionalParam); 

sub new { 
    my $class = shift; 
    my $args = @_; 
    my $self = { 
        param          => $args{param}, 
        optionalParams => $args{optionalParam} 
    };
} 

如果$optionalParam的变量名是“欢迎”,那么我想尝试将其映射到常量welcome

3 个答案:

答案 0 :(得分:3)

这不再是一个答案,但我还是无法将其删除,因为仍在进行讨论以澄清问题。

foreach my $param (@{&OPTIONAL_URL_PARAMS}) {
     # ...
}

OPTIONAL_URL_PARAMS的返回值(你这里已经有错误了,这就是为什么你有&,应该告诉你的东西......)只是一个列表,而不是一个数组引用。实际上此时它应该抛出错误,因为不能将1用作数组引用

答案 1 :(得分:1)

修改

在Perl中,当您将参数传递给子例程时,所有值都会被展平为一个列表(reference)。具体来说,如果要将参数传递给sub,则子不知道您最初使用的变量的名称。它只知道自己的价值观。因此,如果您需要名称和值,则必须单独传递它们。一种简单的方法是使用哈希。例如,new()

    my $class = shift;
    my $param = shift;    # The first, required parameter
    my %therest = (@_);   # Optional parameters, if any

然后您可以说URL::Handler->new($param, 'welcome' => 1)$therest{welcome}的值为1。你也可以说

URL::Handler->new($param, 'welcome'=>1, 'another'=>42);

%therest将有两个键welcomeanother

另见some further discussion将整个散列作为参数传递

原始

这也可能无法回答这个问题!

对您评论中的代码的一些想法。

my $url_handler = URL::Handler->new($param, $optionalParam); 
sub new { 
    my $class = shift;   # OK; refers to URL::Handler
    my $args = @_;       # Problematic: now $args is the _number_ of args passed (list @_ evaluated in scalar context).
    my $self = { 
        # There is no %args hash, so the next two lines are not doing what you expect.
        # I actually don't know enough perl to know what they do! :)
        param => $args{param},   
        optionalParams => $args{optionalParam} 
    };
}

一些想法:

  • use strict;use warnings;位于源文件的顶部,如果还没有。

答案 2 :(得分:1)

我认为除了Algol 60之外,没有任何语言可以支持这一想法。它违背了封装的想法,并阻止您使用数组或散列元素,函数调用,常量或表达式作为调用的实际参数

变量名纯粹是为了方便程序员 ,并且不参与任何正在运行的程序的功能。如果您愿意,可以使用单个数组@memory编写代码并使用“变量”$memory[0]$memory[1]等等。但是您将绕过编译器技术中最有用的部分允许我们将可读文本与内存位置相关联。一旦程序运行,最好将这些名称视为丢失

被调用的代码应该仅对传递的感兴趣,如果作为实际参数传递的变量的名称在子例程中是重要的,那将是一场噩梦

如果您能够访问作为参数传递的变量的名称,如果调用看起来像这样,您认为将向子例程stats提供什么

stats( ( $base[$i] + 0.6 + sum(@offset{qw/ x y /}) + sum(@aa) ) / @aa )

总之,一般情况下不能这样做。如果您需要将值与名称相关联,那么您可能应该查看哈希值

您的代码

my $url_handler = URL::Handler->new($param, $optionalParam); 

sub new { 
    my $class = shift; 
    my $args = @_; 

    my $self = { 
        param          => $args{param}, 
        optionalParams => $args{optionalParam} 
    };
}

有很多问题

您正确shift参数数组@_中的类名称,但随后设置my $args = @_,将$args设置为元素数留在@_。但$args的价值无关紧要,因为你再也不用了它

然后使用hash $self中的值将%args设置为使用两个元素创建的新匿名哈希。但%args不存在,因此两个元素的值都为undef。如果您将use strictuse warnings 'all'放在适当的位置,您会收到此警告

您用来访问此不存在的哈希的密钥是paramoptionalParam,我认为它们与调用的实际参数的名称相匹配并非巧合到new

虽然Perl的不寻常之处在于它允许以编程方式访问其符号表,但它是一种神秘且未经推荐的方法。 这些名称实际上对程序和程序员 是隐藏的,而像Exporter这样的模块必须操纵符号表才能完成工作,基类中的任何此类行为都是如此软件是非常值得避免的

最后,在定义它之后,再也不会再使用$self。你应该根据$class变量(包含字符串URL::Handler)将它祝福到一个类中并从构造函数中返回它

我希望这会有所帮助