2013-03-08 54 views
10

在Scala中,为什么咖喱函数可以很容易地直接传递给其他函数,但是当将它分配给val时,还需要将其部分应用于_?例如,给出的两个功能:为什么Scala在分配给val时需要部分应用curried函数?

def curried(a: Int)(b: Int) = a + b 
def test(a: Int, f: Int => Int) = f(a) 

我可以很容易地通过curriedtest有:

test(5, curried(5)) 

,一切都是幸福的。但是,如果我只需拨打curried(5)我得到一个错误:如果我改变呼叫但是包括类型信息

scala> curried(5) 
<console>:9: error: missing arguments for method curried; 
follow this method with `_' if you want to treat it as a partially applied function 
       curried(5) 

,它的工作原理:

val 'curried: Int => Int = curried(5) 

任何人都可以解释的合理不一致的背后,想必给定原始方法的类型定义,Scala编译器可以推断函数为Int => Int

+0

在'val'的情况下,如果你给一个类型注解,你将不需要公开的部分应用程序'_'。 – 2013-03-08 23:19:58

回答

8

问题不是推断类型,问题是推断你的意图。你犯了一个错误,还是你有意咖哩功能?

唉,尾部下划线语法是形式语法,省略它是语法糖。

+0

这是有道理的,但是我确实将方法描述为咖喱函数的事实已经描述了我的意图。如果问题在于推断意图,为什么内联可以? – 2013-03-09 00:46:19

+0

@MarkDerricutt我不确定你的意思是“内联”,但是在所有情况下,你已经展示了它在哪里工作,你声明了你期望的结果,所以Scala继续使用currying,因为它符合你的期望。至于前者,斯卡拉不会隐式地咖喱,它会用尾部下划线或类型匹配来明确地进行调整 - 如果你来自一种带有隐含的压缩的语言,那看起来可能不自然。然而,函数_declaration_声明了多个参数列表,除了currying以外,这些列表对其他事物都很有用。 – 2013-03-09 01:17:10

+0

通过“内联”,我的意思是在参数位置中使用(思考它,参数的赋值具有完全限定的类型信息,因此基本上与我的最后一个示例相同)。 我假定Scala显式currying来自多个参数列表,不同于Haskell的方法,其中每个方法声明都隐式地被curry调用,任何具有缺少参数的调用只会返回该位置的curried函数。 我的疑惑来自于“多参数列表== currying”的假设,显然这不是特例。 – 2013-03-09 01:39:42

0

下划线并不总是需要的。 From http://docs.scala-lang.org/cheatsheets/

val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd 

currying,语法明显。

def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd 

钻营,明显的语法

def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd 

钻营,糖语法。但随后:

val normer = zscore(7, 0.4) _ 

需要尾随下划线得到部分,只对糖的版本。

相关问题