一个更好的变量命名系统?

时间:2013-07-10 18:42:00

标签: perl foreach

编程的新手。任务是从字符串中提取特定数据,我选择编写代码如下 -

while ($line =<IN>) {
    chomp $line;
    @tmp=(split /\t/, $line); 
    next if ($tmp[0] !~ /ch/); 
    @tgt1=@tmp[8..11];
    @tgt2=@tmp[12..14];
    @tgt3=@tmp[15..17];
    @tgt4=@tmp[18..21];
    foreach (1..4) {
            print @tgt($_), "\n";
            }

我认为@tgt($_)会被解释为@tgt1, @tgt2, @tgt3, @tgt4,但我仍然会收到@tgt是全局符号的错误消息(@ tgt1,@ tgt2,@ tgt3,@ tgt4`已宣布)。

Q1。我是否误解了foreach循环?

Q2。为什么perl看不到@tgt($_)为@ tgt1,@ tgt2 ..etc?

Q2。根据经验,这可能是命名变量的一种不好的方法。命名具有相似特征的变量的首选方法是什么?

1 个答案:

答案 0 :(得分:7)

  
      
  • Q2。为什么perl不能将@tgt($ _)视为@ tgt1,@ tgt2 ..etc?

  •   
  • Q2。根据经验,这可能是命名变量的一种不好的方法。命名具有相似特征的变量的首选方法是什么?

  •   

我会一起回答。

@tgt($_)并不代表您希望的含义

  • 首先,它是一个无效的语法(你不能在数组名后使用(),perl interpeter会产生编译错误)。

  • 您要做的是通过表达式访问变量来访问不同的变量,从而产生其名称(又名symbolic references)。这是可能的;但通常是一个坏主意和糟糕的Perl(因为,你可以,但你不应该这样做,没有一个非常好的理由)。

  • 要以您尝试的方式访问元素$ _,请使用@{"tgt$_"}语法。但我再说一遍 - 不要这样做,即使你可以。

  • 一个正确的惯用解决方案:使用一个arrayrefs数组,用1-4(或更确切地说是0-3)索引外部数组:

     # Old bad code: @tgt1=@tmp[8..11];
    
     # New correct code:
     $tgt[0]=[ @tmp[8..11] ]; # [] creates an array reference from a list.
     # etc... repeat 4 times - you can even do it in a smart loop later.
    

    这样做,它将对数组切片的引用存储到单个@tgt数组的第0个元素中。

    最后,@tgt数组有4个元素,每个元素都是对包含其中一个切片的数组的数组引用。


  
      
  • Q1。我是否误解了foreach循环?
  •   

你的foreach循环(与其内容相反 - 见上文)是正确的,有一种风格警告 - 再次,当你可以使用默认的$_变量时,你几乎不应该使用它,而是总是使用命名变量的可读性。

你打印上面提到的arrayrefs数组如下(如果任何语法不清楚,请分别询问 - 这是一个中级数据结构处理,不适合初学者):

foreach my $index (0..3) { 
    print join(",", @{ $tgt[$index]}) . "\n";
}