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

Scala中def foo={}和def foo()={}之间有什么区别?,scala,programming-languages,functional-programming,jvm,jvm-languages,Scala,Programming Languages,Functional Programming,Jvm,Jvm Languages,给出了以下在Scala中定义函数的结构,您能解释一下区别是什么,以及含义是什么吗 def foo = {} vs 更新 谢谢你的快速回复。这些很好。唯一留给我的问题是: 如果省略括号,还有方法传递函数吗?这是我在repl中得到的: scala> def foo = {} foo: Unit scala> def baz() = {} baz: ()Unit scala> def test(arg: () => Unit) = { arg } test: (arg:

给出了以下在Scala中定义函数的结构,您能解释一下区别是什么,以及含义是什么吗

def foo = {}
vs

更新

谢谢你的快速回复。这些很好。唯一留给我的问题是:

如果省略括号,还有方法传递函数吗?这是我在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>
scala>def foo={}
傅:单位
scala>def baz()={}
baz:()单位
scala>def测试(arg:()=>Unit)={arg}
测试:(arg:()=>单位)(=>单位)
scala>测试(foo)
:10:错误:类型不匹配;
发现:单位
必需:()=>单位
测试(foo)
^
scala>测试(baz)
res1:()=>单位=

更新2012-09-14

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


  • 如果在定义中包含括号,则可以在调用该方法时选择性地忽略括号。如果在定义中省略它们,则在调用该方法时不能使用它们

    scala> def foo() {}
    foo: ()Unit
    
    scala> def bar {}
    bar: Unit
    
    scala> foo
    
    scala> bar()
    <console>:12: error: Unit does not take parameters
           bar()
              ^
    
    scala>def foo(){}
    foo:()单位
    scala>def bar{}
    酒吧:单位
    scala>foo
    scala>bar()
    :12:错误:单元不接受参数
    bar()
    ^
    
    此外,您还可以对高阶函数执行类似操作:

    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
    
    scala>defbaz(f:()=>Unit){
    baz:(f:()=>单位)单位
    scala>def-bat(f:=>Unit){}
    蝙蝠:(f:=>单位)单位
    scala>baz(foo)
    scala>baz(巴)
    :13:错误:类型不匹配;
    发现:单位
    必需:()=>单位
    巴兹(巴)
    ^
    scala>bat(foo)
    scala>bat(bar)//都正常
    

    这里的
    baz
    只接受
    foo()
    而不是
    bar
    。我不知道这有什么用。但它确实显示了不同的类型。

    让我复制一下我发布的答案:

    0-arity的Scala 2.x方法可以定义为带括号或不带括号
    ()
    。这用于向用户发出信号,表明该方法具有某种副作用(如打印到std out或销毁数据),而不是没有副作用的方法,后者可在以后实现为
    val

    见:

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

    本公约支持统一准入原则[……]

    总之,Scala鼓励将不带参数且没有副作用的方法定义为无参数方法,即去掉空括号。另一方面,您永远不应该定义一个没有括号的具有副作用的方法,因为这样对该方法的调用看起来就像一个字段选择

    术语 关于0-arity方法有一些令人困惑的术语,因此我将在这里创建一个表:

    Scala编程 scala/scala术语
    def foo:Int
    无参数方法 无效法
    def foo():Int
    空帕伦方法 幂零法
    要回答第二个问题,只需添加一个

    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>            
    
    scala>def foo=println(“foo!”)
    傅:单位
    scala>def测试(arg:()=>Unit)={arg}
    测试:(arg:()=>单位)(=>单位)
    scala>测试(foo)
    res10:()=>单位=
    scala>测试(foo)()
    福!
    斯卡拉>
    
    我建议始终使用以下函数启动定义:

    def bar {}
    
    只有在您被迫将其更改为:

    def bar() {}
    
    理由:让我们从可能使用的角度考虑这2个功能。如何提供信息以及在何处传递信息

    我根本不会将其称为函数:

    def bar {}
    
    它可以被调用为:

    bar
    
    但不是作为一种功能:

    bar()
    
    def baz(f: () => Unit) {}
    
    当我们使用“按名称调用”参数定义高阶函数时,可以使用此栏:

    def bat(f: => Unit) {
        f //you must not use (), it will fail f()
    }
    
    bat(foo)
    
    我们应该记住,单位甚至不是一个函数。您绝对不能将thunk当作函数来处理,因为您不能选择将其作为要存储或传递的函数值来处理。您只能触发实际参数表达式的求值(任意数量)。

    ()
    定义的函数具有更大的使用范围。它可以在与
    bar
    完全相同的上下文中使用:

    def foo() = {}
    //invokation:
    foo
    //or as a function:
    foo()
    
    可以将其传递到具有“按名称调用”参数的函数中:

    def bat(f: => Unit) {
        f //you must not use (), it will fail f()
    }
    
    bat(foo)
    
    此外,如果我们定义了一个高阶函数,它接受的不是名为pamameter的调用,而是一个实函数:

    bar()
    
    def baz(f: () => Unit) {}
    
    我们还可以将
    foo
    传递到
    baz

    baz(foo)
    
    正如我们所看到的,像
    foo
    这样的标准函数具有更大的使用范围。但是使用一个没有定义
    ()
    的函数,再加上定义接受按名称调用参数的高阶函数,让我们使用更清晰的语法

    如果您不尝试归档更好、更可读的代码,或者如果您需要能够将代码段传递给使用“按名称调用”参数定义的函数和使用实函数定义的函数,则将您的函数定义为标准函数:

    def foo() {}
    
    如果您希望编写更清晰易读的代码,并且您的函数没有副作用,请将函数定义为:

    def bar {}
    
    另外,尝试定义高阶函数以接受按名称参数调用,而不是函数。
    仅当您被强制时,仅在这种情况下使用上一选项

    def
    关键字定义的是一个方法,而不是一个函数,尽管区别往往很细微。按照Java中
    int
    vs
    Integer
    的思路思考:前者可以自动装箱到后者中。感谢您描述了“what”后面的“why”。
    另一方面,您永远不应该定义一个没有括号就有副作用的方法,因为这样调用该方法就像