def关键字vs rocket(=>)表示法改变了scala中的函数行为?

Mad*_*dhu 3 lambda scala function

我正在学习Scala,我正在尝试理解定义函数的第一种方法背后的原因引发错误"+","v1"和"v2"未找到,而下面列出的第二种方法有效.

方法1: - 使用Lambda表达式表示法:

val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
Run Code Online (Sandbox Code Playgroud)

方法2: - 使用def关键字:

def addVect (v1:Vect3, v2:Vect3):Vect3 = (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
Run Code Online (Sandbox Code Playgroud)

如果已经提出这个问题我很抱歉 - 我试图搜索但找不到答案.真正感谢任何帮助/指导.

谢谢

编辑:产生错误消息的完整代码:

type Vect3 = (Double, Double, Double)
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
Run Code Online (Sandbox Code Playgroud)

错误消息:

error: not found: type +
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
                                                        ^
error: not found: type +
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
                                                                       ^
error: not found: type +
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
                                                                                      ^
error: not found: value v1
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
                     ^
error: not found: value v2
val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)
                              ^
Run Code Online (Sandbox Code Playgroud)

And*_*kin 9

这是一个奇怪的错误信息,你已经到了那里,但这不是你的错......我将首先简单解释你的第一个代码片段有什么问题,然后我将讨论它产生的奇怪的错误信息.


如果你想写下一个lambda,你必须这样做:

type V3 = (Double, Double, Double)
val add = (a: V3, b: V3) => (a._1 + b._1, a._2 + b._2, a._3 + b._3)
Run Code Online (Sandbox Code Playgroud)

如果您想明确归因于返回类型,则必须在右侧添加类型归属:

val add2 = (a: V3, b: V3) => ((a._1 + b._1, a._2 + b._2, a._3 + b._3) : V3)
Run Code Online (Sandbox Code Playgroud)

另一种选择是add3明确归类:

val add3: (V3, V3) => V3 = 
  (a: V3, b: V3) => (a._1 + b._1, a._2 + b._2, a._3 + b._3)
Run Code Online (Sandbox Code Playgroud)

这些是你的选择.只要坚持lambdas的有效语法,你应该没问题.


接下来是对奇怪错误消息有意义的原因的解释.但是,要理解解释,至少应该知道类型构造函数,类型成员,中缀表示法规则和隐式转换.


如果你错误地尝试在lambda的参数后面附加返回类型:

val broken = (a: V3, b: V3): V3 => (a._1 + b._1, a._2 + b._2, a._3 + b._3)
Run Code Online (Sandbox Code Playgroud)

你得到一堆错误

error: not found: type +
Run Code Online (Sandbox Code Playgroud)

乍一看,整个表达似乎完全无效.为什么这个表达式应该在编译的解析阶段存活下来并不明显.但是,这不是编译器错误.我们确实可以发明一套(相当人为的)定义,使上述表达式变得有效.这是一种可能性:

import scala.language.implicitConversions
trait +[A, B]
class R
class V3 {
  type _1 = R
  type _2 = R
  type _3 = R
}
val a = new V3
val b = new V3

implicit def conversion(i: (V3, V3)): (V3 => (R + R, R + R, R + R)) = { 
  v: V3 =>
  (new +[R, R]{}, new +[R, R]{}, new +[R, R]{})
}

val notBroken = (a: V3, b: V3): V3 => (a._1 + b._1, a._2 + b._2, a._3 + b._3)

println(notBroken)
Run Code Online (Sandbox Code Playgroud)

这里的右侧notBroken看起来与你问题中的不可编译(非)-lambda基本相同.但是,这是完全有效的Scala代码,甚至可以运行.

这里发生了什么:

  • + 是用中缀表示法编写的二进制类型构造函数
  • _1... _3是类的类型成员V3,设置为R
  • a并且b是实例V3
  • 有一个完全疯狂的隐式转换(V3, V3)到真正丑陋的函数类型V3 => (R + R, R + R, R + R)
  • V3 => (a._1 + b._1, ... , ...)从冒号开始的部分不是lambda,它是一种类型的归属
  • 类型归属强制隐式转换

因此,无论如何,这对于设计较少的用例来说并不是很有用.