Scala中的零度

时间:2013-07-14 17:51:01

标签: scala

在Eclipse工作表(2.10.1)中试过这个:

def a = { println("In a"); 3 }                    //> a: => Int
def b() = { println("In b"); 3 }                  //> b: ()Int
val c = () => { println("In c"); 3 }              //> c  : () => Int = <function0>

def test_type(x: => Int) = x                      //> test_type: (x: => Int)Int

test_type(a)                                      //> In a
                                                  //| res0: Int = 3

b()                                               //> In b
                                                  //| res1: Int = 3
c()                                               //> In c
                                                  //| res2: Int = 3

test_type(b)                                      //> In b
                                                  //| res3: Int = 3
// test_type(c) *** Doesn't compile

我肯定错过了一些东西。 abc之间的区别是什么?在我看来,aval a = 3(统一访问原则?)的“名字”替代品,因此我无法调用a(),但为什么b和{ {1}}有不同的类型?我也可以在没有括号的情况下调用c(即b将被评估为结果)以及ba将被转换为“按名称”调用b,但test_type将不会和c没有参数将被评估为函数本身(看起来合理)。

还有一个问题,Martin Odersky在他的在线课程中说,如果我做对了,c这样的任何匿名函数都可以用() => 3代替,但这两个表达式有不同的类型和评价规则,首先将被评估为函数,第二个是函数结果,例如:

{ def f() = 3; f }

1 个答案:

答案 0 :(得分:3)

在许多情况下,Scala以不同方式处理方法和函数。统一访问原则适用于方法调用,因为方法通常用于模仿对象上的字段,但不能用于函数应用程序。

虽然b()Int类型的方法,但代码b将在评估时调用该方法,除非编译器需要一个函数输入使用b的类型,在这种情况下,它会将方法扩展为函数。

由于c() => Int类型的函数,因此应用它需要在所有上下文中都是显式的。所以,test_type(c())应该编译。

x: => Int的“按名称” - 性质不会影响这些推理/应用规则;它只影响 时可能会评估参数。

scala> object Foo {
     |   def f(): Int = 123
     |   val g: () => Int = () => 123
     | }
defined module Foo

scala> Foo.f
res0: Int = 123

scala> Foo.g
res1: () => Int = <function0>

scala> Foo.g()
res2: Int = 123

scala> (Foo.f: () => Int) // force eta-expansion by explicitly specifying function type
res3: () => Int = <function0>