daxim
daxim

Reputation: 39158

short-cut for named parameters from appropriately named variables

My function is

use 5.028;
use strictures;
use Kavorka qw(fun);

fun foobar(:$foo, :$bar) { say $foo, $bar; }

I need to pass it named arguments, not positional arguments.

foobar('quux', 'quuuux');
# Unknown named parameter: quux at … line 5.
#         main::foobar("quux", "quuuux") called at … line 7

but

foobar(foo => 'quux', bar => 'quuuux');
# ok

Hashes or HashRefs are accepted, too.

my %args = (foo => 'quux', bar => 'quuuux');
foobar(%args);
my $args = {foo => 'quux', bar => 'quuuux'};
foobar($args);

In ES6 exists a short-cut where variables in an object literal are expanded (ed: MDN link?):

function foobar({foo, bar}) { console.log(foo, bar); }
foobar({foo: 'quux', bar: 'quuuux'});
const foo = 'quux';
const bar = 'quuuux';
foobar({foo: foo, bar: bar});
foobar({foo, bar}); // NB!

In Perl 6 a : prefixed variable in a parameter signature will create a key of the same name:

use v6;
sub foobar(:$foo, :$bar) { say $foo, $bar; }
foobar(foo => 'quux', bar => 'quuuux');
my $foo = 'quux';
my $bar = 'quuuux';
foobar(foo => $foo, bar => $bar);
foobar(:$foo, :$bar); # NB!

How can you accomplish something comparable in effect for Perl 5?

my $foo = 'quux';
my $bar = 'quuuux';
foobar(???);

Upvotes: 4

Views: 229

Answers (1)

TBSliver
TBSliver

Reputation: 666

I have a couple of ways of doing it, using either PadWalker (thanks for the suggestion mob) or Hash Slices:

use strict;
use warnings;
use Data::Dumper;
use PadWalker qw/ var_name /;

sub test_sub { print Dumper [ @_ ] }

my %vars;

$vars{foo} = "foo_data";
$vars{bar} = "var_data";

test_sub( %{vars}{qw/ foo bar/} );

# nv = named variables ( rename as needed )
sub nv { map { ( substr( var_name(1, \$_), 1) => $_ ) } @_ }

my $foo = 'foo_stuff';
my $bar = 'bar_stuff';

test_sub( nv( $foo, $bar ) );

Which gives:

$VAR1 = [
          'foo',
          'foo_data',
          'bar',
          'var_data'
        ];
$VAR1 = [
          'foo',
          'foo_stuff',
          'bar',
          'bar_stuff'
        ];

Had to do the substr in nv otherwise it shows the sigil, but thats about the best I can think of without going into deeper magic.

Without using nv, that will require more deep magic manipulation...

Using your Kavorka code as well:

use 5.020;
use strictures;
use Kavorka qw(fun);
use PadWalker qw/ var_name /;

fun foobar(:$foo, :$bar) { say $foo, $bar; }

my %vars;

$vars{foo} = "foo_data";
$vars{bar} = "var_data";

foobar( %{vars}{qw/ foo bar/} );

# nv = named variables ( rename as needed )
sub nv { map { ( substr( var_name(1, \$_), 1) => $_ ) } @_ }

my $foo = 'foo_stuff';
my $bar = 'bar_stuff';

foobar( nv( $foo, $bar ) );

gives:

foo_datavar_data
foo_stuffbar_stuff

I dont have 5.28 installed locally unfortunately heh

Upvotes: 4

Related Questions