2016-11-06 30 views
3

我想了解perldsc文檔中的'常見錯誤'部分。作者試圖傳達什麼時,他提到:瞭解perl中的數據結構

構造類似於數組數組中的兩個最常見的錯誤是要麼意外計算元素的數量,要麼反覆地引用相同的內存位置。在這裏你剛纔得到的計數,而不是一個嵌套的數組的情況下:

for my $i (1..10) { 
    my @array = somefunc($i); 
    $AoA[$i] = @array;  # WRONG! 
} 

從我的理解是,當它遍歷它會採取(1..10)的第一個值是1將它傳遞到這樣的功能:

my @array = somefunc(1); 

由於該函數沒有定義,我會創建邏輯。

sub somefunc { 
my $a = shift; 
print $a * $a; 
} 

這將從根本上做到這一點:

1 * 1 

,其結果是 '1'。

據我瞭解我的@array看起來像:

@array = ('1'); 

下一行會做:

$AoA[$i] = @array; 

我假設$農產品協議[$ 1]是一個匿名數組(他/她沒有用'my'聲明,btw),@array將是這個匿名數組的第一個元素,作者說它是'錯誤的。每次循環迭代到'2'。

somefunc(2); 

,這將是「4」,並傳遞到:

$AoA[$i] = @array 

什麼是筆者這段代碼是錯的點。我試圖理解哪些是錯誤的,但更重要的是,我試圖理解代碼。任何幫助將不勝感激。

UPDATE

我想我明白爲什麼這是一個常見的錯誤,因爲當我使用印刷和翻斗車,我可以直觀地看到是作者想傳達,這裏是修改後的代碼。

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 

