2017-04-21 40 views
-1

我想實現一個計算輸入字符串的d鄰居的子例程。這是planted motif search的實現的一部分,但我的問題更一般。下面是代碼:這個Perl子程序有什麼問題?

#subroutine for generating d-neighbors 
sub generate_d_neighbors{ 
    # $sequence is the sequence to generate d-neighbors from 
    # $HD is the Hamming Distance 
    my ($sequence, $HD) = @_; 

    for(my $i = 0; $i=$HD; $i++){ 
     my @l = ['A', 'C', 'T', 'G']; 
     my @t = splice(@l,$sequence[$i]); 
     #TODO 
    } 
} 

錯誤在最後一行出現,說:

Global symbol "@sequence" requires explicit package name (did you forget to declare "my @sequence"?

這是我的理解是,Perl不帶參數的形式subroutine(param1, param2)象Java例如,但爲什麼$sequence未被識別爲已經被初始化?

+2

你使用'$序列[0 ]',但是你還沒有聲明'@ sequence'。在Perl中,'$ sequence'和'@ sequence'是兩個不同的變量 –

+4

另外,賦值'$ i = $ HD'可能不是你的意思。通常有一些比較去那裏。 –

+5

'$ sequence [0]'是您如何訪問名爲'@ sequence'的數組的元素。 Perl正確地注意到它不知道任何關於名爲'@ sequence'的變量。你可能會傳遞一個數組引用*,它應該使用解引用箭頭來訪問:'$ sequence - > [0]' –

回答

0

像你想

​​

,而不是

$sequence[0]. 

在Perl中,字符串是第一類變量,而不是一個類型的數組在我看來。

或者你想要splice(@l, $sequence->[0])

+0

哎呀,只是編輯了這個問題。意思是'$ i'而不是0 –

4

有一些問題與您的代碼:

sub generate_d_neighbors{ 
    my ($sequence, $HD) = @_; 

    for(my $i = 0; $i=$HD; $i++){ 
     my @l = ['A', 'C', 'T', 'G']; 
     my @t = splice(@l,$sequence[$i]); 
    } 
} 

首先,讓我們來看看

for(my $i = 0; $i=$HD; $i++){ 

假設$HD是非零值,這個循環不會終止,因爲條件將永遠是假的。如果您希望$i的範圍從0$HD,那麼將該語句寫爲for my $i (0 .. $HD)會更好。

其次,你必須

 my @t = splice(@l,$sequence[$i]); 

,你似乎認爲有一個數組@sequence和您要訪問它的第一個元素。但是,$sequence是對數組的引用。因此,你應該使用

$sequence->[$i] 

三(感謝@Ikegami),您在for -loop的身體有

 my @l = ['A', 'C', 'T', 'G']; 

。然後@l將包含單個元素,對包含元素'A','C','T''G'的匿名數組的引用。相反,使用:

my @l = qw(A C T G); 

我不知道你想達到與splice(@l, $sequence->[$i])到底是什麼,但可以更好地寫爲:

my @t = @l[0 .. ($sequence->[$i] - 1)]; 

事實上,你可以在兩個賦值減少到:

my @t = qw(A C T G)[0 .. ($sequence->[$i] - 1)]; 
+0

@ikegami謝謝你指出這些。我不確定在原始代碼片段中使用「拼接」是否是OP的目標,但是將其作爲面值,我試圖引入您的反饋。 –

+0

拼接線旨在移除當前位置的基部。例如,'$ sequence =「ATG」;'和'$ HD = 1;'在位置0,我想刪除'A',並且只剩下'C T G'。類似地,對於位置1,刪除'T'並留下'A C G'等。 –

+0

因此,'$ sequence'是簡單的標量還是對數組的引用? –

0

這個列表賦值語法:

my (@sequence, $HD) = @_; 

不會做你想做的事(把最後一個參數放在$HD,其餘的放在@sequence)。數組總是接受它所能提供的所有參數,而不會留下任何後面的參數。

顛倒順序可以正常工作,對於情況下,只有一個數組:

my ($HD, @sequence) = @_; 

和您在主叫方的相應變化。

更普遍解決這一問題,請參考:

my ($sequence, $HD) = @_; 

,並呼籲像這樣子:

generate_d_neighbors(\@foo, $bar); 

或本:

# Note the brackets, which make an array reference, unlike parentheses 
# which would result in a flat list. 
generate_d_neighbors([...], 42); 

如果使用原型:

sub generate_d_neighbors (\@$) 

然後調用者可以說

generate_d_neighbors(@foo, $bar); 

@foo自動成爲參考,就好像它已經\@foo

如果你使用任何基於參考的解決方案,你必須改變函數體使用$sequence,而不是@sequence,遵循以下規則:

  1. 變化@sequence@$sequence
  2. 變化$#sequence$#$sequence
  3. 變化$sequence[...]$sequence->[...]
  4. 變化@sequence[...]@$sequence[...](但要確保你真的打算使用數組切片...如果你是新的perl的,你可能不是故意的,而且應該用$sequence[...]代替)