占位符与lambda函数中的显式参数有何不同?

时间:2014-09-05 11:59:50

标签: scala lambda placeholder

当在lambda函数中使用时,占位符通常只显示为语法糖,允许您避免指定参数,例如:

def bar(s: String) = s

val o = Some("x")

o.foreach(s => bar(s)) // Explicit parameter.
o.foreach(bar(_)) // No need for explicit parameter.

第二个foreach只是第一个的缩短版本。但是,如果我添加了另一个级别的调用,那么事情就不会像可能首先假设的那样起作用:

def foo(s: String) = s

o.foreach(s => foo(bar(s))) // OK
o.foreach(foo(bar(_)) // Error

这里发生的事情是foo觉得它传递的是lambda函数而不是String。

因此虽然对于像我这样的简单人类来说,似乎似乎 ,但Scala应该将foo(bar(_))转换为s => foo(bar(s)),它实际上相当于:

o.foreach(foo(s => bar(s)))

足够公平 - 想象Scala可能会神奇地知道向外拉动参数的距离可能是多么愚蠢(尽管在这种情况下可以想象将初始表达式解析为树,看到占位符,然后试图将其直接父母重新制定为lambda,并且在看到没有意义的情况下,将重新制定推到树上直到它,但我想这可能太难以推理关于表达式,如果有一种具有这种隐式行为的话。)

我可以避免使用显式参数并重新拟定上面的错误情况,如下所示:

o.foreach((foo _).compose(bar)(_))

这很清楚。

但有人可以提供一个简明的解释,说明如何在这些情况下考虑占位符以及Scala正在执行的转换吗?

虽然现在我很明显Scala无法推断,在我的错误案例中,我的意思是s => foo(bar(s))我不清楚它必须使用哪些规则。

鉴于Scala中大多数事物背后的理论很好,我很难想象只有一些任意规则,例如“如果占位符用作函数的参数,则用一个在其参数上调用此函数的lambda替换它。”

注意:我知道在上面的例子中我甚至不需要明确地使用占位符,即我可以写o.foreach(bar)o.foreach((foo _).compose(bar))而是 - 原始标题是一个天真的表述这个问题 - 通常问这个问题的过程让事情变得更加清晰。

0 个答案:

没有答案