为什么在此代码块中需要返回?

时间:2015-07-19 21:18:59

标签: scala

下面的代码只是通过getFileName方法返回一个随机字符串:

import scala.collection.mutable.ListBuffer

object RTest extends App {

  var currentFileNameList: ListBuffer[String] = new ListBuffer

  def getFileName(): String = {
    var fileName = java.util.UUID.randomUUID().toString();

    while (true) {
      if (!currentFileNameList.contains(fileName)) {
        currentFileNameList = currentFileNameList :+ fileName
        return fileName
      } else {
        fileName = java.util.UUID.randomUUID().toString();
      }
    }

    throw new RuntimeException("Error - filename not generated")
  }

  println(getFileName())
}

如果我删除行中的return语句:return fileName,那么方法getFileName似乎陷入无限循环并且不会终止。

为什么需要明确的退货? scala编译器是否应该推断var fileName的返回?

4 个答案:

答案 0 :(得分:8)

正如om-nom-nom在评论中已经说过,它并不是关于类型推断,而是控制流问题。

使用return你打破了(否则)无限循环。

此外,不是问题的真正部分,但由于您使用的是随机UUID,您可以删除重复检查代码并简单地按原样返回生成的UUID,除非您的要求非常高。

According to Wikipedia

  

[生成重复字符串的概率]约为0.00000000006(6×10-11),相当于一年内创建几十万亿UUID并且有一个重复的可能性。

在“正常”的情况下,我只会做

def getFileName: String = java.util.UUID.randomUUID.toString

并完成它。

答案 1 :(得分:2)

由于这个障碍......

 while (true) {
  if (!currentFileNameList.contains(fileName)) {
    currentFileNameList = currentFileNameList :+ fileName
    return fileName
  } else {
    fileName = java.util.UUID.randomUUID().toString();
  }
}

你处在一个无限循环中,因为"真实"从不改变。通过返回函数,您将跳出此循环(以及完全脱离函数)。

你可以做点像......

object RTest extends App {

    var currentFileNameList: ListBuffer[String] = new ListBuffer

    def getFileName(): String = {
        var fileName = java.util.UUID.randomUUID().toString();

        while (currentFileNameList.contains(fileName)) {
            fileName = java.util.UUID.randomUUID().toString();                    
        }
        currentFileNameList = currentFileNameList :+ fileName;
        return fileName;
    }

    println(getFileName())
}

哪个应该具有相同的效果。

答案 2 :(得分:2)

没有循环,变量或(显式)递归

def getFileName(): String = {
  val fileName = Iterator.continually(java.util.UUID.randomUUID().toString())
                         .find(!currentFileNameList.contains(_)).get
  currentFileNameList += fileName
  fileName
} 

答案 3 :(得分:0)

你不应该循环或使用变种:

import scala.collection.mutable.ListBuffer

object Test extends App {

  val currentFileNameList: ListBuffer[String] = new ListBuffer

  @annotation.tailrec
  def getFileName(): String = {
    val fileName = java.util.UUID.randomUUID().toString();

    if (!currentFileNameList.contains(fileName)) {
      currentFileNameList += fileName
      fileName
    } else {
      getFileName()
    }
  }

  println(getFileName())
}