7

To retrieve arguments from a function call I usually do

use strict;
use warnings;

foo([1,2],[3,4]);

sub foo{
    my ($x, $y) = @_;
    ...
}

In the example, $x and $y are now references to an array each. If I want to use the variables inside these arrays easily I dereference them first.

...
my ($x1, $x2) = @{$x}[0,1];
# ...same for $y

I'm wondering if there is a way to dereference the arguments in @_ (or, indeed, any other array) and return them to a list of declared variables in just one line?

MattLBeck
  • 5,701
  • 7
  • 40
  • 56

3 Answers3

8
foo ( [1,2], [3,4] );

sub foo {

    my ( $x1, $x2, $y1, $y2 ) = map @$_, @_;

    ...
}

The map takes @_ and dereferences each of its elements into an array with the @$_ operation.

One could also use List::Gen's deref or d functions to achieve the same goal.

Zaid
  • 36,680
  • 16
  • 86
  • 155
2

That's why I have unroll:

sub unroll (@) { 
    return map { ref() eq 'ARRAY' ? @$_ : ref() eq 'HASH' ? %$_ : $_ } @_;
}

So that I can go like this:

my ($x1, $y1, $x2, $y2) = unroll @_;

(or)

my ($x1, $y1, $x2, $y2) = &unroll;

A lot prettier than

map { @$_ } @_[0, 1]

and the like. Plus, it's a bit more robust.

Axeman
  • 29,660
  • 2
  • 47
  • 102
  • What's with the `@{[ ... ]}`, and what's with using `@_[0,1]` in some places and `@_` in others. False dichotomy! – ikegami Mar 16 '12 at 19:31
  • As for robustness, `map @$_, @_` works with all arrays, where `unroll` does not. Furthermore, `map @$_, @_` detects more bad inputs than `unroll` does. – ikegami Mar 16 '12 at 19:33
1

I don't get exactly what you want, but is this ok :

foo([1,2],[3,4]);
sub foo{
    my ($x1,$x2) = @{$_[0]}[0,1];
    say "x1=$x1 , x2=$x2";
}

output:

x1=1 , x2=2
Toto
  • 89,455
  • 62
  • 89
  • 125
  • That's not what the OP is asking about. He wants to fetch `($x1, $x2, $y1, $y2)` in one line. – Blagovest Buyukliev Mar 16 '12 at 12:56
  • I guess I could fetch them all by using `my ($x1,$x2,$y1,$y2) = (@{$_[0]}[0,1], @{$_[1]}[0,1]);`. So maybe I am simply wondering if there is a quick way to flatten an array of arrays :/ – MattLBeck Mar 16 '12 at 12:57