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

Hi, Monks! I am trying to creat a series of arrays whose names are the values of a series of scalars. Here is the code:

while(<FGLCS>){ chomp; ($scfd_name_frgt,$stt_pst_frgt,$stp_pst_frgt,$lgh_frgt)=split /\t/,$_; $scfd_name_frgt=reverse $scfd_name_frgt; unless($scfd_name_frgt eq $scfd_name_frgt_tmp){ $scfd_name_frgt_tmp=$scfd_name_frgt; @{$scfd_name_frgt}=($stt_pst_frgt,$stp_pst_frgt,$lgh_frgt); $frgtlocs{$scfd_name_frgt}=\@{$scfd_name_frgt}; } else{ push @{$frgtlocs{$scfd_name_frgt}},($stt_pst_frgt,$stp_pst_frgt,$lgh_f +rgt); } }

I wish to creat the arrays whose names are the values of the scalars "$scfd_name_frgt". But under "use strict", @{$scfd_name_frgt} is defined as dereference of reference of $scfd_name_frgt. How can I name arrays via scalars values under "use strict" ?

Replies are listed 'Best First'.
Re: How to name arrays via scalars.
by AnomalousMonk (Archbishop) on May 03, 2014 at 09:29 UTC

    Why it's stupid to `use a variable as a variable name'

    Update:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "use warnings; use strict; ;; my $foo = 'bar'; ;; my %data; push @{ $data{$foo} }, qw(zero one two three); dd \%data; ;; print qq{'$data{$foo}[1]'}; " { bar => ["zero", "one", "two", "three"] } 'one'

      Thanks for you advice. It is very helpful.

Re: How to name arrays via scalars.
by hdb (Monsignor) on May 03, 2014 at 10:04 UTC

    Due to a feature of Perl called Autovivification, you only need this:

    use strict; use warnings; while(<FGLCS>){ chomp; my ($scfd_name_frgt,$stt_pst_frgt,$stp_pst_frgt,$lgh_frgt)=split /\t +/,$_; $scfd_name_frgt=reverse $scfd_name_frgt; push @{$frgtlocs{$scfd_name_frgt}},($stt_pst_frgt,$stp_pst_frgt,$lgh +_frgt); }

    If @{$frgtlocs{$scfd_name_frgt}} does not exist, Perl just creates an array and you are done.

    UPDATE: Also looking at these two lines:

    @{$scfd_name_frgt}=($stt_pst_frgt,$stp_pst_frgt,$lgh_frgt); $frgtlocs{$scfd_name_frgt}=\@{$scfd_name_frgt};

    They can be abbreviated using square brackets to create a reference to an array:

    $frgtlocs{$scfd_name_frgt}=[$stt_pst_frgt,$stp_pst_frgt,$lgh_frgt];

    There is no need to create a named array first and then store a reference to it (if that is what you want).

      Thanks very much. Your answer has directly solved my problem. I now understand more about the reference.

Re: How to name arrays via scalars.
by Laurent_R (Canon) on May 03, 2014 at 09:58 UTC
    While you can use symbolic references under the use strict; pragma using the additional no strict refs; pragma and global variables, this is very generally considered as a (very) bad idea. It is much better practice to use one more level of reference in your data structure, such as an hash of arrays in your case (if I understand you correctly).

      Yeah, one more level can work. But it just need to be @{$genelocs{$scfd_name_gene}}=($a,$b,$c). Thanks anyway.