为什么Scala中的匿名函数和函数是这样构造的?

时间:2013-09-24 09:26:58

标签: scala lambda functional-programming anonymous-function

SICP 1.3.2中,有这个功能

(define (f x y)
  ((lambda (a b)
     (+ (* x (square a))
        (* y b)
        (* a b)))
   (+ 1 (* x y))
   (- 1 y)))

现在在追踪错误30分钟后,我发现this page并提供了此功能

  def f_lambda(x: Int, y: Int) =
    (((a: Int, b: Int) => ((x * square(a)) + (y * b) + (a * b)))
      (1 + (x * y), 1 - y)) 

我不明白为什么它被括号包围(就像一个堡垒)。

编辑:对不起,我的真正问题是我不明白为什么这个功能是按原样构建的。换句话说,为什么首先需要所有括号。与我迄今为止看到的Scala代码相比,这看起来完全是“外来的”。

2 个答案:

答案 0 :(得分:2)

首先,在上面给出的特定示例中,当然可以消除一些括号中的一对,但在最外层对的情况下,这确实需要将最后一行的部分或全部放在末尾。上一行:

def f_lambda2(x: Int, y: Int) =
   ((a: Int, b: Int) => (x * square(a) + y * b + a * b))(1 + x * y, 1 - y)

那就是说,你可以 - 像任何代码一样 - 选择加上额外的括号来澄清事物(例如,围绕乘法来使优先级更清晰)。

其次,还有其他方法可以编写这样一个功能,可以使任何读者都能清楚地看到它。这确实意味着代码的简洁性,但我认为获得的清晰度绝对值得:

def f_lambda3(x: Int, y: Int) = {
  def inner(a: Int, b: Int) = (x * square(a)) + (y * b) + (a * b)
  inner(1 + x * y, 1 - y)
}

总的来说,仅仅因为编码概念的最有效,最紧凑的表示可能涉及支架疯狂(yay,Lisp!),这并不意味着必须将其转移到Scala,Scala具有许多更易于访问的结构用于编写令人振奋的代码。

答案 1 :(得分:2)

我也不明白。你可以剥掉一些:

def f_lambda(x: Int, y: Int) =
  ((a: Int, b: Int) => (x * square(a)) + (y * b) + (a * b)) (1 + (x * y), 1 - y)

或者,如果您想依赖乘法优先于加法的事实:

def f_lambda(x: Int, y: Int) =
  ((a: Int, b: Int) => x * square(a) + y * b + a * b) (1 + x * y, 1 - y)

我个人认为第一个更具可读性。

编辑:

打破这一点,这是声明一个匿名函数,它将两个Int作为参数,样式为“a”和“b”:

(a: Int, b: Int) => x*square(a) + y*b + a*b

注意,这仍然使用x和y(作为外部方法的参数)。然后使用a = 1 + xy和b = 1-y来应用此内部函数。

所以代替,我相信你最终得到:

x*square(1 + x*y) + y*(1 - y) + (1 + x*y)*(1 -y)

为什么不首先以这种方式编写(或使用Shadowland的内部函数)?嗯,这是一个风格和背景的问题,我猜,所以我不能真正猜测作者的初衷。关键是Scala足够灵活,允许许多不同的风格,你可以用来表达同样的事情。