for my $i (1..10) { 
      my @AoA; 
      my @array = somefunc($i); 
      print "The array is Dumper(@array)\n"; 
      $AoA[$i] = @array;  # WRONG! 
      print Dumper($AoA[$i]); 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

在的perldoc perldsc的常見誤區款,他/她指出

在這裏你剛纔得到的計數,而不是一個嵌套數組的情況:

下面是Dumper的輸出。

The array is Dumper(1) 
$VAR1 = 1; 
The array is Dumper(4) 
$VAR1 = 1; 
The array is Dumper(9) 
$VAR1 = 1; 
The array is Dumper(16) 
$VAR1 = 1; 
The array is Dumper(25) 
$VAR1 = 1; 
The array is Dumper(36) 
$VAR1 = 1; 
The array is Dumper(49) 
$VAR1 = 1; 
The array is Dumper(64) 
$VAR1 = 1; 
The array is Dumper(81) 
$VAR1 = 1; 
The array is Dumper(100) 
$VAR1 = 1; 

所以我假設重複

$VAR1 = 1; 

是計數,而不是嵌套數組。

筆者的確表明,如果算上是我真正想要再改寫這樣的代碼:

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 

for my $i (1..10) { 
      my @count; 
      my @array = somefunc($i); 
      print "The array is Dumper(@array)\n"; 
      $count[$i] = scalar @array;  
      print Dumper($count[$i]); 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

但文件沒有告訴我怎麼去嵌套數組?

UPDATE

糾正我,如果我錯了,但我重寫了代碼來獲取嵌套的數組:

#!/usr/bin/perl -w 
use strict; 
use Data::Dumper; 
my @count; 
my @new_array; 

for my $i (1..10) { 
      #my @count; 
      my @array = somefunc($i); 
      push @new_array, [@array]; 
     } 


sub somefunc { 
my $a = shift; 
return $a * $a; 
} 

print Dumper(\@new_array); 

打印了

$VAR1 = [ 
     [ 
     1 
     ], 
     [ 
     4 
     ], 
     [ 
     9 
     ], 
     [ 
     16 
     ], 
     [ 
     25 
     ], 
     [ 
     36 
     ], 
     [ 
     49 
     ], 
     [ 
     64 
     ], 
     [ 
     81 
     ], 
     [ 
     100 
     ] 
    ]; 
+2

我認爲應該'返回$ a * $ a'而不是'print $ a * $ a'? '$ AoA [$ i]'指的是常規數組「@ AoA」的元素(作者沒有聲明)。賦值'$ AoA [$ i] = @ array'在標量上下文中,所以'@ array'將計算爲數組長度 –

+1

Re「* @ array將是這個匿名數組的第一個元素*」,否,標量上下文中的「@ array」計算出「@ array」中的元素數量。 – ikegami

+1

請注意,該示例試圖演示如何將'@ array'放在'@ AoA'的元素中,所以'sub somefunc {my $ i = shift;返回($ i * 2,$ i * 3); ''會成爲一個更好的例子。 – ikegami

回答

6

在下面的語句:

$AoA[$i] = @array; 

@array標量上下文中被引用,從而產生一些元素。上下文是由LHS強加的,即$AoA[$i],它是@AoA陣列的單個元素。在Perl中,嚴格意義上沒有數組的數組。這些主要是通過將數組或數組與參考「變平」來模擬的。對於後者,你就需要使用取參考操作符如:

$AoA[$i] = \@array; 

對於起動器,你可能會發現,這Data::Dumper是在研究複雜的數據鋼結構製品如arrayrefs和hashrefs非常方便。

1

Perl是多態的,這意味着它可以透明地處理不同的數據類型,並且對於如何處理某些東西通常是一個很好的猜測。這使程序員的工作更容易,因爲它不像其他語言那樣強類型化。

因此,例如,當$ i 4號,你可以這樣做:

print $i + 1; 

,你會看到一個5 - 漂亮的邏輯,對不對?

,如果你這樣做:

print "I am " , $i , " years old"; 

你會看到「我4歲」 - 在這種情況下的perl說:「你在列表環境工作,所以我會$把我作爲一個字符串,無需將數字轉換成許多其他語言的堅持一個字符串。

所以,當你分配

$AoA[$i] = @array; 

它把這個依賴於上下文的方式。在標量方面,將設置$農產品協議[ $ i]是數組的長度。

有關標VS列表上下文的更多信息,請閱讀這樣的回答:

http://perl.plover.com/context.html

+0

好點,花在JavaScript上的時間太多了。應該使用「。」運算符,但它明確地進行連接:) – Mikkel

+1

「你在列表上下文中操作,所以我將把$ i當作字符串」。列表上下文沒有說明一個值是作爲數字還是字符串處理的。它是將所有參數轉換爲字符串的'print()'。如果用點替換逗號,那麼'$ i'將在標量上下文中被評估,但仍然會被轉換爲一個字符串(這次是通過連接操作符而不是'print()')。 –

1

您的例子並不瞭解這到底是怎麼回事作爲您的子程序總是返回「1」是非常有用的 - 的致電print()的結果。如果您將print()替換爲return(),那麼您將獲得不同的值(1,4,9等)。

但下一行代碼:

$AoA[$i] = @array; 

將始終分配給1@Aoa的元素。這是因爲您正將一個數組(@array)分配給標量變量($AoA[$i]),並且您在標量上下文中計算數組時,會得到數組中的元素數。

現在,您@array永遠只能有一個單一的元素,你可以這樣做:

$AoA[$i] = $array[0]; 

但是,這並不是真正構建一個數組的數組。你真正想要做的是獲得對數組的引用。

$AoA[$i] = \@array; 

如果你的子程序返回多個值,這會更有用。

sub somefunc { 
    # Used $x instead of $a as $a has a special meaning in Perl 
    my $x = shift; 
    return ($x * $x, $x * $x * $x); 
} 

for my $i (1..10) { 
    my @array = somefunc($i); 
    $AoA[$i] = \@array; 
} 

作爲探索這個有用的工具是Data::Dumper。嘗試添加:

use Data::Dumper; 

你的代碼的頂部:

print Dumper @AoA; 

foreach循環後看到你回來了不同的數據結構。