用于curala函数和scala中部分应用函数的最佳用例

时间:2017-09-21 15:31:04

标签: scala currying partial-application

我正在尝试学习Scala,我很困惑何时使用currying函数而非部分应用函数。

我很确定这些概念并不是多余的,但我看不出不同方法的真正目的。

我正在尝试使用此代码:

解决方案使用currying:

object CurryTest extends App {

  def filter(xs: List[Int], p: Int => Boolean): List[Int] =
    if (xs.isEmpty) xs
    else if (p(xs.head)) xs.head :: filter(xs.tail, p)
    else filter(xs.tail, p)

  def modN(n: Int)(x: Int) = ((x % n) == 0)

  val nums = List(1, 2, 3, 4, 5, 6, 7, 8)

  println(filter(nums, modN(2)))
  println(filter(nums, modN(3)))
}

解决方案使用部分应用的功能:

object PartialFunctionTest extends App {

  def filter(xs: List[Int], p: Int => Boolean): List[Int] =
    if (xs.isEmpty) xs
    else if (p(xs.head)) xs.head :: filter(xs.tail, p)
    else filter(xs.tail, p)

  def modN(n: Int, x: Int) = ((x % n) == 0)

  val nums = List(1, 2, 3, 4, 5, 6, 7, 8)

  println(filter(nums, modN(2,_)))
  println(filter(nums, modN(3,_)))
}

两者都给出了相同的结果:

List(2, 4, 6, 8)
List(3, 6)

这些不同的方法是否相同?

有人可以告诉我,每个人的最佳用例是什么?

1 个答案:

答案 0 :(得分:1)

这是一种风格独特的选择。在你的情况下,它没有真正的区别,但我认为第一个替代多个参数列表看起来更好。

在风格方面,当方法用于以咖喱方式使用时,请使用咖喱功能。当您需要为不是为其设计的函数时,请使用部分应用程序。

在某些情况下,您必须使用一个而不是另一个。例如,多个参数列表允许您在两个列表中使用var args

def ex1(ints: Int*)(strings: String*)

如果您有通用类型,这些类型可以从一个列表流向下一个

def ex2[A](input: A)(func: A => A): A = func(input)
ex2(1)(x => "Hello " + x) //compile error, A is Int from first parameter list

def ex2a[A](input: A, func: A => A): A = func(input)
ex2a(1, x => "Hello " + x) //compiles and returns "Hello 1",  A is Any because all parameters in the same list are used to determine it's type

在某些情况下,您可能需要使用部分应用程序。例如,在case类构造函数中,如果您尝试进行curry,则只有第一个参数列表成为case类字段的一部分。

case class ex3(a: Int, b:Int)
ex3(1, 2) == ex3(1,3) //false

val y: Int => ex3 = ex3(1,_)

y(2) == y(2) //true
y(2) == y(3) //false

case class ex3a(a: Int)(b:Int)

ex3a(1)(2) == ex3a(1)(3) //true

val x: Int => ex3a = ex3a(1)

x(1) == x(1) //true
x(1) == x(2) //true