【问题标题】:Scala: value :: is not a member of IntScala:值 :: 不是 Int 的成员
【发布时间】:2018-11-30 11:10:26
【问题描述】:

我最近开始使用 scala,但我无法生成任何错误消息。对于以下代码,我得到了声明的消息(使用 eclipse):

def helper: Int => List[Int] = x =>  x match  {
    case 2 => 2::1
    ...
}

我可以通过使用 List(2,1) 来修复它,但这与 2::1 不一样吗? 我有类似的问题,List(...) 方法更难使用,所以我真的很想知道我的思维错误在哪里。

【问题讨论】:

  • 2 :: 1 :: Nil 试试这个
  • 或者,更好:List(2,1)

标签: scala


【解决方案1】:

中缀运算符在 Scala 中被解释为方法调用。如果中缀运算符以冒号结尾,则它是对右操作数的方法调用,左操作数作为其参数。否则,它是以右操作数作为参数对左操作数的方法调用。

换句话说,如果你执行x + y,它与x.+(y) 相同,即你在对象x 上调用+ 方法,以y 作为参数。如果你做x :: y它和y.::(x)一样,在对象y上调用方法::

因此,在您的示例中,您在对象1 上调用方法::,这是一个Int。但是,Int 类没有 :: 方法,因此这不起作用,并且您会收到一条错误消息,告诉您 Int 类不存在 :: 方法。

要使:: 工作,正确的操作数需要是一个列表(或其他具有:: 方法的东西),所以2 :: 1 :: Nil 可以工作。但是在这种情况下,使用 List() 似乎是更清洁的选择。

【讨论】:

  • 谢谢,现在我明白了。那么在 + 的情况下,右边是参数,对于 :: 它是左边?
【解决方案2】:

表达式 2::1 在 Scala 中被解释为:

{ val x = 2; 1.::(x) }

因为以冒号结尾的运算符: 是右关联的,如果op 是右关联的,那么e1 op e2 会被解释为{ val x = e1; e2.op(x) }(参见Scala Language Reference, Section 6.12.3, p. 84, which is p. 92 of the PDF)。

出于这里的目的,基本上称为以下简化版本

1.::(2)

但是,1Int 类型,而 Int 没有名称为 :: 的方法(并且也没有隐式转换为具有此类方法的另一种类型),因此出现错误。

正如 ayvango 上面指出的那样,您可以使用

2::1::Nil

解释为

Nil.::(2).::(1)

现在这工作得很好,因为NilList[Nothing] 类型并且确实有一个方法::,请参阅scala.collection.immutable.List 此外,:: 返回类型为List[Int] 的东西,所以随后的调用@ 987654342@也可以。

另一种方法是

2::List(1)

变成List(1).::(2) 并出于与上述相同的原因。

您的困惑可能是因为您认为List(2,1)2::1 相同,但实际上它是2::1::Nil。将列表视为归纳构建如下:

  • Nil是一个列表
  • 如果head是一个元素,tail是一个列表,那么head::tail是一个列表

由列表的实现所见证(简化版本,省略特征)

sealed abstract class List[+A]
final case class ::[B](head: B, tl: List[B]) extends List[B]
object Nil extends List[Nothing]

因此,列表总是以:: 的呈现形式“以”Nil 结尾。

在旁注中,您还可以尝试使用类似的方法将 Int 自动包装到 List[Int]

implicit def wrap(x : Int) : List[Int] = List(x)

或使用 Scalaz 等库提供的类似功能,但这可能并不总是可取的,并且可能有点超出了这个问题的范围。

【讨论】:

    【解决方案3】:

    :: 是在 List 上定义的方法。您正在尝试将此运算符与 Int 类型一起使用。 看一看:http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List

    正如@ayvango 指出的那样,您可以这样做:

    def helper: Int => List[Int] = x =>  x match  {
      case 2 => 2 :: 1 :: Nil
    }
    

    【讨论】:

      【解决方案4】:

      如果要使用:: 运算符,在Intstring 等其他类型上,只需在列表末尾添加Nil,否则会出现此错误:

      value :: 不是 Int 的成员

      这个不会被编译:

      println(0::1::2::3::4::5)
      

      但这会被编译:

       println(0::1::2::3::4::5::Nil)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多