Scala中的函数相关问题

时间:2012-06-10 18:41:48

标签: scala

我有几个与咖喱功能有关的问题。我在这里逐一问他们

1)http://twitter.github.com/scala_school/basics.html给出了一个curried函数的例子 - 我认为它是一个函数定义,但实际上并非如此。 REPL根本不承认这是一个有效的声明。

multiplyThenFilter { m: Int =>   m * 2 } { n: Int =>   n < 5}

2)为什么我们不能从部分参数化方法定义函数?即,以下定义有什么问题?

scala> def multiply(m: Int, n: Int): Int = m * n
multiply: (m: Int, n: Int)Int

scala> val timesTwo = multiply(2,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1))
       val timesTwo = multiply(2,_)
                                 ^

3)为什么我们不能将部分参数化的功能用于咖喱?即,以下定义有什么问题?

scala> (multiply(_,_)).curried
  res13: Int => (Int => Int) = <function1>  // THIS IS OK

scala> (multiply(20,_)).curried
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1))
              (multiply(20,_)).curried
                           ^

1 个答案:

答案 0 :(得分:12)

问题1

Scala School示例 令人困惑 - 它绝对不是一个定义。在GitHub上有an issue开放,所以也许这是一个错误。您可以想象一个合理的定义可能如下所示:

def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = {
  i =>
    val j = f(i)
    if (p(j)) Some(j) else None
}

(或者,相当于f andThen (Some(_) filter p)。)

然后该示例将是一个函数,它将其输入加倍并在Some中返回结果,如果它小于5,否则返回None。但是,在对该问题作出回应之前,没有人确切知道作者的意图。


问题2

您的timesTwo不起作用的原因只是Scala编译器不支持这种类型推断 - 请参阅this questionmy answer there了解一些相关细节。您需要使用以下其中一项:

def multiply(m: Int, n: Int): Int = m * n    
val timesTwo = multiply(2, _: Int)

def multiply(m: Int)(n: Int): Int = m * n    
val timesTwo = multiply(2) _

即,如果您想在此处进行类型推断,则需要使用多个参数列表。否则你必须使用类型帮助编译器。


问题3

对于您的第三个问题,假设我们在第二个问题中有以下内容以避免此问题:

val timesTwo = multiply(2, _: Int)

这是一个Function1,它没有curried方法 - 您需要Function2(或Function3等)。

谈论用一个参数来讨论函数是没有意义的。 Currying接受一个带有多个参数的函数,并为您提供一个函数,它接受一个返回另一个函数的参数(它本身可能需要一个参数并返回另一个函数等)。