【问题标题】:Why does Scala require partial application of curried functions when assigning to a val?为什么 Scala 在分配给 val 时需要部分应用柯里化函数?
【发布时间】:2015-10-30 06:24:23
【问题描述】:

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

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

我可以轻松地将curried 传递给test

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 =&gt; Int

【问题讨论】:

  • val 的情况下,如果您提供类型注释,则不需要公开的部分应用程序_

标签: scala currying


【解决方案1】:

问题不在于推断类型,问题在于推断您的意图。是你搞错了,还是故意对函数进行柯里化?

唉,后面的下划线语法是正式语法,省略它是语法糖。

【讨论】:

  • 这是有道理的,但我确实将方法声明为柯里化函数这一事实已经描述了我的意图。如果问题在于推断意图,为什么可以进行内联?
  • @MarkDerricutt 我不确定你所说的“内联”是什么意思,但在所有情况下,你都已经展示了它的工作原理,你声明了你期望它是什么,所以 Scala 继续使用柯里化,因为它符合您的期望。至于前者,Scala 不会隐式柯里化,它会使用尾随下划线或类型匹配显式柯里化——如果您来自一种可能看起来不自然的隐式柯里化语言。然而,declaration 函数声明了多个参数列表,这对于柯里化之外的其他事情很有用。
  • 通过“内联”我的意思是在参数位置使用(考虑一下,对参数的赋值具有完全限定的类型信息,因此与我的上一个示例基本相同)。我假设 Scala 显式柯里化来自多个参数列表,这与 Haskell 的方法不同,其中每个方法声明都是隐式柯里化的,任何缺少 args 的调用只会返回该位置的柯里化函数。我的困惑来自“多个参数列表 == currying”的假设,显然情况并非如此。
【解决方案2】:

并不总是需要下划线。来自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 

currying,明显的语法

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

currying,糖语法。但是:

val normer = zscore(7, 0.4) _   

需要尾随下划线来获取部分,仅适用于糖版本。

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    相关资源
    最近更新 更多