TheAschr
TheAschr

Reputation: 973

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

Upvotes: 1

Views: 131

Answers (2)

zdim
zdim

Reputation: 66883

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 reference of) arguments for the callback

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

Upvotes: 2

Jim Garrison
Jim Garrison

Reputation: 86774

You can turn it into a hash reference easily with just

{@a}

and dereference entries with, for example

({@a})->{key}

Here's a debugger log:

$ perl -de0

Loading DB routines from perl5db.pl version 1.49_001
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> @a = ('a',1,'b',2,'c',3)

  DB<2> x @a
0  'a'
1  1
2  'b'
3  2
4  'c'
5  3
  DB<3> x {@a}
0  'a'
1  1
2  'b'
3  2
4  'c'
5  3
  DB<4> x ({@a})
0  HASH(0x804d82e0)
   'a' => 1
   'b' => 2
   'c' => 3
  DB<5> x ({@a})->{c}
0  3

Upvotes: 1

Related Questions