2016-06-23 24 views
1

这两个代码块之间的区别是什么?Curvature in 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

在第1,这两个参数是令行禁止,在他们没有第二次。你试图学习/解决什么? – jwvh

+0

@jwvh柯里与另类的好处是什么?谢谢你的回复! – Shehaaz

+0

@jwvh我看到你可以部分地调用一个具有currying功能。 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) 

(不考虑implicits和类型推断)是你如何运用一个函数:

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是少一点优雅,如果你有多行代码块作为第二个参数:f(..., {...})

此外,如果你做哗众取宠/部分应用程序的大量当时f2是有点更容易处理比f

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并且将生成类型Af2是一个需要2个参数的函数:IntA并返回A

这真的取决于你的代码。如果由于类型推断的缺点,您需要执行大量的部分应用程序或需要较少的注释,则使用多个参数列表。否则,不需要过分复杂的东西,并使用常规的单参数列表函数。

最后你总是可以,只要它是有道理的转换,从一种类型的功能,另:

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令行禁止,因为它已经是了。我们不能让f tupled,因为它不会改变任何东西。但是,我们可以使用curried转换为f2f

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

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

感谢您的详细解释!它终于有效! https://gist.github.com/shehaaz/7ea265d8b43006d7b395a035c3479925 – Shehaaz