2014-02-28 36 views
2

假設我有sub1()和sub2()。 sub2僅從sub1調用。是否最好使用匿名sub來最小化sub2的範圍,以便只有sub1可以看到sub2?使用匿名潛艇將Perl中的子範圍最小化是否是一種好的做法?

例1(範圍沒有最小化):

sub sub_called_only_in_calc { 
    #do s.th 
    #return s.th 
} 

sub calc { 
    my $n = sub_called_only_in_calc(1,2,3); 
    #... 

    return $n; 
} 

例2(範圍與匿名子最小化):

sub calc { 
    #my or state 
    my $sub_called_only_in_calc = sub { 
     #do s.th 
     #return s.th 
    }; 

    my $n = $sub_called_only_in_calc->(1,2,3); 

    #or 

    #my $n = sub { 
     #do s.th 
     #return s.th 
    #}->(1,2,3); 

    return $n; 
} 
+3

這看起來像基於意見的問題,但我只會使用較小的範圍[閉包](http://stackoverflow.com/q/17039427/223226)。另外我想''我的$ n = sub {..}'任務有一些開銷。 –

+1

如果僅調用一次,則可以使用裸循環('{...}')。 – ikegami

+0

雖然我提出了一個答案,但我認爲這個問題應該以*「主要是基於意見的」*爲理由迅速結束。我們已經看到了不可證實的分歧的開始,Stack Overflow是關於*可證明的解決方案*。 – Borodin

回答

4

不同的人會有不同的看法,但我的觀點是,使用詞彙標器以將子系統本地化子程序可能在限制訪問非常重要的情況下是一種有用的技術;例如,這些子程序可能被未授權的人惡意地調用,通常通過網頁。

如果您正在考慮只是爲了防止編碼錯誤(調用錯誤的子例程)或允許具有相同標識符的多個子例程,那麼我會說您浪費了時間。無論如何,前者是一個微不足道的問題,我懷疑這個措施不會顯着減少;而後者通常應該使用包來實現:這是它們的設計目的。

大多數Perl模塊僅通過在子例程標識符前加一個下劃線來限制訪問的隱含性。

還記得拉里

Perl的這個報價不具有強制執行隱私的迷戀。它寧願你留在客廳因爲你沒有被邀請,不是因爲它有獵槍

儘管許多拉里的原創思想可以被認爲是與Perl的後續版本無關,認爲這個依然存在。

+1

我反對。我使用帶subscore前綴的package subs和詞法變量coderefs,以直觀的方式區分「protected」和「private」訪問(即不需要任何其他文檔)。 –

+2

@StefanMajewsky:當然,歡迎您不同意 - 即使是反對 - 但我不會那樣執行。我建議你的技術*需要額外的文檔,因爲沒有它,你的代碼很容易被看作是不一致的。 – Borodin

3

這取決於你的優化。在編寫維護的代碼,優化易讀性可能比最小範圍優化更重要,所以你會用一個私有方法去你的模塊中:

sub _only_called_in_calc { 
    ... 
} 

sub calc { 
    my $result = _only_called_in_calc(1,2,3); 
    ... 
} 

如果您擔心私有函數可以調用來自世界各地使用其名稱和包(如Foo::Bar::_only_called_in_calc(...)),可以將其存儲在一個詞法變量只能在同一個文件中可以看出:

my $_only_called_in_calc = sub { 
    ... 
}; 

sub calc { 
    my $result = $_only_called_in_calc->(1,2,3); 
    ... 
} 

此外,考慮Perl的最佳做法如下:

Place original code inline. 
Place duplicated code in a subroutine. 
Place duplicated subroutines in a module. 

換句話說,除非您計劃使用兩次,否則不要將代碼放在當前範圍之外。當你不需要它們重用代碼時,這背後的基本原理不是暴露接口。

+2

PBP現在變得有點襤褸,挑選出成熟的果實可能很困難。但是你的最後一點非常好,適用於所有程序語言。 – Borodin

+0

你的第二個例子的變體是[添加一些限制coderef範圍的額外curries](http://gist.github.com/9273452)。 – tobyink

相關問題