TheAschr TheAschr - 8 months ago 126
Perl Question

Reduce array to anonymous hash code

Is there anyway to do something like this in perl (convert array hash and use it in one line)?

sub func{
#from this
my %args = @_;
print $args{test};

#to this
print %{@_}{test};
}


Im using it for passing errors to callbacks like javascript
use strict;
use warnings;

sub error{
my $msg = shift;
print("ERROR: $msg\n");
}

sub parse_args{
my %args = @_;
return $args{args};
}

sub do_something{
my $args = parse_args(
args=>{@_},
optional_args=>["fail_cb"]
);
if(!0){
return(exists $args->{fail_cb} ? $args->{fail_cb}->(err=>"not good") : 0);
}
}

do_something(
fail_cb => sub{error(({@_})->{err});}
);

Answer Source

Yes, by making it into a reference and then dereferencing

sub func { say ${{@_}}{key} }

(I must ask, do you really want to be doing this?)

The {@_} creates a hash reference, while ${ ... }{} syntax dereferences it (item 2).


Update to the question edit

Apparently, the intent is to run a callback. But then you need to run that callback

sub func { ${{@_}}{key}->() }

func( key => sub { say "cb here" } );

If you were to print the value, as asked, you'd get the code-reference itself, CODE(0x...)

Or, pass the hashref with a key and the cb arguments

my $hr = { k1 => sub { .. }, k2 => sub { .. }, .. };
...
func($hr, $key, $arrayref_cb_args);

sub func { $_[0]->{$_[1]}->(@{$_[2]}) }

where now func can decide dynamically what to run. This gives you far more flexibility in design.

For a ready test

perl -wE'
    sub tt { $_[0]->{$_[1]}->(@{$_[2]}) };
    tt( { k1 => sub { say "args: @_" }}, "k1", [qw(cb here)] )
'

prints the line   args: cb here

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download