snakespan snakespan - 4 years ago 120
Perl Question

Matching optional query parameters using the variable name

I want to create a hash of optional query parameters that are sometimes passed to my subroutine. Sometimes a query parameter called

welcome
is passed in, and the value is either 1 or 0.

If that variable exists, I want to add it to a hash.

I've created a configuration value called OPTIONAL_URL_PARAMS which is a list of expected parameter names that can be passed in:

use constant OPTIONAL_URL_PARAMS => ("welcome")


So far I have:

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
}
}
}


But this tries to use the value of
$self->{$param}
instead of its name. i.e. I want welcome to match
welcome
, but it's trying to match 1 instead.

I know when it comes to keys in a hash you can use
keys %hash
, but is there a way you can do this with regular variables?

Edit



My subroutine is being called indirectly:

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

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


If
$optionalParam
's variable name is 'welcome', then I want to try and map it to the constant
welcome
.

cxw cxw
Answer Source

Edit

In Perl, when you pass arguments to a subroutine, all the values are flattened into a single list (reference). Specifically, if you are passing parameters to a sub, the sub doesn't know the names of the variables you originally used. It only knows their values. Therefore, if you want names as well as values, you have to pass them separately. An easy way is using a hash. E.g., in new():

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

Then you can say URL::Handler->new($param, 'welcome' => 1), and $therest{welcome} will have the value 1. You can also say

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

and %therest will have the two keys welcome and another.

See also some further discussion of passing whole hashes as parameters

Original

This also probably doesn't answer the question!

Some thoughts on the code from your comment.

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

Some thoughts:

  • use strict; and use warnings; at the top of your source file, if you haven't yet.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download