【问题标题】:Why does Scala's require method in Predef allow a String as argument?为什么 Predef 中的 Scala 的 require 方法允许使用字符串作为参数?
【发布时间】:2012-05-20 11:39:16
【问题描述】:

我可以在 Scala 的 Predef 类中使用 String 作为第二个参数的 require 方法,例如

require ("foo" == "bar", "foobar")

首先想到 require 方法被重载为不同的参数作为第二个参数。但事实并非如此。 require 方法(Scala 2.9.1)的签名是:

require(requirement: Boolean, message: ⇒ Any): Unit

为什么上面的方法调用是可能的?

【问题讨论】:

  • 定义有什么问题? "foo" == "bar"Boolean 值,String 符合 Any(就像 any 类型一样)。
  • 问题是,为什么 String 是第二个参数的有效类型,而签名说它必须是函数 'message: => Any'

标签: scala


【解决方案1】:

require 方法存在于 Predef 之前 scala 有默认参数(在 2.8 中引入),因此如果您希望给定参数的默认行为,重载是唯一的选择。如消息所示,第二个参数可以是任何东西,然后将其用作抛出的IllegalArgumentExceptionmessage(通过调用其toString 方法),(如果它被抛出- 即如果要求失败)。

请注意,参数实际上是按名称调用;也就是说,它被声明为=> Any,这意味着它只有在需求失败时才会被评估

这会以对象创建的形式造成性能损失,但在构建消息的成本很高的情况下(可能需要对数据结构进行一些 O(n) 访问),它可能很有用。

【讨论】:

    【解决方案2】:

    我不完全理解这个问题,但这里有一点解释。 requirePredef 中有一个重载版本:

    def require(requirement: Boolean) //...
    def require(requirement: Boolean, message: => Any) //...
    

    由于message: => Any 类型,第二个有点混乱。如果它只是简单的可能会更容易:

    def require(requirement: Boolean, message: Any) //...
    

    第二个参数当然是一条消息,如果不满足断言,则假定将其附加到错误消息中。你可以想象message 应该是String 类型,但是Any 你可以简单地写:

    require(x == 4, x)
    

    如果xInt 类型)的实际值不等于4,它将添加到错误消息中。这就是选择 Any 的原因 - 允许任意值。

    但是: => 部分呢?这被称为按名称调用,基本上意味着:评估此参数当它被访问时。想象一下下面的 sn-p:

    require(list.isEmpty, list.size)
    

    在这种情况下,您要确保 list 为空 - 如果不是,请将实际的 list 大小添加到错误消息中。然而,在正常的调用约定中,list.size 部分必须在调用方法之前进行评估——这可能是浪费。使用 按名称调用 约定,list.size 仅在第一次使用时评估 - 当错误消息是构造函数时(如果需要)。

    【讨论】:

    • @Tomasz - 我将编辑答案以从按名称调用的描述中删除“懒惰”一词。我认为这是误导。惰性(评估一次)和按名称调用(评估每次访问)之间存在明显区别。
    • @oxbow_lakes:没问题,我知道它可能会与lazy 关键字混淆。谢谢!
    【解决方案3】:

    问题是,为什么 String 是第二个参数的有效类型 而签名说它必须是一个函数message: => Any

    签名没有这么说。签名说第二个参数是 Any 类型的,并且这个参数是按名称传递的

    “按名称”由前缀=> 符号表示,它表示函数——函数总是表示为输入参数 => 结果类型Function0() => type

    “按值”和“按名称”查找参数。

    【讨论】:

      【解决方案4】:

      答案很简单:你期望

      的第二个参数
      require(boolean: Boolean, message: => Any): Unit
      

      成为 AnyFunction 并询问为什么 String 有效,即使它不是 Function

      分解为:固定的String 只不过是一个函数

      1. 不接受任何参数
      2. 不需要调用() 括号
      3. 每次调用都产生相同的结果

      实际上以下两个语句在 Scala 中是等价的:

      def x: String = "ABC" // const value, even though 'def' implies a function
      val x: String = "ABC"
      

      所以你可能会说=> Any 满足String

      【讨论】:

        猜你喜欢
        • 2013-10-21
        • 1970-01-01
        • 2012-03-07
        • 2011-06-06
        • 1970-01-01
        • 1970-01-01
        • 2010-12-10
        • 1970-01-01
        相关资源
        最近更新 更多