Scala中def foo = {}和def foo()= {}之间有什么区别?

Jay*_*lor 53 jvm programming-languages functional-programming scala jvm-languages

给定以下用于在Scala中定义函数的构造,您能解释一下它们之间的区别,以及它们的含义是什么?

def foo = {}
Run Code Online (Sandbox Code Playgroud)

def foo() = {}
Run Code Online (Sandbox Code Playgroud)

更新

感谢您的快速回复.这些都很棒.对我来说唯一的问题是:

如果我省略括号,是否还有办法传递函数?这是我在repl中得到的:

scala> def foo = {}
foo: Unit

scala> def baz() = {}
baz: ()Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo)
<console>:10: error: type mismatch;
 found   : Unit
 required: () => Unit
              test(foo)
                   ^

scala> test(baz)
res1: () => Unit = <function0>
Run Code Online (Sandbox Code Playgroud)

更新2012-09-14

以下是我注意到的一些类似问题:

  1. 功能与括号和没有的区别
  2. 没有参数的Scala方法

Lui*_*hys 39

如果在定义中包含括号,则可以在调用方法时将其省略.如果在定义中省略它们,则在调用方法时无法使用它们.

scala> def foo() {}
foo: ()Unit

scala> def bar {}
bar: Unit

scala> foo

scala> bar()
<console>:12: error: Unit does not take parameters
       bar()
          ^
Run Code Online (Sandbox Code Playgroud)

此外,您可以使用更高阶的功能执行类似操作:

scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit

scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit

scala> baz(foo)    

scala> baz(bar)
<console>:13: error: type mismatch;
 found   : Unit
 required: () => Unit
       baz(bar)
           ^
scala> bat(foo)

scala> bat(bar)  // both ok
Run Code Online (Sandbox Code Playgroud)

这里baz只会采取foo()而不是bar.这是什么用,我不知道.但它确实表明类型是不同的.

  • 所以基本上如果你在定义中省略括号,你必须在调用方法时省略它们。此外,当方法有副作用时,您永远不应该省略括号,因为它看起来像一个属性调用。 (2认同)

Eug*_*ota 38

让我复制我在一个重复的问题上发布的答案:

可以使用括号或不使用括号来定义0-arity的Scala方法().这用于向用户发出信号,告知该方法具有某种副作用(如打印输出或销毁数据),而不是没有副作用的方法,以后可以实现val.

请参阅Scala编程:

这种无参数的方法在Scala中很常见.相比之下,使用空括号定义的方法(例如def height():Int)称为empty-paren方法.建议的约定是在没有参数时使用无参数方法,并且该方法仅通过读取包含对象的字段来访问可变状态(特别是,它不会改变可变状态).

该公约支持统一访问原则[...]

总而言之,鼓励Scala中的样式定义不带参数且没有副作用的方法作为无参数方法,即省略空括号.另一方面,您永远不应该定义一个没有括号的副作用的方法,因为那个方法的调用看起来像一个字段选择.

  • 感谢您描述“内容”背后的“原因”。 (3认同)

aij*_*aij 5

要回答第二个问题,只需添加一个_

scala> def foo = println("foo!")
foo: Unit

scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit

scala> test(foo _)
res10: () => Unit = <function0>

scala> test(foo _)()
foo!

scala>            
Run Code Online (Sandbox Code Playgroud)