Почему Scala требует возвращаемый тип для рекурсивных функций? - PullRequest
22 голосов
/ 18 сентября 2010

В приведенном ниже фрагменте кода у меня есть рекурсивный вызов функции, используемый для облегчения повторной попытки в случае сбоя сетевого вызова (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")
   }
 }

Почему это требуется для рекурсивных функций? Моя мысль состоит в том, чтобы просто вернуть истинное / ложное логическое значение, чтобы удовлетворить компилятор ... следующий компилируется нормально.

// 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
  }
}

Ответы [ 2 ]

19 голосов
/ 18 сентября 2010

Насколько я понимаю, рекурсивным функциям нужен возвращаемый тип, потому что алгоритм вывода типов недостаточно силен, чтобы определять возвращаемые типы для всех рекурсивных функций.

Однако вам не нужно составлять тип возвращаемого значения, вам просто нужно объявить тип возвращаемого значения, которое вы уже использовали: Unit. Unit - это специальный тип только с одним элементом (). Это также тип большинства «операторов» в Scala, и это тип возврата, который объявляется для методов, которым не нужно ничего возвращать, но которые выполняются только для их побочных эффектов (как у вас). Вы можете либо объявить свой метод как возвращающую единицу, как и другие типы

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int):Unit = {

Более идиоматически Scala предоставляет специальный синтаксис для методов, возвращающих единицы, просто не указывайте тип возвращаемого значения и знак равенства

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int){

Согласно руководству по стилю scala, вы должны предпочесть использовать знак равенства

http://docs.scala -lang.org / стиль / declarations.html

10 голосов
/ 18 сентября 2010

Просто удалите = из строки, и он вернет Unit, это означает, что вам не нужно ничего возвращать.

def simpledb_update(name: String, metadata: Map[String,String], attempt: Int) {

Я считаю, что нужно возвращать типы, чтобы убедиться, что все пути рекурсии имеют правильный тип. Для нормальной функции тип будет выведен из всех возвращаемых точек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...