理解lambda表达式的语法糖

时间:2015-06-09 19:19:19

标签: scala lambda type-inference syntactic-sugar

我正在努力understand the behavior of type inference。例如,这无法编译:

import math._
object Distance {

  def euclidean (p: Seq[Double], c: Seq[Double]) = {
    val d = (p,c)
      .zipped map (_ - _)
      .map pow(_,2.0)
      .foldLeft(0.0)(_+_)
    sqrt(d)
  }
}

使用:

  

错误:(5,17)缺少扩展函数的参数类型((x $ 3)=>   scala.Tuple2(p,c).zipped.map(((x $ 1,x $ 2)=>   x $ 1. $ minus(x $ 2)))。map.pow(scala.Tuple2(x $ 3,2.0).foldLeft(0.0)((x $ 4,   x $ 5)=> X $ 4 $加(X $ 5)))))         .map pow(_,2.0)

I somehow do not get how the de-sugaring works我最终不得不围绕类型声明和括号或摆脱infix notations以支持显式方法调用(使用.)。

例如,这个有效:

import math._
object Distance {

  def euclidean (p: Seq[Double], c: Seq[Double]) = {
    val d = (p,c)
      .zipped.map (_ - _)
      .map ( (x:Double) => pow(x,2.0) )
      .foldLeft(0.0)(_+_)
    sqrt(d)
  }
}

但没有机会拥有一个可爱的oneliner:

(p,c).zipped map pow(_ - _, 2.0)

我有兴趣了解rules of the game for dummies explain

1 个答案:

答案 0 :(得分:3)

问题似乎是中缀符号。规则实际上非常简单:采用一个参数的方法可以用中缀表示法编写。这样您就可以写a b c而不是a.b(c)

然而, 简单,因为通过省略显式点和括号,必须有其他东西来决定运算符的优先级。这样编译器就可以确定1+2*31.+(2.*(3))而不是(1.+(2)).*(3)。您已链接的规范的运算符部分的优先级(简称为)由运算符的前导符号控制。

要注意的另一个重要细节是以:结尾的运算符绑定右侧的参数。因此a :: b相当于b.::(a)

另一个棘手的问题是圆括号。在点符号中,它们只是包装参数列表。在运算符表示法中,他们可能需要自己包装参数(例如函数文字)。

顺便说一下:您的单行内容可以这样写:(p,c).zipped map {(a, b) => pow(a - b, 2.0)}请注意,我已使用{}包装了函数文字,这只是为了提高可读性,()也可以。