Scala中def foo={}和def foo()={}之间有什么区别?
给出了以下在Scala中定义函数的结构,您能解释一下区别是什么,以及含义是什么吗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:
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
vsInteger
的思路思考:前者可以自动装箱到后者中。感谢您描述了“what”后面的“why”。另一方面,您永远不应该定义一个没有括号就有副作用的方法,因为这样调用该方法就像