Transitive aliasesby JadeNB (Chaplain)
|on Dec 27, 2009 at 23:56 UTC||Need Help??|
JadeNB has asked for the wisdom of the Perl Monks concerning the following question:
The following amusing piece of code gives a reference to a length-2 array whose 0th and 1st entries may be changed, but are always equal to one another:
I would like to have a 3-argument subroutine switch_var such that the following code works:
Of course, a cheating way to do it is as follows:
This satisfies the letter of my requirement, but not the spirit, because it only works for the particular $r I've given, not for an arbitrary circular reference.
Since the responses to Local for lexicals taught me the lesson of How to force one variable to be an alias to another?, I bethought myself of Data::Alias, but it doesn't work:
Even if I assume that I know something about the structure of the self-reference $r, I can only get at half of it:
I think that this is the behaviour mentioned in KNOWN ISSUES:
When aliasing existing lexical variables, the effect is limited in scope to the current subroutine and any closures create after the aliasing is done, even if the variable itself has wider scope. While partial fixes are possible, it cannot be fixed in any reliable or consistent way, and therefore I'm keeping the current behaviour.Thus, I guess that what I'm specifically wondering here is: Does the behaviour that I want admit one of the partial fixes mentioned? If so, what is it?
Oh, and, since Local for lexicals also taught me that I should explain the ‘why’ as well as the ‘what’: What I'm trying to do is make fake subroutines for a combinator library I'm writing (sort of as a replacement for Sub::Compose, which is lovely but inherits the limitations of Data::Dumper::Streamer), so that I can write something like:
The obvious response is “Why not use real subroutines?”, but it doesn't work for me: I'm using some trickery elsewhere so that I can tell the combinator SKK, say, to expect 1 argument $x, and it will figure out once and for all that it will just return $x (whatever it happens to be). The trickery I'm using (which is, literally, just calling my fake subroutine with a fresh variable $x and noting down the result as a ‘template’ for future calls) doesn't play well with real subroutines.