2010-07-20 47 views
3

當我想使用隱式方法將函數轉換爲其他東西時,我遇到了一些問題。在scala中使用我的函數 - 在函數上應用隱式轉換

我正在Scala 2.8中實現一個小型DSL用於測試目的。它應該支持對實例進行各種檢查(如果你喜歡的話)。整個DSL是一個有點複雜,但下面的簡單示例說明我的問題:

object PimpMyFunction { 

    class A(val b: Int) 

    def b(a: A) = a.b 

    class ZeroCheck(f: A => Int) { 
    def isZeroIn(a: A) = f(a) == 0 
    } 

    implicit def fToCheck(f: A => Int): ZeroCheck = new ZeroCheck(f)  

    def main(args: Array[String]) { 
    val a0 = new A(0) 
    val a1 = new A(1) 

    println(fToCheck(b).isZeroIn(a0)) 
    println(fToCheck(b).isZeroIn(a1)) 

    println(b.isZeroIn(a0)) 
    } 
} 

前兩位的println線(當我明確地調用轉換方法)編制,做工精細,但最後一個(當我想依靠implicits)產生的錯誤:
Compile error: missing arguments for method b in object PimpMyFunction; follow this method with '_' if you want to treat it as a partially applied function
如果我想隱式地轉換「正常」的實例(這不是函數)的方式,它也可以工作,所以我猜這個問題與範圍/導入無關。

如果我按照錯誤消息的指示並使用println((b _).isZeroIn(a0))它也可以工作,但DSL是針對非技術人員的,因此我希望保持語法儘可能乾淨和簡單。

我想我有另一種解決方法(b應該是一個擴展了一個斷言特徵的類,它已經包含了檢查方法+ A => Int),它將支持更清晰的語法,但它會更冗長和更不靈活,所以我寧願隱含的方式。

任何想法如何避免(b _)語法,仍然使用implicits?

回答

6

Scala要求您編寫(b _)以確保您確實希望將方法b裝箱爲函數值。如果你不想寫下劃線,直接定義b可能是一個函數值,而不是一個方法:發生

val b = (a: A) => a.b 
+1

用於通過部分應用程序將方法轉換爲函數的術語是「提升」或「提升」。 – 2010-07-20 13:56:08

+0

就像丹尼爾的解決方案一樣,工作就像一個魅力。我看不出兩者之間有什麼重大區別,你是第一個 - >這就是我所接受的,即使他們兩個都完美地解決了我的問題。謝謝你的答案。 – 2010-07-21 07:08:11

4

的問題,因爲b不是一個函數,而是一個方法。請查找關於該主題的相關問題。如果定義b像下面,但是,你應該不會有任何問題:

def b = (_: A).b 

這定義的b類型是一個函數。

+0

謝謝,請參閱接受答案的評論。 – 2010-07-21 07:08:35