【问题标题】:Scala Currying FunctionScala 柯里化函数
【发布时间】:2021-02-07 22:22:48
【问题描述】:

我有两种方法,nTimesnTimesBetter。这两个函数都对作为参数传递的函数执行 n 次操作。

方法nTimes 接受一个函数f,它必须被调用的次数n 以及函数在x 上工作的初始值

def nTimes(f:Int=>Int,n:Int,x:Int):Int =
  if (n <= 0) x
  else
    nTimes(f, n-1, f(x))

以下是使用某个函数fn = 3x = 1 调用该方法时发生的情况:

// nTimes(f,3,1)
// nTimes(f,2,f(1))
// nTimes(f,1,f(f(1)))
// nTimes(f,0,f(f(f(1))))

方法nTimesBetter方法不取初始值,只取一个函数f和该函数应该被调用的次数n

def nTimesBetter(f:Int=>Int,n:Int):(Int=>Int)=
  if (n <= 0) x => x
  else
   x => nTimesBetter(f, n-1)(f(x))

nTimesBetter 返回一个可以应用于初始值的函数

println(nTimes((x:Int)=>x+1,10,1))

val plus10 = nTimesBetter((x:Int)=>x+1,10)
println(plus10(1))

有人可以用一堆执行和使用(x:Int) =&gt; nTimesBetter(f,n-1)(f(x)) 来解释nTimesBetter 吗?为什么(f(x))被这样调用。

【问题讨论】:

  • 旁注:当您已经拥有nTimes 时,编写nTimesBetter 的简单方法是def nTimesBetter(f: Int =&gt; Int, n: Int) = nTimes(f, n, _)

标签: scala functional-programming


【解决方案1】:

这两者的主要区别在于前者返回一个值,后者返回一个函数Int =&gt; Int。该堆栈的可读性远低于nTimes 中的堆栈,但它是:

  // nTimesBetter(f, 3)
  // x => nTimesBetter(f, 2)(f(x))
  // x => (x => nTimesBetter(f, 1)(f(x)))(f(x))
  // x => (x => (x => (x => x)(f(x)))(f(x)))(f(x))

为什么 (f(x)) 被这样调用?

因为nTimesBetter 返回一个需要参数的函数。您可以将nTimesBetter 重写为:

def nTimesBetter(f: Int => Int, n: Int): Int => Int =
  if (n <= 0) x => x
  else {
    val function: Int => Int = nTimesBetter(f, n - 1) // Creates a function
    x => function(f(x))                               // Uses f(x) as an argument
  }

PS。 nTimesBetter 并没有那么好,因为 nTimes 是尾递归的。

【讨论】:

  • x => (x => (x => (x => x)(f(x)))(f(x)))(f(x) 的执行顺序是什么))?最里面的表达式将首先像堆栈函数一样被评估
  • 没错。首先(x =&gt; x)(f(x)) 将被评估为f(x)。然后我们有(x =&gt; f(x))(f(x)),即f(f(x))。最后我们会得到一个函数x =&gt; f(f(f(x)))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 2017-06-30
  • 2012-12-27
相关资源
最近更新 更多