Java 机具重复时堆栈溢出,直到在Scala中
我想在Scala中实现一个Repeat-Until 注释代码将抛出StackOverflowException 但是代码现在在main方法中运行 但我不知道为什么,这两个片段之间有什么区别Java 机具重复时堆栈溢出,直到在Scala中,java,scala,Java,Scala,我想在Scala中实现一个Repeat-Until 注释代码将抛出StackOverflowException 但是代码现在在main方法中运行 但我不知道为什么,这两个片段之间有什么区别 object REPEAT{ class REPEAT(command: => Unit){ def UNTIL(cond: => Boolean):Unit = { command if(!cond) UNTIL(cond)
object REPEAT{
class REPEAT(command: => Unit){
def UNTIL(cond: => Boolean):Unit = {
command
if(!cond) UNTIL(cond)
}
}
def REPEAT(command: => Unit): REPEAT = {
new REPEAT(command)
}
def main(args: Array[String]) {
/* this code work well */
var i = 0
REPEAT { i+= 1; println(i)} UNTIL (i == 100)
/*
// something wrong in this code.
var i = 0
new REPEAT {
i += 1; println(i)
} UNTIL (i == 100)
*/
}
}
ps:我发现了错误的代码,只需将VARI更改为1,但不要再更改它
错误代码的输出:
一,
线程“main”java.lang.StackOverflower中的异常位于
重复$$anon$1$$anonfun$$lessinit$大于$1。应用$mcV$sp(重复。scala:15)
在REPEAT$REPEAT.UNTIL时(REPEAT.scala:4)
这就是问题所在:
new REPEAT {
i += 1; println(i)
} UNTIL (i == 100)
相当于:
new REPEAT() {
i += 1; println(i)
} UNTIL (i == 100)
因此,实际上您正在使用command=()
和i+=1创建REPEAT
类的新实例;println(i)
在构造函数中-因此i++
只重复一次,而()
则无限重复
正确的称呼方式是:
new REPEAT({
i += 1; println(i)
}) UNTIL (i == 100)
原因是您不必在scala中使用Unit
type显式指定单个参数:
scala> class Aaaa(a: Unit)
defined class Aaaa
scala> new Aaaa //parenthesis is not required for 'new'
res10: Aaaa = Aaaa@17de44d4
scala> def aaaa(a: Unit) = 5
aaaa: (a: Unit)Int
scala> aaaa()
res13: Int = 5
这就是问题所在:
new REPEAT {
i += 1; println(i)
} UNTIL (i == 100)
相当于:
new REPEAT() {
i += 1; println(i)
} UNTIL (i == 100)
因此,实际上您正在使用command=()
和i+=1创建REPEAT
类的新实例;println(i)
在构造函数中-因此i++
只重复一次,而()
则无限重复
正确的称呼方式是:
new REPEAT({
i += 1; println(i)
}) UNTIL (i == 100)
原因是您不必在scala中使用Unit
type显式指定单个参数:
scala> class Aaaa(a: Unit)
defined class Aaaa
scala> new Aaaa //parenthesis is not required for 'new'
res10: Aaaa = Aaaa@17de44d4
scala> def aaaa(a: Unit) = 5
aaaa: (a: Unit)Int
scala> aaaa()
res13: Int = 5
如果取消注释您的注释代码(
var i
定义了两次),它将不会编译。没有它-按预期打印1到100。如果您写入重复{i+=1;println(i)}直到(i==100)
两次-它将导致堆栈溢出,因为它将从i=101开始,以i=无穷大结束。很抱歉,我没有清楚地表达它。在main方法中运行的代码是替换注释的代码。目前,我非常确定您的UNTIL
方法不是尾部递归的,因为它既不是private
也不是final
。使用更长的循环,您也会得到一个堆栈溢出。您应该向该方法添加@tailrec
注释。如果取消注释您的注释代码(var i
定义了两次),则不会编译该注释。没有它-按预期打印1到100。如果您写入重复{i+=1;println(i)}直到(i==100)
两次-它将导致堆栈溢出,因为它将从i=101开始,以i=无穷大结束。很抱歉,我没有清楚地表达它。在main方法中运行的代码是替换注释的代码。目前,我非常确定您的UNTIL
方法不是尾部递归的,因为它既不是private
也不是final
。使用更长的循环,您也会得到一个堆栈溢出。您应该向该方法添加@tailrec
注释。