【问题标题】:Why do you use concat operator backward in scala?为什么在 scala 中向后使用 concat 运算符?
【发布时间】:2016-07-07 03:48:00
【问题描述】:

在 Scala 中 repl

scala> List(1) :: 2
<console>:8: error: value :: is not a member of Int
          List(1) :: 2

但是

scala> 2 :: List(1);
res4: List[Int] = List(2, 1)

这是反直觉的,因为如果从左到右读取中缀运算符,则上面的行可以转换为

List(1) :: 2
List(1).::(2) 

2 :: List(1)
2.::(List(1))

我想Int 没有方法::List 有。我假设有什么问题吗?

【问题讨论】:

标签: scala functional-programming operators


【解决方案1】:

这是反直觉的,因为如果中缀运算符被读取到 对了

如果你仔细想想,从逻辑上讲,这很有意义。 :: (cons) 运算符将值添加到列表的开头,它不会它添加到列表的末尾。当您这样考虑时,:: 运算符是右关联的事实是有道理的,因为它将一个元素粘贴到 List 的开头:

scala> 4 :: List(3,2,1)
res1: List[Int] = List(4, 3, 2, 1)

内部实现相当简单:

def ::[B >: A] (x: B): List[B] =
  new scala.collection.immutable.::(x, this)

List 在内部实现为 LinkedList,其中包含集合中的第一个元素的头部和尾部元素的列表。这就是为什么添加元素比添加元素便宜得多,因为它需要 O(n) 遍历内部列表才能复制元素,并添加新值。

虽然成本高昂,但您仍然可以使用:+ 运算符来做到这一点,它是左关联

scala> List(1,2,3) :+ 4
res3: List[Int] = List(1, 2, 3, 4)

【讨论】:

    【解决方案2】:

    : 结尾的Scala 运算符是右结合的。因此,在您的示例中,您尝试将 :: 运算符应用于 Int

    此外,List 结构在 Scala 中是不可变的,因此附加到列表的末尾非常昂贵;在列表的开头添加一个值非常便宜。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 2018-03-13
      • 2016-03-31
      相关资源
      最近更新 更多