为什么Scala需要递归函数的返回类型?

Jos*_*hua 22 scala

在下面的代码片段中,我有一个递归函数调用,用于在网络调用失败时促进重试(Amazon SimpleDB偶尔会返回503并需要重试.)

当我尝试编译时,Scala抱怨道recursive method simpledb_update needs result type.

// sends data to SimpleDB. Retries if necessary
def simpledb_update(name: String, metadata: Map[String,String], attempt: Int) = {
 try {
  db(config("simpledb_db")) += (name, metadata)
 } catch {
  case e =>
   // if it fails, try again up to 5 times
  if(attempt < 6)
  {
   Thread.sleep(500)
   simpledb_update(name, metadata, attempt + 1)
   } else
     AUlog(name + ": SimpleDB Failed")
   }
 }
Run Code Online (Sandbox Code Playgroud)

为什么递归函数需要这个?我的想法是只返回一个true/false布尔值来满足编译器...以下编译很好.

// sends data to SimpleDB. Retries if necessary
 def simpledb_update(name: String, metadata: Map[String,String], attempt: Int): Boolean = {
 try {
  db(config("simpledb_db")) += (name, metadata)
  true
 } catch {
  case e =>
   // if it fails, try again up to 5 times
   if(attempt < 6)
   {
    Thread.sleep(500)
    simpledb_update(name, metadata, attempt + 1)
   } else
    AUlog(name + ": SimpleDB Failed")
    false
  }
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ith 19

据我所知,递归函数需要一个返回类型,因为类型推断算法不够强大,无法确定所有递归函数的返回类型.

但是,您不需要构成返回类型,只需要声明您已经使用的返回类型:Unit.Unit是一种特殊类型,只有一个元素().它也是Scala中大多数"语句"的类型,并且是为不需要返回任何内容的方法声明的返回类型,但仅针对它们的副作用执行(就像你的那样).您可以将方法声明为返回单位,就像其他类型一样

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int):Unit = {
Run Code Online (Sandbox Code Playgroud)

更具惯用性Scala为单元返回方法提供了一种特殊的语法,只需省略返回类型和等号

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int){
Run Code Online (Sandbox Code Playgroud)

根据scala风格指南,您应该更喜欢使用等号

http://docs.scala-lang.org/style/declarations.html


Tho*_*mas 10

只需从行中删除=,它将返回Unit,这意味着您不需要返回任何内容.

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int) {
Run Code Online (Sandbox Code Playgroud)

我认为需要返回类型,以确保所有递归路径都具有正确的类型.在正常函数上,将从所有返回点推断出类型.

  • 对.这就像尾递归._许多方程式都是可以解决的,没有太多困难.问题是不是所有方程都是可解的.语言规范需要声明明线规则,其中所有可接受的构造都可以由编译器解决,并且所有不可接受的构造都有一个简短的错误消息,说明它们为何不可接受."递归方法需要显式返回类型"是Scala的明线规则之一,并且希望不会太繁琐. (4认同)
  • @Jorg - 实际上,它并不难推断(但它比人们想要的更难).如果得到的每个路径返回值的类型不是递归返回值,那么它必须是返回值的类型.但是当推入相互递归的函数时,这变得复杂. (3认同)
  • 您根本无法从返回点推断出类型,因为至少有一个返回点具有您想要推断的类型. (2认同)