【问题标题】:Scala simple function returns type mismatch errorScala简单函数返回类型不匹配错误
【发布时间】:2020-05-27 21:39:38
【问题描述】:

我有一个向量列表。每个向量以Vector(Double,Double) 的形式表示一个范围。我想创建一个给定输入数字的函数,找到它包含在哪个向量中并返回该向量的索引。我不知道是否有更简单的方法可以做到这一点,我是 Scala 新手,但我的代码如下:

val vectors = #List of vectors ( List[scala.collection.immutable.IndexedSeq[Double]] )

def in_range(start: Double, end: Double, x : Double): Boolean = {(x>= start && x<end)}

def find_index(x:Double): Int = {
    for(i <- 0 to n){
     if( in_range(vectors(i)(0),vectors(i)(1),x)){ 
        return i
     }
}

我收到以下错误:

<console>:28: error: type mismatch;
 found   : Unit
 required: Int
        for(i <- 0 to 10){
              ^

【问题讨论】:

    标签: scala


    【解决方案1】:

    如果for 在没有返回值的情况下终止,它将返回Unit 而不是所需的Int,因此会出现错误消息。

    但是对于这类事情,您应该查看像 find 这样的方法,而不是遍历集合的索引。例如

    def find_index(x: Double): Int =
      vectors.indexWhere(v => in_range(v(0), v(1), x))
    

    【讨论】:

      【解决方案2】:

      您的代码中有很多错误,让我们一一修复。

      最重要的是 Scala 中没有 return(嗯,它确实存在,但你是 shouldn't use it)。
      Scala 中,块的返回是其最后一个表达式的返回。因此,在您的情况下,find_index 的返回是 for(){...} 的返回,这实际上不是 for 循环,而是 for comprehension;如果你读过documentation,你就会知道它只需要一个简单的foreach调用,它返回Unit,而不是Int

      所以,你可以这样欺骗编译器:

      def find_index(x:Double): Int = {
          for(i <- 0 to n){
           if( in_range(vectors(i)(0),vectors(i)(1),x)){ 
              return i
           }
           -1 // default return value.
      }
      

      但这只是 Scala 中的糟糕代码。 你可能习惯了旧的命令式循环(对于你命名事物的方式,我假设你有一个 Python 背景)Scala 不是另一种 OOP 语言,它是 FP 和 OOP 的混合体。
      而且,即使 Scala 允许您使用命令式,您也会发现该语言为您提供了a lot of useful tools 以使代码更简单。

      其他一些错误包括:语法错误、使用向量而不是元组来表示元组以及假设您总是可以返回一个值。

      代码的更惯用版本是。

      def inRange(start: Double, end: Double, x: Double): Boolean =
        x >= start && x < end
      
      def findIndex(vectors: List[(Double, Double)])(x: Double): Option[Int] =
        vectors.iterator.zipWithIndex.collectFirst {
          case ((start, end), idx) if (inRange(start, end, x)) => idx
        }
      

      旁注,通常我们不会过多地使用索引。也许你真的想要元组而不是元组的索引?

      你可以像这样使用:

      findIndex(List((0, 3), (3, 5), (8, 10)))(3)
      // res: Option[Int] = Some(1)
      // A index was found.
      
      findIndex(List((0, 3), (3, 5), (8, 10)))(6)
      // res: Option[Int] = None
      // A index was not found.
      

      顺便说一句,这些是没有遵循任何实际 Scala 课程而只是阅读语法的人会犯的错误。正如我之前所说,这不仅仅是另一种 OOP 语言,您需要的不仅仅是语法来有效理解和使用 Scala,它还需要范式转换。

      【讨论】:

      • 感觉就像我之前的回答中建议的那样使用indexWhere 是一个更好的选择......
      • @Tim 是的,我不记得那个了,既然你已经回答过了,我决定不编辑我的答案来使用它。无论如何,我不喜欢-1,因为没有匹配项,但这主要是一种风格/设计选择。
      • 另外 (start until end) contains x 比写一个特定的 inrange() 函数要好,恕我直言
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2015-02-24
      相关资源
      最近更新 更多