Scala表达评估

时间:2014-04-21 21:18:30

标签: scala functional-programming

我对以下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的函数,得到一个评估为另一种类型的函数,因为它会在其他类型之间发生。

非常感谢,

Maatari

3 个答案:

答案 0 :(得分:3)

  

返回评估的函数有什么区别   Int和表达式2 + 2.

评估为Int的函数可能有副作用

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

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

  

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

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

答案 1 :(得分:1)

为方便起见,

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)

我们看到可变+=的{​​{1}}方法返回地图。

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

HashMap

不起作用。

哪个更糟糕 - 意外地期望返回值与要求您明确返回最无聊的可能返回值 - 取决于您的代码的功能。如果你有不止一些副作用,不要推断def add(a: String, b: String): Unit = h += a -> b 是相当痛苦的。

答案 2 :(得分:1)

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

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

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 = ()