#!/usr/bin/perl -w
use strict;
sub alias{ \@_ };
my @a = (1,"world");
my $arr = alias( $a[0], $a[0], $a[1] );
$arr->[0] = "hello";
print "@$arr\n";
I learned this ugly trick from demerphq while he was testing the aliasing features of his DDS module, so maybe looking at what the dumpers and their tests do might give you some more inspiration.
Updated: Fixed typo in sub alias, spotted by nothingmuch
Updated: I use strict; but the code won't run like that. That should teach me about posting when I don't cut'n'paste my code ... Spotted by The Mad Hatter | [reply] [d/l] |
I don't see how this helps the situation at all. He needs to alias one element of an array to another element of the array.
Update: hrm, I didn't follow the code properly. Yes, this is a solution to problem. My apologies, Corion.
_____________________________________________________
Jeff japhy Pinyan,
P.L., P.M., P.O.D, X.S.:
Perl,
regex,
and perl
hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
| [reply] |
It may well be that my solution misses the goal. As far as I understood it, nothingmuch wants two slots in an array to contain the same scalar, and I believe that my subroutine alias does that.
The routine returns a reference to an array in which the elements are aliased as passed in. So to create an array which aliases the slots 2,3 and 4, you would call it as:
my $v;
my $ar = alias("foo","bar",$v,$v,$v,"baz");
Assigning to any of the slots 2,3,4 of @$ar will change the other two slots as well, which is how I interpret the question.
I might well have misunderstood the question and the problem, as I also don't understand what he needs it for, or rather, what he needs it for prompts different solutions to me. | [reply] [d/l] |
use Array::RefElem 'av_store';
my @array;
av_store @array, 1, $array[0];
$array[1] = 2;
print "@array";
If you're bent on using Lexical::Alias, you can try the following
trick for your particular situation, though it's of little use for generic
array element aliasing. It's an answer to the first question from
How's your Perl?, adapted to Lexical::Alias.
use Lexical::Alias 'alias_a';
my @array;
{
my $t;
alias_a @{sub {\@_}->($t, $t)}, @array;
}
Warning: code untested!. I don't have my laptop which has my
custom Perl install with Lexical::Alias and Array::RefElem. Particularly the
second example might not work as advertised.
update: a monk confirms that code works on CB
| [reply] [d/l] [select] |
\$array[0] gives you an alias to the value stored in that slot of the array, which is half of what you need. To make $array[1] an alias to that value, you need to get a pointer to the slot $array[1], which isn't a concept that is exposed to Perl scripts. It is almost like you want \\$array[1] except that that gives you a reference to a temporary scalar that points to the same value rather than a reference to the array slot (Perl doesn't support references to array slots).
Lexical::Alias finds the extra layer of indirection by searching through internal structures (where the lexical variables are kept track of) until it finds a lexical that points to the same data that you passed it a reference to.
There are other modules that can do this for arrays and hashes. So you can write XS code that you pass a reference to the array, the index to be made an alias, and a reference to (or alias of) the value to be aliased (for example).
I know that demerphq's Data::Dump::Streamer needed this same functionality so I went to look up which module it used. But it looks like demerphq decided to roll his own replacements before he released the module (at least under that name). But you can just install Data::Dump::Streamer and use its alias functions:
alias_av(@Array,$index,$var); uses prototypes to get a reference to the array you pass it and uses the fact that function parameters are aliases to the corresponding (scalar) arguments to get a reference to $var. Then it sets $Array[$index] to be an alias to $var.
| [reply] [d/l] [select] |
Update: I forgot about the magic aliasing power of @_. See Corion's branch in this thread.
I believe part of the problem is that $array[$x] is not a lexical. Consider:
my @data = (1 .. 5);
{
local $data[2] = 100;
print_data();
}
print_data();
sub print_data {
print "@data\n";
}
(Did you know you can use local() on elements in lexical aggregates?)
But moreso, because the elements in aggregates do not have symbols, I do not think they can be aliased. I would expect Perl 6 would make this possible.
_____________________________________________________
Jeff japhy Pinyan,
P.L., P.M., P.O.D, X.S.:
Perl,
regex,
and perl
hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
| [reply] [d/l] [select] |