【问题标题】:Scala expression evaluationScala 表达式求值
【发布时间】:2014-04-21 21:18:29
【问题描述】:

我对以下 Scala 编译器行为很感兴趣。当我声明一个单元类型的函数,但仍然提供一个评估为 Int 的函数作为主体时,Scala 编译器可以接受。

def add(x:Int, y:Int) = x + y
def main(args: Array[String]): Unit = {add(args(0).toInt, args(0).toInt)}

虽然其他类型的情况并非如此

def afunc: String = {1} //type mismatch;  found   : Int(1)  required: String

如果我写了

def afunc: Unit = {1}

def main(args: Array[String]): Unit = {2 + 2} // Which is just like the first addition above

在这两种情况下,我都会收到以下警告:

a pure expression does nothing in statement position; you may be omitting necessary parentheses 

从某种意义上说,这里有两个问题。返回计算结果为 Int 的函数和表达式 2 + 2 之间有什么区别。那么,究竟为什么编译器不会抱怨假设计算结果为 Unit 的函数会得到一个计算结果为另一种类型的主体,因为它会发生在其他类型之间。

非常感谢,

马塔里

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    返回求值的函数与 Int 和表达式 2 + 2。

    计算结果为 Int 的函数可能有副作用

    var a = 0
    def fn: Int = {
      a = a + 1
      1
    }
    

    每次调用 fn 都会改变 a 的值。

    那么到底为什么编译器不抱怨一个函数 假设评估为 Unit,得到一个评估为另一个的主体 类型,因为它会发生在其他类型之间。

    当您指定 Unit 作为返回类型时,编译器会从函数返回的任何值到 Unit 进行隐式转换(只有一个 Unit 值,因为它是一个对象,您可以将其视为 Scala 的 void 类型) .

    【讨论】:

    • 感谢您的回答。完成最后一点。这是 scala 规范中的一个指示:>
    【解决方案2】:

    Unit 为方便起见被推断为返回类型。例如,

    scala> val h = new collection.mutable.HashMap[String,String]
    h: scala.collection.mutable.HashMap[String,String] = Map()
    
    scala> h += "fish" -> "salmon"
    res1: h.type = Map(fish -> salmon)
    

    我们看到可变HashMaps 上的+= 方法返回地图。

    但如果你不推断单位,那么

    def add(a: String, b: String): Unit = h += a -> b
    

    没用。

    哪件事更糟——意外地期望返回值与要求你显式返回最无聊的可能返回值——取决于你的代码的功能性。如果你有多个副作用,不推断Unit 是相当痛苦的。

    【讨论】:

      【解决方案3】:

      只有括号的函数主要是为了副作用而调用的。它可能会返回一个结果,因为它在 C 或 Java 时代很常见,但实际上我们不在乎,因为我们不会使用它。 {} 等价于 : Unit =,返回类型的注解可以看作是强制转换或隐式转换以匹配函数期望的类型。 p>

      这是发生此行为的另一个示例。

      def add(a: Int, b:Int) : Double = a + b
      add: (a: Int, b: Int)Double
      
      scala> add(4,5)
      res17: Double = 9.0
      

      因此,似乎每个值都可以转换为单位。

      scala> val a: Unit = 1:Unit
      <console>:28: warning: a pure expression does nothing in statement position; you may be omitting    necessary parentheses
         val a: Unit = 1:Unit
                       ^
      a: Unit = ()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-30
        • 2019-09-06
        • 2014-06-22
        • 2012-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多