2011-01-25 153 views
11

我知道Scala支持ALGOL的名稱調用,我想我明白這意味着什麼,但Scala可以像C#,VB.NET和C++那樣通過引用進行調用嗎?我知道Java不能通過引用來調用,但我不確定這個限制是否僅僅是由於語言或JVM。Scala可以通過引用調用嗎?

當你想將一個龐大的數據結構傳遞給一個方法,但你不想複製它時,這會很有用。在這種情況下,通過引用調用看起來很完美。

+1

我不認爲你可以通過Scala中的值傳遞數據結構。 – Gabe 2011-01-25 04:46:23

+0

@Gabe它仍然是[傳遞/調用值](http://en.wikipedia.org/wiki/Evaluation_strategy)(AnyRef類型的傳遞值 - 底層對象引用)和Python/Java人喜歡濫用「pass-by-reference」這個術語;-)。但是,傳遞/調用引用意味着在函數*中設置變量*將設置傳入變量的值(例如,在C++中使用`&ref`或使用VB中的`ByRef`或使用C#中的`out/ref`) 。這可以通過傳遞對象和狀態變化來模擬*但它不相同(C可以通過修改指針引用的值來模擬它)。 – 2011-01-25 07:04:02

+1

@pst:我指的是「將龐大的數據結構傳遞給方法」部分。 Scala有一種方法,我不知道在將數據結構傳遞給函數時複製數據結構,或者數據結構已經通過引用傳遞,並且來自OP的引用是不相關的。 – Gabe 2011-01-25 16:55:50

回答

34

Java和Scala都只使用按值調用,不同之處在於該值是基元或指向對象的指針。如果你的對象包含可變字段,那麼這和引用的調用之間幾乎沒有實質性的區別。

由於您總是通過指向對象的指針而不是對象本身,因此您不必重複複製巨型對象。

順便提一下,Scala的名稱調用是通過值調用來實現的,該值是一個(指向函數的)函數對象,它返回表達式的結果。

0

對於「一切都是對象」並且對象引用無法訪問的語言,例如Java和Scala,那麼每個函數參數都是在語言之下的某個抽象層次上通過值傳遞的引用。但是,從語言抽象的語義角度來看,根據函數是否提供了引用對象的副本,可能會有引用調用或值調用。在這種情況下,「共享呼叫」一詞既包含在抽象的語言層面上的引用引用和值引用。因此,認爲Java是在語言語義之下的抽象層次上進行價值調用是正確的(即,比較它如何被假設轉換爲C或用於虛擬機的字節碼),同時還說Java和Scala(除了內建類型)在其「一切都是對象」抽象的語義上通過引用進行引用。在Java和Scala中,某些內置(a/k/a原語)類型自動獲取傳值(例如int或Int),並且每個用戶定義的類型都是通過引用傳遞的(即必須手動複製他們只傳遞他們的價值)。

注意我更新了維基百科的Call-by-sharing section以使其更加清晰。

也許維基百科對傳遞值和按值傳遞之間的區別感到困惑?我認爲按值傳遞是更通用的術語,因爲它適用於賦值表達式以及函數應用程序。我沒有費心去嘗試在維基百科進行修正,讓其他人去散佈。

當對象是不可變的時候,在引用調用和值調用之間的「一切都是對象」的語義層次上沒有區別。因此,可以通過延遲按值複製直到對象被修改來優化允許按值引用聲明與基於引用的聲明(如我正在開發的類似Scala的語言)的語言。


投票的人顯然不明白「分享呼叫」是什麼。

下面我將爲我的Copute語言(針對JVM)添加寫作,我將在其中討論評估策略。


即使有純度,也沒有圖靈完整的語言(即圖靈語言)。允許遞歸)完全是陳述性的,因爲它必須選擇一個評估策略。評估策略是功能與參數之間的相對運行時評估順序。功能的評估策略可以是嚴格的,也可以是非嚴格的,因爲所有表達式都是函數,所以它們分別與渴望或懶惰相同。 Eager意味着參數表達式在它們的函數之前被評估;而懶惰的意思是參數表達式只在函數首次使用的運行時刻被評估(一次)。 評估策略決定了性能,確定性,調試和操作語義的折衷。對於純程序,它不會改變指稱的語義結果,因爲純粹性,評估順序的命令性副作用只會導致內存消耗,執行時間,延遲和非終止域的不確定性(即分類限制) 。基本上所有表達式都是(組成)函數,即常量是沒有輸入的純函數,一元運算符是一個輸入的純函數,二元運算符是具有兩個輸入的純函數,構造函數是函數,甚至控制語句(例如如果,因爲,while)可以用函數建模。我們評估這些函數的順序不是由語法定義的,例如, f(g())可以熱切地評估g,然後f對g的結果進行評估,或者它可以評估f,並且只有在f內需要結果時才懶惰地評估g。

前者(渴望)是按值(CBV),後者(懶惰)是按名稱(CBN)。 CBV具有不同的基於共享的調用,這在現代OOP語言(如Java,Python,Ruby等)中很流行,其中不純的函數通過引用隱式輸入一些可變對象。 CBN有一個不同的需求調用(也稱爲CBN),其中函數參數只進行一次評估(與記憶函數不同)。按需呼叫幾乎總是用來代替按名稱呼叫,因爲它的指數速度更快。由於所聲明的功能層次與運行時評估順序之間的不一致,通常CBN的兩種變體都僅以純度出現。

語言通常有一個默認的評估策略,有些語法可以選擇強制函數在非默認情況下評估。由於第二個操作數不是默認值,所以通常會評估布爾連接(a/k/a「和」,& &)和分離(a/k/a「或」,||)運算符,因爲第二個操作數不是需要一半的情況下,即真||任何東西== true和false & & anything == false。

0

以下是如何在Scala中模擬參考參數。

def someFunc(var_par_x : Function[Int,Unit]) { 
    var_par_x(42) // set the reference parameter to 42 
} 

var y = 0 
someFunc((x => y=x)) 
println(y) 

好的,好吧,不完全是Pascal或C++程序員習慣的;但是,在Scala中很少。好處在於,這使得調用者可以更靈活地處理髮送給參數的值。例如。

someFunc((x => println(x))) 
相關問題