2017-04-06 78 views
2

我想要做的定義Scala中的一個函數,它的參數在前綴符號:定義函數,它的參數在前綴符號斯卡拉

sum i1 i2 i3 ... in 

,並返回和Int與所提供的所有參數的個數之和。請注意,我不想在調用函數時使用括號。

我的目標是做類似sum i1 plus i2的事情,但我想先從簡單一點開始。

注意:如果您可以使用+運算符,您可能會說沒有這樣做的目的,但我的目標不是添加數字。我只是將其用作通用學習工具。

+0

你接受'i1 plus i2 plus ...'?這是更簡單的... –

+0

這將是很高興知道如何定義。儘管我現在對前綴符號調用更感興趣。如果你可以展示你的例子可以做的話,我們將不勝感激。謝謝 – locorecto

回答

1

在回答這個問題之前,我想指出scala首先是一個面向對象的語言,因此大多數您想定義的函數實際上都是特定對象上的方法。我將給出任何類別T(不一定代表Int)的更一般性的答案。我還假設你想在你的值列表上做什麼可以迭代完成,所以sum 1 2 3實際上與sum (sum 1 2) 3相同,所以我假設你有一些減速函數f: (T, T) => T

定義中綴操作符,讓你可以這樣做

i1 and i2 and i3 ... 

,你只需要在你的T類中定義的方法

and(that: T): T = f(this, that) 

。如果你不能夠方法添加到您的類型(例如,如果您正在使用從一個lib,或Int個類),您可以使用implicit wrapper你的類型:

implicit class ReducibleT(i: T) { 
    def and(j: T): f(i, j) 
} 

要定義一個前綴運營商,帶中繼器,如

sum i1 and i2 and i3 ... 

看來你不能這樣做!這是因爲像ident1 ident2 ident3這樣的表達式總是(據我所知)被解析爲ident1.ident2(ident3),(除非ident2以冒號結尾,在這種情況下它被顛倒過來)。但是您無法爲您的類型T定義所有可能的標識符的方法(例如,對於Int,您無法在對象上定義方法1,因此sum 1 2沒有任何意義),因此它是不可能的。

但是,你可以做幾乎一樣好:

sum (i1) and i2 and i3 ... 

在這種情況下,括號表示函數調用,所以它實際上調用該對象sum(i1)的方法and(實際上是sum.apply(i1),因爲所有函數是使用特殊方法apply)的對象。這裏有一個例子:

def sum(i: T) = i 

implicit class ReducibleT(i: T) { 
    def and(j: T): f(i, j) 
} 

現在,如果你明白這第二種情況下,它會在毫不奇怪,你不能做

sum i1 i2 i3 ... 

無論是。我們使用以下限定自己

sum (i1) (i2) (i3) 

def sum(i: T) = i 

implicit class ReducibleT(i: T) { 
    def apply(j: T) = f(i, j) 
} 

或者混合了一點東西,你可以使用隱式轉換函數:

implicit def tAsReducer(i: T): T => T = f(i, _)