Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I take a reference to an array slice in Perl?

How would you take a reference to an array slice such that when you modify elements of the slice reference, the original array is modified?

The following code works due to @_ aliasing magic, but seems like a bit of a hack to me:

my @a = 1 .. 10;
my $b = sub{\@_}->(@a[2..7]);
@$b[0, -1] = qw/ < > /;
print "@a\n";
# 1 2 < 4 5 6 7 > 9 10

Anyone have a better / faster way?

Edit: the code example above is simply to illustrate the relationship required between @a and $b, it in no way reflects the way this functionality will be used in production code.

like image 608
Eric Strom Avatar asked Nov 30 '09 00:11

Eric Strom


People also ask

How do I reference an array in Perl?

Creating a reference to a Perl array If we have an array called @names, we can create a reference to the array using a back-slash \ in-front of the variable: my $names_ref = \@names;. We use the _ref extension so it will stand out for us that we expect to have a reference in that scalar.

How do I slice an array in Perl?

Array slicing can be done by passing multiple index values from the array whose values are to be accessed. These values are passed to the array name as the argument. Perl will access these values on the specified indices and perform the required action on these values. print "Extracted elements: " .

How do I add elements to the middle of an array in Perl?

How to insert an element in the middle of an array in Perl? In this case we used splice to insert an element. Normally the second parameter (the offset) defines where to start the removal of elements, but in this case the third parameter - the number of elements - was 0 so splice has not removed any elements.

Can you slice arrays?

The slice() method returns a shallow copy of a portion of an array into a new array object selected from start to end ( end not included) where start and end represent the index of items in that array. The original array will not be modified.


2 Answers

Data::Alias seems to be able to do what you want:

#!/usr/bin/perl

use strict; use warnings;

use Data::Alias;

my @x = 1 .. 10;

print "@x\n";

my $y = alias [ @x[2 ..7] ];
@$y[0, -1] = qw/ < > /;

print "@x\n";

Output:

1 2 3 4 5 6 7 8 9 10
1 2 < 4 5 6 7 > 9 10
like image 54
Sinan Ünür Avatar answered Oct 23 '22 21:10

Sinan Ünür


That's how you do it, yes. Think about it for a bit and it's not such a hack; it is simply using Perl's feature for assembling arbitrary lvalues into an array and then taking a reference to it.

You can even use it to defer creation of hash values:

$ perl -wle'my %foo; my $foo = sub{\@_}->($foo{bar}, $foo{baz}); print "before: ", keys %foo; $foo->[1] = "quux"; print "after: ", keys %foo'
before: 
after: baz
like image 39
ysth Avatar answered Oct 23 '22 23:10

ysth