Scala文本函数(语法)-两个版本,相同的结果-有什么区别?

dxxyhpgq  于 2023-01-20  发布在  Scala
关注(0)|答案(1)|浏览(134)

我是一个Scala初学者。有人能解释一下这两行代码之间的区别(除了语法)吗(尽管它们返回相同的结果)?我写它们是为了练习字面函数,并试图找出“幕后”是否有什么东西?

val literal1 = (fn: Int => Int, x: Int) => fn(x)

val literal2 = (fn: Int => Int) => (x: Int) => fn(x)

我看到有可能以不同的方式将参数传递到函数中,但是我选择哪种方式真的重要吗(除了大小写)?

literal1(p => p + 1, 2) /*3*/

literal2(p => p + 1)(2) /*3*/
vltsax25

vltsax251#

这两个值具有不同的类型:

val literal1: (Int => Int, Int) => Int = <function>
val literal2: (Int => Int) => (Int => Int) = <function>

换句话说,literal1是一个接受两个参数的函数-一个接受Int并返回Int,另一个接受Int并返回Int
另一方面,literal2是一个只带一个参数的函数--一个带Int并返回Int的函数,而 * return * 是一个带Int并返回Int的函数。
除了调用约定不同之外,第二种形式允许您轻松地部分应用第一个参数,返回一个接受Int并返回Int的函数:

val doubler = literal2(_ * 2) // val doubler: Int => Int = <function>

doubler(2) // val res0: Int = 4
doubler(5) // val res1: Int = 10

对第一个表单执行同样的操作需要稍微复杂一些的语法:

val doubler = literal1(_ * 2, _)

doubler(2)
doubler(5)

使用curried方法可以将第一种形式自动转换为第二种形式:

val literal3 = literal1.curried // val literal3: (Int => Int) => (Int => Int) = scala.Function2<function>

literal3(_ * 3)(6) // val res2: Int = 18

请注意,在Scala中,对于只接受一个函数参数的函数和方法,通常会以curry格式将其指定为最终参数,因为这为多行lambda提供了方便的语法:

val literal4 = (x: Int) => (fn: Int => Int) => fn(x)

literal4(25) { x =>
  val mod = x % 2
  if (mod == 0) println("even")
  else println("odd")
  mod
}

输出:

val literal4: Int => ((Int => Int) => Int) = <function>

odd
val res3: Int = 1

相关问题