2009-07-17 42 views
2

爲什麼這麼多的編程語言使得函數可以將傳遞給它的對象作爲參數進行修改,而不需要某種語法來使調用者清楚。例如考慮:清除函數可以修改其參數

SomeObject A(15), B 
B = DoSomething(A) 
print(A + " " + B + "\n) 

讀取代碼,你會希望輸出是類似於「15 75」,即A是你構造它。然而,大多數語言都可以讓DoSomething改變A.在C++中,你可以通過查看DoSomething的聲明來判斷它是否可能,例如通過查看參數被定義爲非const引用。然而,在很多語言中,比如Python,如果沒有閱讀函數的代碼以確保它永遠不會改變,真的沒有辦法告訴A.

我很多次被這個問題困擾過,特別是在嘗試工作時與別人的代碼使用這種行爲,通常會導致貫穿整行代碼逐行嘗試並找到什麼改變參數...

爲什麼它是語言通常不需要一些顯式語法通過調用說「是的,這個對象可以修改」,例如說「B = DoSomething(inout A)」?

是否有任何編碼標準有助於防止問題發生,除了「從不修改傳入函數的參數」?

+1

選擇一種語言; 「這麼多的編程語言」是很多語言,每種語言的設計決定都不一樣。 – 2009-07-17 07:43:38

+0

Python,C,C++,Java都可以完全按照我的示例中所示的那樣進行,我懷疑還有很多我不知道/使用的東西。 – 2009-07-17 12:06:52

回答

1

「編碼標準」因語言和用戶/團隊而異。 C++具有常量正確性,當正確使用時,它就是編碼標準。對於明顯的情況,C#有outref參數。我認爲在各種語言中唯一真正的一致性是參數修改應始終記錄在函數的後置條件中。

+0

是的,但在將C++中的每個變量傳遞給函數之前,人們很少會將其轉換爲const類型,並且如我的示例中所示,從調用代碼中看不到參考傳遞,您需要查看函數定義(它與現代IDE並不難,但仍然需要檢查每個函數,而不是瀏覽代碼)。 當我看了一些像我的例子那樣的代碼時,文檔仍然不突出,你必須去查看它。 – 2009-07-17 11:58:34

1

如果你看看Java,一種方法不能真正改變參數(Java只有輸入參數)。但是參數通常只是對某個對象的引用,這意味着該方法可以以任何可能的方式更改對象。這使得關於語義的推理(不看文檔)變得困難,這與函數編程完全相反。

你是對的,這是不可取的,但在短期內它使事情變得更容易。不幸的是,大多數情況下它是短期的重要,所以我們仍然在使用支持隱藏副作用的語言......

+0

即使有規則。作爲一個簡單的例子,getter不應該改變程序狀態,所以你通常可以假設你正在閱讀代碼。 – 2009-07-17 07:37:36

+0

這對於POD類型也不適用。 – scorpiodawg 2015-05-13 03:02:08

0

這並不直接使您的代碼片段更清晰,但我仍想提及它:我們使用參數的命名約定來準確顯示您想要的內容。我們使用'in','out'和'io'前綴。所以DoSomething聲明看起來像DoSomething(ioSomeObject inA)。在Visual Studio中使用Visual Assist工作時,您將看到一個彈出窗口,其中包含參數的類型和名稱,並記錄了可能的副作用。在我看來,這比記錄後期條件更爲明顯。

問候,

Sebastiaan

1

我給該優選的設計模式是不可變的數據類。

使用可變類時,您必須考慮是否被修改。

根據我的理解,一個澄清點就是像Java和C(沒有修飾符)那樣傳遞值。但是你傳遞的通常是一個可變對象。

(編輯:。幾乎所有的主流語言遵循這些語義現在最突出的例外是Lisp的,在這裏你不僅可以修改可變對象,但重新分配的值由變量指向)