Ramblings

<rant>

Using named parameters without names when calling functions in perl

, ,

I just read my collegue Zbigniew Lukasiak's blog post about wanting to pass variables without doing redundant work like: foo({ email => $email, username => $username }). I totally loved the idea as I'm doing this kind of stuff all the time. And just passing an object reveals its internal representation, unless you add cascades of getters/setters which are really (most of time) revealing its internal representation anyway.

So, I noticed he got a comment that he could use Devel::Declare and do something like the Perl6 implementation of prototypes, but I think it can be even easier than that (as it requires you to actually make new keywords and what not.)

Enter autoparams.pl:
#!/usr/bin/perl -wl
use strict;
use warnings;
use PadWalker qw/var_name/;

use Data::Dumper;

{
  no strict 'refs';
  *{'main:::'} = sub {
    my $ret;
    my @params;

    foreach  (@_) {
      my $var_name = var_name(1,\$_);
      do { $ret->{substr $var_name, 1} = $_; next } if $var_name;
      push @params, $_;
    }
    return $ret, @params;
  };
}

sub foo {
  print Dumper(\@_);
}

my $a = 123;
my $b = 'abc';
my $c = { foo => 'bar' };

foo(&:($a, $b, $c, '456', '567'));

gives:
$ perl perl/autoparams.pl
$VAR1 = [
          {
            'c' => {
                     'foo' => 'bar'
                   },
            'a' => 123,
            'b' => 'abc'
          },
          '456',
          '567'
        ];

Of course the implementation details could be slightly different, but I'm thinking something like this might make sense.

Family picUsing map to have less explicit checks, good idea or bad?

Comments

Unregistered user Monday, December 12, 2011 9:23:37 AM

zby writes: Nice! I did not think I'll get an implementation that fast :) I think that the way to make it popular would be to stick to the Perl6 syntax. Maybe ':' could be a prefix operator? I have to admit I've always shied away from that low level hacking - because it always involves awful lot of special cases to consider.

Unregistered user Monday, December 12, 2011 3:33:52 PM

garu writes: I really like the fact that you're thinking out of the box, and I honestly hope you continue to do so: many great ideas come from this sort of experimentation. That said, I'm not sure this is such a good idea, mainly for 3 reasons: 1) If you must ask everybody using your code to name their own variables just like you use them internally, then you ARE exposing your internal representations anyway. 2) If one wishes to use two modules with that kind of constraints, one must hope both APIs share the very same internals, otherwise we'd have to do silly stuff like "my $othername = $somename;" all the time. 3) PadWalker's doesn't seem to work for arrays/hashes, only scalars (unless I'm doing something very wrong). See https://rt.cpan.org/Ticket/Display.html?id=70729 If your talking about a very restrictive and controlled environment, go for it. But even so I don't think this would scale very well, or add to maintainability for that matter. Besides, if you don't like your subs to receive hashes, you could just use a plain old regular list of parameters, such as foo($username, $email). You'd still have to boil those into your object/state/whatever though. Keep the ideas coming!

Unregistered user Monday, December 12, 2011 9:13:04 PM

zby writes: @garu - the idea is that you don't really expose anything more then you already are - you can call it both ways the new one is just shorter, but it is not required you can call it the old way as you always did.

Write a comment

New comments have been disabled for this post.

June 2013
M T W T F S S
May 2013July 2013
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30