在Scala中
def loop():
Unit = loop
当你打电话时:
loop()
它将永远循环。我无法理解为什么?
例如在Python中:
def loop():
return loop
当你打电话时:
loop()
返回
<function loop at 0x7f276e680668>
在Scala中,所有内容都是自动添加()
的表达式吗?
println(println())
返回一个空行:
()
答案 0 :(得分:2)
来自Scala style guide:
“Scala允许在arity-0(无参数)方法上省略括号:
reply()
// is the same as
reply
但是,只有在相关方法没有副作用(纯函数)时才应使用此语法。换句话说,在调用queue.size时省略括号是可以接受的,但在调用println()时则不行。该约定反映了上面给出的方法声明约定。
宗教观察此惯例将极大地提高代码的可读性,并使一目了然的任何给定方法的最基本操作更容易理解。只是为了保存两个字符而拒绝省略括号的冲动!“
答案 1 :(得分:1)
您可以省略括号,并且不带参数调用函数。它不像Python。
答案 2 :(得分:1)
在Scala中,可以使用括号或不使用括号调用不带参数的方法,但仅在使用括号定义时才会调用。
def one() = 1
def two = 2
one // 1
one() // 1
two // 2
two() // error: Int does not take parameters
()
的{{1}}输出略有不同。 println(println())
语句返回println()
,这是一种只有一个可能值的类型,表示为Unit
。
答案 3 :(得分:1)
也可以在Scala中获得对非匿名函数的引用。例如,这里我们有两个函数:
def callFunc(f: Unit => Unit): Unit = f()
def printUnit(x: Unit): Unit = println(x)
第一个函数接受对另一个函数的引用,该函数返回Unit
,调用该函数并返回结果Unit
,而第二个函数采用类型Unit
的值,打印出来,并返回Unit
。
例如,以下编译:
callFunc(printUnit)
就像这样:
printUnit(callFunc(printUnit))
但不是这样:
callFunc(printUnit())
为什么呢?因为callFunc
引用了一个带有签名Unit => Unit
的函数,printUnit
满足,所以编译器会发现我们必须要<function1>
个对象。然后返回值Unit
的值printUnit
接受并打印。
但是,如果我们在printUnit
之后附加了parens,我们会明确地调用它,返回Unit
。所以第三个例子没有编译,因为callFunc
只接受一个函数的引用,它不接受类型为Unit
的简单值。
如果您希望explitly引用编译器无法以其他方式获得该意图的函数,您可以使用currying:
val f = loop _
但是,如果您明确了解类型,编译器可以自己解决这个问题:
val f: () => Unit = loop
答案 4 :(得分:0)
添加答案。除了括号外,Scala的行为与Python类似。比较以下两个例子:
//scala
def loop(): () => Unit = {
println("function executed")
loop _
}
scala> loop
function executed
res0: () => Unit = <function0>
scala> loop _
res1: () => () => Unit = <function0>
#python
def loop():
print("function executed")
return loop
>>> loop()
function executed
<function loop at 0x1090f07d0>
>>> loop
<function loop at 0x1090f07d0>
不同之处在于,你可以通过调用loop()
执行该函数,引用调用loop
的函数,在Scala中你可以执行调用loop()
或{{1}的函数。并引用调用loop
的函数。
答案 5 :(得分:0)
只是为了添加所有其他答案:在scala中输入loop
的最有趣和最正确的方法就是这样。
def loop(): T forSome {type T <: () => T} = {
println("function executed")
loop _
}
loop()()()()()()