pmilne has asked for the wisdom of the Perl Monks concerning the following question:

Is there a means of referencing $a, $b, $c directly without copying them out of a list then back into a list. Using $a etc would make code more readable than using $x[0] etc.
my @x = (1, 2, undef) ; my ($a, $b, $c) = @x ; $c = $a + $b ; @x = ($a, $b, $c) ; print "@x\n" ;
I have read through Perldata but cannot seem to find how to do this.

Replies are listed 'Best First'.
Re: referencing list
by tobyink (Canon) on Jun 06, 2012 at 00:27 UTC
    use Data::Alias; my @x = (1, 2, undef) ; alias my ($a, $b, $c) = @x ; $c = $a + $b ; print "@x\n" ;
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      As Data::Alias is not standard in the version of PERL I am using, this may not be what I am looking for. Perhaps I could give another example:
      my @shape = ("round", "square", "polygon"); my @colour = ("red", "salmon", "purple" ); my @tag ; for my $j ( 0..2 ) { if ( ($shape[$j] eq "round") && ($colour[$j] eq "red") ) {$tag[$j]=1;} else {$tag[$j]=0;} print "$shape[$j] $colour[$j] $tag[$j]\n"; }
      There must be a more elegant way of doing ths eg by using: my @x = ($shape, $colour. $tag) ; rather than having a separate list for each attribute.
        Data::Alias is a module. To use it you need to install it. That's the point of modules: they are modular; you only install the ones you need. Not sure what you're trying to say with your second example; it appears to have little in common with the first.
        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: referencing list
by sauoq (Abbot) on Jun 06, 2012 at 01:12 UTC
    $ perl -le 'my @x=(1,2,3); (*a,*b,*c) = \(@x); $a="f"; $b="o"; $c="o"; + print @x' foo
    -sauoq
    "My two cents aren't worth a dime.";
      Thanks, this seems to be what I am looking for. However if I add 'use strict;', I get the message 'Global symbol "$c" requires explicit package name ...'.
        However if I add 'use strict;', I get the message 'Global symbol "$c" requires explicit package name ...'.

        Yes, and if you named $a and $b something more reasonable, you'd hear about them too. (You only don't because they are special case variables used in sort blocks.) You can take care of that by declaring your globals though, and that's something you should be doing anyway. The following is safe under warnings and strict.

        use warnings; use strict; my @x = (1,2,3); our ($a,$b,$c); (*a,*b,*c) = \(@x); $a = "f"; $b = "o"; $c = "o"; print sort {$b<=>$a} qw(17 11 13 29 31 37 3 2 7 5 19 23); print @x;
        It also shows that using $a and $b is fine, despite also using them for a sort block. The problem with using $a and $b comes up when you have them declared as lexicals...
        $ perl -le 'my $a=1; print sort {$b<=>$a} 1' Can't use "my $a" in sort comparison at -e line 1.
        Since we all usually declare our variables as lexicals these days, the advice "don't use $a and $b" get dispensed without a lot of understanding about why it matters. Or when it doesn't.

        Update: By the way, Data::Alias is a fine module and you shouldn't hesitate to use it if you can and it passes its tests. Sometimes people don't have control over what perl modules are available in their environment, particularly ones with an XS component. And sometimes modules have bugs, particularly platform specific ones, that prevent them being used. And sometimes adding a module isn't worth it when a couple extra lines of code will do. This is why I offered the old way of doing this. It's up to you to decide what is most appropriate in your situation.

        -sauoq
        "My two cents aren't worth a dime.";

        imho, using symbolic refs is not advisable in production code for something this simplistic.

        If you know when and why to use them, they are great, but they are generally reserved for very advanced uses. However, I really do like sauoq's take on the problem though ;)

        Update: yes... under strict, their code will break. Kudos for having strict enabled to begin with.

Re: referencing list
by thomas895 (Deacon) on Jun 06, 2012 at 00:09 UTC

    Just as a note: using $a and $b as variables outside of the sort() function is generally a bad idea.

    To answer your question, yes it is possible, but you don't need references for that:

    my @x = ( 1, 2, undef ); $x[2] = $x[0] + $x[1]; print @x, "\n";

    Or is that not what you are looking for?

    ~Thomas~
    confess( "I offer no guarantees on my code." );
Re: referencing list
by stevieb (Canon) on Jun 06, 2012 at 00:10 UTC

    afaik, there is not.

    As an aside, I completely disagree with your statement. When I'm reading code (mine or someone elses), it is inherently easier to know the intention of $x[0] directly than it is to have to scroll through to find out first where $a came from, and then have to do it again to find out how it got back into @x (imho).

    Also, using $a and $b is not advised much of the time, as they are special variables when one is using sort. This recommendation is contentious with some people, especially if you meant it only as an example... but I thought I'd point it out anyways.

    Update: unless I'm misunderstanding the question, the OP does not want to use the syntax of $x[0] at all, and instead just use a single variable that references the element. I'll let OP clarify.