def关键字vs火箭(=>)表示法会改变Scala中的功能行为吗? [英] def keyword vs rocket ( => ) notation changes function behavior in scala?

查看:63
本文介绍了def关键字vs火箭(=>)表示法会改变Scala中的功能行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Scala,我试图了解定义函数的第一种方法背后的原因引发错误,即在第二种方法中找不到"+","v1"和"v2"下面列出的作品.

I'm in the process of learning Scala and I am trying to understand the reason behind the first method of defining the function throws an error that "+", "v1" and "v2" are not found while the second method listed below works.

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

Method 1: - using Lambda expressions notation:

val addVectLambda = (v1:Vect3,v2:Vect3):Vect3 => (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)

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

Method 2: - using the def keyword:

def addVect (v1:Vect3, v2:Vect3):Vect3 = (v1._1 + v2._1, v1._2 + v2._2, v1._3 + v2._3)

很抱歉是否已经提出此问题-我尝试搜索但找不到答案.真正感谢任何帮助/指导.

I apologize if this question has been asked already - I've tried to search but couldn't find an answer. Truly appreciate any help / guidance.

谢谢

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

EDIT: Full code that produces the error message:

type Vect3 = (Double, Double, Double)
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: 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)
                              ^

推荐答案

那是一条奇异的错误消息,提示您到那里,但这绝不是您的错...首先,我将简单解释一下您的第一个问题代码段,然后我将讨论它产生的奇怪错误消息.

That's a bizarre error message that you've got there, but it's hardly your fault... I will first give a simple explanation of what's wrong with your first code snippet, and then I will discuss the strange error message that it produces.

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

If you wanted to write down a lambda, you would have to do it like this:

type V3 = (Double, Double, Double)
val add = (a: V3, b: V3) => (a._1 + b._1, a._2 + b._2, a._3 + b._3)

如果要明确地将返回类型归因,则必须在右侧添加类型归因:

If you wanted to ascribe the return type explicitly, you would have to add the type ascription on the right hand side:

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

另一种选择是明确地指定add3的类型:

another alternative would be to ascribe the type of add3 explicitly:

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

这些都是您的选择.只要坚持使用lambda的有效语法,就可以了.

Those are your choices. Just stick to the valid syntax for lambdas, and you should be fine.

现在,接下来是为什么奇怪的错误消息有意义的解释.但是,要理解这一解释,至少应该了解类型构造函数,类型成员,中缀表示法规则和隐式转换.

What follows now is an explanation of why the weird error message makes sense. However, to understand the explanation, one should know at least about type constructors, type members, rules for infix notation, and implicit conversions.

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

If you mistakenly try to append the return type right after the arguments of the lambda:

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

您会遇到很多错误

error: not found: type +

乍一看,整个表达式似乎完全无效.尚不清楚为什么该表达式应在编译的分析阶段中幸存下来.但是,这不是编译器错误.我们确实可以发明(合理设计的)一组定义,以使上述表达式有效.这是一种可能性:

On the first glance, the entire expression seems completely invalid. It is not obvious why this expression should survive the parsing stage of the compilation. However, this is not a compiler bug. We can indeed invent a (fairly contrived) set of definitions such that the above expression becomes valid. Here is one possibility:

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)

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

Here the right hand side of notBroken looks essentially the same as the uncompilable (non)-lambda in your question. However, this is perfectly valid Scala code, and it even runs.

这是怎么回事:

  • +是用后缀符号编写的二进制类型构造函数
  • _1 ... _3是类V3的类型成员,设置为R
  • abV3
  • 的实例
  • (V3, V3)到真正丑陋的函数类型V3 => (R + R, R + R, R + R)
  • 完全是疯狂的隐式转换
  • 从冒号开始的V3 => (a._1 + b._1, ... , ...)部分不是lambda,而是类型说明
  • 类型归属会强制进行隐式转换
  • + is a binary type constructor written in infix notation
  • _1 ... _3 are type members of the class V3, set to R
  • a and b are instances of V3
  • there is a completely insane implicit conversion from (V3, V3) to the really ugly function type V3 => (R + R, R + R, R + R)
  • the V3 => (a._1 + b._1, ... , ...) part right from the colon is not a lambda, it's a type ascription
  • the type ascription forces the implicit conversion

因此,诚然,它在不太人为的用例中不是很有用.

So, it's valid, though, admittedly, not very helpful in less contrived use cases.

这篇关于def关键字vs火箭(=>)表示法会改变Scala中的功能行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