为什么Scala支持使用针对每个定义的表达式的多名称定义?

时间:2016-08-31 12:36:43

标签: scala

对于大多数语言我都不会问"为什么他们这样做X?"因为它通常基于意见。

对于像C ++这样的语言,通常的答案是引用一些规范,并且所有人都可以说,在做出特定选择之前,有人可能认为很长很难(但可能做出了不同的选择)。

Scala是不同的 - 通常答案是指出你可以用一些更简单的结构Y和Z来思考X,因此在这种情况下看X的表达是有意义的。

因此,我会问为什么Scala允许引入多个名称的定义并为每个名称计算一次给定表达式?

如果你让Java程序员猜测这里会发生什么,他们可能会猜错:

var x, y, z = 3

即。他们只猜测z被分配了一个值。

如果您解释val然后告诉他们以下内容是合法的:

val x, y, z = 3

然后他们可能会猜到正在进行更多操作,因为xy必须在此行之后有值,因为以后无法为它们分配不同的值。

他们可能会认为xy为其类型采用了默认值,例如0表示整数,但由于此处没有明确的类型,这是一个跳跃。

他们可能会认为它被处理为:

val z = 3
val x = z
val y = z

=左边的表达式产生原始值或不可变对象时,这并不重要。但以下可能让他们有理由怀疑:

val x, y, z = new StringBuilder

为什么有人想为同一个StringBuilder实例引入三个名称?

如果你向他们展示了以下内容,他们可能会从构造中猜出,甚至在运行代码之前出现了一些奇怪的事情:

var i = 0

def f: Int = {
  i += 1
  println(i)
  i
}

val x, y, z = f

有人最终意识到,似乎只与z相关联的表达式对每个名称实际评估一次,即上述内容相当于:

val x = f
val y = f
val z = f

那么谈论习惯于的其他语言的程序员可能会思考一下,这甚至是有趣的吗?

大多数人从其他地方来到像Scala这样的语言,所以除非有充分的理由,否则应避免使用可能令人困惑的程度结构。

乍一看这个功能似乎并没有多大提供,它避免了你不得不重复自己,但是为了这么小的收益而添加这段相当混乱的语法糖似乎很奇怪。

那么在某种情况下会带来真正的好处吗?或者这里没有真正的收益,例如我们与其他地方建立的更广泛的模式保持某种逻辑一致性?

2 个答案:

答案 0 :(得分:5)

有一种情况是使用这个令人惊讶的功能:定义scala.Enumeration

object Weekday extends scala.Enumeration {
  val Monday, Tuesday, Wednesday, Thursday, Friday = Value
}

调用Value(从def继承的Enumeration)5次,对于每个枚举字段调用一次。实际上,这为每个字段分配了一个Enumeration#Value的新实例,这显然是枚举有用的必要条件。

如果没有这种多重赋值功能,您必须写:

object Weekday extends scala.Enumeration {
  val Monday = Value
  val Tuesday = Value
  val Wednesday = Value
  val Thursday = Value
  val Friday = Value
}

我从未见过在Enumeration声明中使用的其他任何地方使用多重赋值功能。

在语言设计方面这是否是个好主意是一个主观问题,而且SO不适合讨论它。

答案 1 :(得分:2)

你已基本回答了自己的问题。选择在val x, y, z = someComplexExpression含义

之间
val z = someComplexExpression
val y = z
val x = z

val x = someComplexExpression
val y = someComplexExpression
val z = someComplexExpression

或根本不被允许。第一个是糟糕的选择有两个原因:

  1. 您提到第一个:您通常不需要为同一个实例提供多个名称。

  2. 如果您选择第一个,则每次需要第二个时都必须复制someComplexExpression,或者将其提取到方法中。如果你选择第二个,在你需要的时候写第一个(尽管第1点)是微不足道的:

    val z = someComplexExpression
    val x, y = z
    
  3. 不允许这样做。在看到你的评论之前,我认为我从未真正看过它。但是一旦被允许就删除它是一个坏主意。

    显然var x, y, z = ...需要与此保持一致。