Scala`def loop():Unit = loop`,为什么循环永远?

时间:2017-04-22 16:05:13

标签: python scala

在Scala中

def loop():
   Unit = loop

当你打电话时:

loop()

它将永远循环。我无法理解为什么?

例如在Python中:

def loop():
    return loop

当你打电话时:

loop()

返回

<function loop at 0x7f276e680668>

在Scala中,所有内容都是自动添加()的表达式吗?

println(println())

返回一个空行:

()

6 个答案:

答案 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()()()()()()