10

私は Scala ( Scala コード ランナー バージョン 2.7.7.final ) を初めて使用しますが、高階関数を使用しているときに呼び出し元がパラメーターの型を指定する必要がある理由がよくわかりません。

以下のサンプルでは、​​1 つの関数を持つ 1 つのスタンドアロン オブジェクト ( Util) があります。ただし、Mainブロックでは、呼び出し元はパラメーターの型を無名関数に渡す必要があります。

Scala が型から関数の型を推測しないのはなぜですかArray(つまりString)? それを行う方法はありますか?

object Util {

 // Just for fun! Suppose that the arrayOne and arrayTwo are all the same length.
 // will swap the elements from arrayOne to ArrayTwo.
  def swap[T](arrayOne:Array[T], arrayTwo:Array[T] , f:(T,T) =>(T,T)) {
    for(i <- 0 until (arrayOne.length min arrayTwo.length)){
      val (left, right) = f(arrayOne(i),arrayTwo(i))
      arrayOne(i) = left
      arrayTwo(i) = right
    }
  }
}

object Main extends Application {

   val arrayOne = Array("A","B","C")
   val arrayTwo = Array("D","E","F")

 //If not specified the type String,the compiler throws "Missing Parameter Type" error

Util swap(arrayOne, arrayTwo,(elem1:String,elem2:String)=>(elem2,elem1))

}
4

1 に答える 1

15

この時点で通過しなければならないのはandTだけなので、の型は推測しません。ただし、Scala は 1 つのパラメーターの型を使用して別のパラメーターの型を推測することはありません。これは、おそらくメソッドのオーバーロードで問題が発生するためです。ただし、カリー化すると機能します。arrayOnearrayTwo

Object Util {

 // Just for fun! Suppose that the arrayOne and arrayTwo are all the same length.
 // will swap the elements from arrayOne to ArrayTwo.
   def swap[T](arrayOne:Array[T], arrayTwo:Array[T])(f:(T,T) =>(T,T)) : Unit = {
     var i = 0   
        var tuple :Tuple2[T,T] = null
       while(i < arrayOne.length && i < arrayTwo.length){
         tuple =f(arrayOne(i),arrayTwo(i))
         arrayOne(i) = tuple._1
         arrayTwo(i) = tuple._2
         i+=1
        }
      }
}

object Main extends Application {

   // val works fine below -- the object is mutable
   val arrayOne = Array("A","B","C")
   val arrayTwo = Array("D","E","F")

   (Util swap(arrayOne, arrayTwo))((elem1,elem2)=>(elem2,elem1))
   // The weird parenthesis is caused by mixing operator notation and currying
   // One could also write it like this:
   // Util.swap(arrayOne, arrayTwo)((elem1,elem2)=>(elem2,elem1))
}

カリー化すると正常に動作する理由は、カリー化されたメソッドが実際には最初のパラメーター リストを受け取り、他の (または他の) パラメーター リストを必要とする関数を返すメソッドだからです。そのため、オーバーロードは最初のパラメーター リストで決定できるため、2 番目のパラメーター リストは推論された型を利用できます。

于 2010-03-25T16:47:59.930 に答える