2011-06-13 39 views
22

請原諒我,如果這已被問到別處。我有一個涉及函數值和隱式參數的Scala語法問題。帶有隱含的斯卡拉功能性文字

我很喜歡用Scala的咖喱特性使用implicits。舉例來說,如果我有一個求和函數,並希望讓第二個參數的隱式:

scala> def sum(a: Int)(implicit b: Int) = a + b 
sum: (a: Int)(implicit b: Int)Int 

有沒有辦法做到這一點使用的函數值的語法?忽略隱含了一會兒,我通常寫咖喱函數值是這樣的:

scala> val sum2 = (a: Int) => (b: Int) => a + b 
sum: (Int) => (Int) => Int = <function1> 

然而,在第二種方法的函數簽名有很大不同(在鑽營被表達明確)。只需添加隱關鍵字B沒有多大意義和編譯器抱怨以及:

scala> val sum2 = (a: Int) => (implicit b: Int) => a + b 
<console>:1: error: '=>' expected but ')' found. 
     val sum2 = (a: Int) => (implicit b: Int) => a + b 
              ^

從最初的做法此外局部應用和得到一個函數值導致的問題,以及:

scala> val sumFunction = sum _ 
<console>:14: error: could not find implicit value for parameter b: Int 
     val sumFunction = sum _ 
         ^

這使我相信具有隱式參數的函數必須在創建函數值時確定所述參數,而不是稍後應用函數值時確定。這是真的嗎?你可以使用一個隱式參數與函數值?

感謝您的幫助!

+0

不幸的是,我沒有給你一個答案,但我有一個澄清的問題:在你的第二段你談論一個'sum' *功能*,但你的相應的代碼示例顯示了'sum' *方法*。你是指哪一個? – 2011-06-13 02:45:39

+0

嗨Jörg - 我的理解是,一個方法只是一個與類或對象相關的函數。以上所有功能都被輸入到Scala REPL中;沒有創建用戶定義的類或對象。所以我會說我們只在這裏處理函數。 – shj 2011-06-13 03:34:39

回答

16
scala> val sum2 = (a: Int) => {implicit b: Int => a + b} 
sum2: (Int) => (Int) => Int = <function1> 

這將使b成爲函數體範圍的隱式值,因此您可以調用期望隱式Int的方法。

我不認爲你可以有隱含的函數的參數,因爲它不清楚這個函數是什麼。是Int => Int還是() => Int

我發現的最接近的是:

scala> case class Foo(implicit b: Int) extends (Int => Int) {def apply(a: Int) = a + b} 
defined class Foo 

scala> implicit val b = 3 
b: Int = 3 

scala> Foo() 
res22: Foo = <function1> 

scala> res22(2) 
res23: Int = 5 
9

在這個片段中

scala> val sum2 = (a: Int) => (b: Int) => a + b 
sum: (Int) => (Int) => Int = <function1> 

注意的是,精確型的sum2Function1[Int, Function1[Int, Int]]。它也可以被寫成

val sum2 = new Function1[Int, Function1[Int, Int]] { 
    def apply(a: Int) = new Function1[Int, Int] { 
     def apply(b: Int) = a + b 
    } 
} 

現在,如果你試圖讓b隱式的,你會得到這樣的:

scala>  val sum2 = new Function1[Int, Function1[Int, Int]] { 
    |   def apply(a: Int) = new Function1[Int, Int] { 
    |    def apply(implicit b: Int) = a + b 
    |   } 
    |  } 
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined 
       def apply(a: Int) = new Function1[Int, Int] { 
            ^

或者,換句話說,Function的接口沒有隱含參數,所以任何帶有隱含參數的東西都不是Function

3

嘗試重載apply方法。

scala> val sum = new Function1[Int, Function1[Int, Int]] { 
     |  def apply(a: Int) = (b: Int) => a + b 
     |  def apply(a: Int)(implicit b: Int) = a + b 
     |} 
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1> 

scala> sum(2)(3) 
res0: Int = 5 

scala> implicit val b = 10 
b: Int = 10 

scala> sum(2) 
res1: Int = 12