Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereferencing values from an array to declared variables in one line

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?

like image 308
MattLBeck Avatar asked Mar 16 '12 12:03

MattLBeck


People also ask

How do you dereference an array?

You cannot dereference an array, only a pointer. What's happening here is that an expression of array type, in most contexts, is implicitly converted to ("decays" to) a pointer to the first element of the array object. So ar "decays" to &ar[0] ; dereferencing that gives you the value of ar[0] , which is an int .

What is dereferencing a variable?

Dereferencing is used to access or manipulate data contained in memory location pointed to by a pointer. *(asterisk) is used with pointer variable when dereferencing the pointer variable, it refers to variable being pointed, so this is called dereferencing of pointers.

How do I declare multiple pointers in one line?

and a single statement can declare multiple variables of the same type by simply providing a comma-separated list ( ptr_a, ptr_b ), then you can declare multiple int-pointer variables by simply giving the int-pointer type (int *) followed by a comma-separated list of names to use for the variables ( ptr_a, ptr_b ).

What does the dereference operator (*) do?

In computer programming, a dereference operator, also known as an indirection operator, operates on a pointer variable. It returns the location value, or l-value in memory pointed to by the variable's value. In the C programming language, the deference operator is denoted with an asterisk (*).


2 Answers

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.

like image 134
Zaid Avatar answered Oct 11 '22 12:10

Zaid


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.

like image 21
Axeman Avatar answered Oct 11 '22 12:10

Axeman