2016-06-23 1 views
1

これら2つのコードブロックの違いは何ですか?Scalaでのカリング:タイプ(=> A)の匿名関数を含む関数の複数のパラメータ

def measure[A](histogram: Histogram)(thunk: ⇒ A): A = { 
    val start = RelativeNanoTimestamp.now 
    try thunk finally { 
    val latency = NanoInterval.since(start).nanos 
    histogram.record(latency) 
} 

def measure[A](histogram: Histogram, thunk: ⇒ A): A = { 
    val start = RelativeNanoTimestamp.now 
    try thunk finally { 
    val latency = NanoInterval.since(start).nanos 
    histogram.record(latency) 
} 

Github Source

+2

第一には、二つの引数は、そうでない第二に、カリー化されています。あなたが学び/解決しようとしていることは何ですか? – jwvh

+0

@ jwvhカレーリングと代替の利点は何ですか?返信ありがとうございます! – Shehaaz

+0

@jwvh私はあなたが部分的にカリングで関数を呼び出すことができます参照してください。 http://docs.scala-lang.org/tutorials/tour/currying.html – Shehaaz

答えて

3

=> A怠惰なパラメータです。この関数で参照されたときに評価されます。これは、値を生成する関数、または値を生成する関数とすることができます。

あなたの例のように、単一および複数のパラメータリストの主な違い:

def measure[A](histogram: Histogram)(thunk: ⇒ A) 
def measure[A](histogram: Histogram, thunk: ⇒ A) 

(暗黙と型推論を考慮していないが)あなたが関数を適用する方法である:

scala> def f[A](i: Int)(p: => A): A = { p } 
f: [A](i: Int)(p: => A)A 

scala> f(1)(2) 
res0: Int = 2 

scala> f(1){ println("something") } 
something 

scala> f(1){ 
    | println("test") 
    | } 
test 

scala> def f2[A](i: Int, p: => A): A = { p } 
f2: [A](i: Int, p: => A)A 

scala> f2(1, 2) 
res4: Int = 2 

scala> f2(1, println("test")) 
test 

scala> f2(1, { println("test") }) 
test 

はそのfを参照してください。複数のパラメータリストを使用するとf(...){...}のようなスタイルで書くことができますが、f2は、2番目の引数として複数行のコードブロックを使用すると少し優雅です:f(..., {...})

あなたはたくさんのカリー化/部分のアプリケーションの操作を行うならば、f2fよりに対処するために少し簡単ですさらに:

scala> val f_withFirstArg = f(1) _ 
f_withFirstArg: (=> Nothing) => Nothing = <function1> 

scala> val f2_withFirstArg = f2(1, _) 
<console>:8: error: missing parameter type for expanded function ((x$1) => f2(1, x$1)) 
     val f2_withFirstArg = f2(1, _) 
           ^

私たちは、明示的にパラメータの型を指定する必要があり、型推論が短い失敗:

scala> val f2_withFirstArg = f2(1, _: String) 
f2_withFirstArg: String => String = <function1> 

技術について知りたい場合は、実際に異なるタイプのものであることを指摘する価値があります。

scala> :type f _ 
Int => ((=> Nothing) => Nothing) 

scala> :type f2 _ 
(Int, => Nothing) => Nothing 

fは、Intを受け取り、タイプがAで、タイプがAとなる別の関数を返す関数です。 f2は、2つの引数(IntA)をとり、Aを返す関数です。

実際にはコードによって異なります。型推論の欠点のために、部分的にたくさんのアプリケーションを実行する必要があるか、アノテーションが少なくて済むようにするには、複数のparamリストを使用します。さもなければ、事態を過度に複雑にする必要はなく、通常の単一パラメータリスト機能を使用する必要はありません。

最後に、あなたはいつものように長い間、それは理にかなっていると機能の一つのタイプから別のものに変換することができます:それはすでにあるので、我々は fカリー化をすることはできません

scala> f2 _ 
res13: (Int, => Nothing) => Nothing = <function2> 

scala> f2 _ curried 
warning: there were 1 feature warning(s); re-run with -feature for details 
res14: Int => ((=> Nothing) => Nothing) = <function1> 

scala> f _ curried 
<console>:9: error: value curried is not a member of Int => ((=> Nothing) => Nothing) 
       f _ curried 
       ^

scala> f _ tupled 
<console>:9: error: value tupled is not a member of Int => ((=> Nothing) => Nothing) 
       f _ tupled 
       ^

scala> f2 _ tupled 
warning: there were 1 feature warning(s); re-run with -feature for details 
res17: ((Int, => Nothing)) => Nothing = <function1> 

お知らせ。 fは何も変更されないため、タップされていません。しかし、我々はcurriedを使用してff2を変換することができます:

scala> :type f _ 
Int => ((=> Nothing) => Nothing) 

scala> :type f2 _ curried _ 
Int => ((=> Nothing) => Nothing) 
+0

詳細な説明をいただきありがとうございます。それは最終的に動作します! https://gist.github.com/shehaaz/7ea265d8b43006d7b395a035c3479925 – Shehaaz