当应用尾部递归而不进行注释时,是否有一个Scala编译器标志来警告?

当应用尾部递归而不进行注释时,是否有一个Scala编译器标志来警告?,scala,sbt,scala-compiler,Scala,Sbt,Scala Compiler,我希望编译器在我没有告诉它使用注释时,在它将尾部递归应用到我的一个函数时发出警告。这可能吗 动机:由于逻辑错误,我很少写无限循环,但我已经完成了打字错误(是的,这是可能的)。通常,递归无限循环只会告诉您堆栈溢出异常有什么问题,但如果它们以递归方式编译尾部,它就会挂起 忘记new关键字以及带有默认参数的case类就是一个很好的例子,我曾经两次愚蠢地发现了这个例子: case class A(a: Int, b: Int = 1) object A { def apply(a: Int): A

我希望编译器在我没有告诉它使用注释时,在它将尾部递归应用到我的一个函数时发出警告。这可能吗

动机:由于逻辑错误,我很少写无限循环,但我已经完成了打字错误(是的,这是可能的)。通常,递归无限循环只会告诉您堆栈溢出异常有什么问题,但如果它们以递归方式编译尾部,它就会挂起

忘记
new
关键字以及带有默认参数的case类就是一个很好的例子,我曾经两次愚蠢地发现了这个例子:

case class A(a: Int, b: Int = 1)

object A {
  def apply(a: Int): A = A(a)

导致无SO的无限循环,但
def apply(a:Int):a=new a(a)
不我认为编译器没有这个功能,但IntelliJ在Inspections>Scala:General下提供了一个“无尾递归注释”

检测不带@tailrec注释的尾部递归方法,该注释验证将使用尾部调用优化编译该方法


避免在实际情况下声明函数返回类型:
def apply(a:Int)=a(a)
将无法编译,因此您将知道有问题。

对象a{def b:Any=c;def c:Any=b}-编译器根本无法警告您可能犯的每一个错误。您还可以创建一个无限循环,其中递归调用不在尾部递归位置。所以你提出的警告也不起作用。有点离题,但如果你为代码编写单元测试,这些问题就不会发生arise@MrWiggles不是真的。1.单元测试必须连续运行或频繁手动调用,2。即使他们被吊死了,他们也不会告诉你出了什么问题,只是说出了什么问题。SBT(和个人环境)在正常情况下可能会很慢、不可预测且不稳定(我的公司笔记本电脑绝对糟糕,这要感谢安全方面的白痴在它上面放了无用的、不必要的赛门铁克)。@0_uu;不,请更仔细地阅读这个问题,这只会让调试变得非常简单。1。无论如何,您的单元测试应该非常频繁地运行,至少当您刚刚更改了一段代码时。2.如果您足够频繁地运行测试,您可以将中断的内容缩小到您刚刚进行的更改集。3.如果SBT如您所述,我将停止使用它-就我个人而言,我使用gradle进行Scala工作黄色下划线很好,我总是注意这些。很好,我真的很高兴确实有一个解决方案。您可以将它配置为错误级别,即使是在Intelligent内部编译,声明类型通常会增加编译时检查。将类型弄糊涂比偶然使用尾部递归函数更常见。把类型弄糊涂是BAU,偶然的尾部递归可能每隔几个月发生一次。@samthebest:我说的是“实际的时候”,记得吗?
def-apply(a:Int):a=新的a(a)
def-apply(a:Int)=新的a(a)
更安全?它“增加”了什么样的“编译时检查”?不要说“一般”,要具体。这就是工程的全部,与宗教相反。做出理性的决定,并基于真正的技术优势,而不是一些僵化的“经验法则”,虽然它只是一个代用品,但实际上并不是弱者的拐杖。我同意在某些情况下省略注释可以吗?确实是这样的情况,我不同意人们应该“避免”根据经验规则声明类型;)你在自相矛盾,“避免”意味着一种默认的立场或倾向,而不仅仅是手头的细节。此外,该问题特别要求提供一种防止意外无限尾递归的一般方法,您必须暗示您自己的解决方案“一般”应用,否则它作为答案完全没有意义。。。如果我一般不能应用你的“解决方案”,那么你基本上是在说“当你知道你正在进行尾部递归调用时,不要注释类型,那么编译器会告诉你正在进行尾部递归调用”,在这种情况下,我不需要被告知!!思考“嗯,我可能会导致无限尾递归,我最好不要注释类型”的目的是什么??我可能会想“嗯,我可能会导致无限尾递归,我最好检查一下我是否导致了无限尾递归”。@samthebset不,我不是这么说的。我是说“不要使用类型归属,除非您知道在特定情况下应该使用它们的好的和具体的原因”。