【问题标题】:Scala and the :: objectScala 和 :: 对象
【发布时间】:2011-07-15 18:17:18
【问题描述】:

我一直在深入研究 scala,到目前为止我非常喜欢它。我正在研究模式匹配和案例类,以下让我有些难过。我知道它的作用,但我想了解到底发生了什么

var list = List(2,3,4)
1::list

如果我到目前为止的理解是正确的。然后 :: 代表一个案例对象。如果是这样,我的问题是:

我如何将其“左应用​​”到 1?而不是 :: 是 1 的方法。基本上有人可以将这个语句 1::list 分开一些,显示真正发生的事情(即在什么对象上调用什么方法)

谢谢

【问题讨论】:

    标签: scala


    【解决方案1】:

    我对 :: (“cons”运算符)的理解是,它以这种方式使用是因为将元素添加到列表中(从技术上讲,创建一个新列表,将新元素添加到旧列表中)是 O (1) ,而附加它将是 O(N)。这是一个效率问题...

    【讨论】:

      【解决方案2】:

      要为其他答案添加一些附加信息:

      :: 都是List 的子类

      final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B] { ... }
      

      List上的方法

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

      基本上是按照第一个来实现的。

      所以这背后没有深厚的理论背景,只要记住以:结尾的方法规则即可。

      【讨论】:

        【解决方案3】:

        令人讨厌的是,Scala 的一些最显眼和最棒的功能在表面之下却有着如此多的复杂性。所以,考虑一下这个简单的行:

        val (head :: tail): ::[Int] = 1 :: Nil
        

        :: 出现的三个位置中的每一个都指向不同的::,以及 Scala 中的不同机制。让我们按顺序逐一介绍。

        head :: tail

        这里发生的是模式匹配,就像人们看到case 语句一样。模式匹配可以出现在val 赋值、<- 左侧的for 理解以及case 语句中。

        那么,这种特定的模式匹配是如何发生的呢?好吧,只要模式的格式为 a b c,Scala 就会将其转换为 b(a, c),然后将其转换为对对象 bunapplyunapplySeq 的调用。

        所以,val (head :: tail) 中的:: 指的是对象::(通过case class 定义)。

        : ::[Int]

        这是一个类型声明,所以::[Int] 是一个类型。 :: 本身是一个类,也是一个类型构造函数(因为它在给定类型参数的情况下构造类型——::[Int] 是一种类型,::[String] 是另一种类型,等等)。它也是List的子类,它只有两个子类:::Nil的单例类。

        这个声明是多余的,一般来说,很少有人使用:: 作为类型或类。我在这里展示它主要是为了完整性。

        1 :: Nil

        这里,:: 是一个方法。它是List的一个方法,所以,既然Nil是一个List1不是,它必须属于Nil(或者可以通过隐式转换得到)。

        这里要注意的机制是,以: 结尾的方法,当用于中缀运算符表示法时,绑定到右侧而不是左侧。或者,换句话说,a :: b 等价于b.::(a)

        这种机制很少使用,我怀疑主要是为了让习惯 fp 的程序员更熟悉传统的 fp 列表算法。它在 Scala 标准库和其他一些地方使用。

        例如,在 Scala 2.8 上,现在有 +:,它的用途与 :: 相同,但为所有 Seq 定义。它由 :+ 镜像,它附加元素,其 : 除了消除与 + 的歧义之外没有其他用途,+ 被重载以连接字符串。

        【讨论】:

          【解决方案4】:

          : 结尾的运算符名称绑定到右侧。 :: [A] 实际上是case classList[A] 的子类,如Scala API reference 所示。 :: 也是一个对其右参数(一个列表)进行操作的方法,将其左操作数作为参数并返回一个::[A]

          因此,在您的示例中,方法 ::1 作为参数在 list 上调用。这构造了一个 :: [Int] 类型的对象,其参数为 1list

          【讨论】:

          • @npiv ::List 的运算符/方法
          【解决方案5】:

          非常快速的答案。方法 :: 在列表中被调用,参数为 1。

          任何以冒号结尾的方法名称(是的,:: 是一个方法)都对正确的操作数进行操作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-12-17
            • 2017-09-14
            • 1970-01-01
            • 2018-02-06
            • 2012-11-18
            • 2016-10-17
            • 1970-01-01
            相关资源
            最近更新 更多