簡體   English   中英

Scala模式匹配返回期望的類型,但之后會生成類型不匹配

[英]Scala Pattern Matching returns expected type but generates type mismatch afterwards

我有以下scala對象定義:

case class RecursiveSettings (
    var recursiveFrom: Int,
    var recursiveTo: Int,
    var nonRecursiveFrom: Int,
    var nonRecursiveTo: Int,
    var betweenReach: Int,
    var scoresamephrase: Boolean
    )

我正在嘗試從ArrayBuffer中獲取變量:

import scala.collection.mutable.ArrayBuffer

def main(args: Array[String]){
    var settings = List("","1", "2", "0", "0", true)
    var newsettings = new ArrayBuffer[Any]

    println(settings)

    settings.foreach {a =>
        val z = a match{
            case "" => 0
            case s : String => s.toInt
            case _  => a
        }
        newsettings += z
    }
    println(newsettings)

    var result = new RecursiveSettings(0,0,0,0,0,true)
    println(result)

    for (i <- 0 to (newsettings.length - 1)){
        println("newsettings_i", newsettings(i))

        val x = newsettings(i) match{
            case y : Int => y
            case y : Boolean => y
            case _ => 0
        }
        println("x:", x)
        i match{
            case 0 => result.recursiveFrom = x
            case 1 => result.recursiveTo = x
            case 2 => result.nonRecursiveFrom = x
            case 3 => result.nonRecursiveTo = x
            case 4 => result.betweenReach = x
            case 5 => result.scoresamephrase = x
        }
    }
}

如果我注釋掉i match語句並進行簡單的類型匹配:

for (i <- 0 to (newsettings.length - 1)){
        println("newsettings_i", newsettings(i))
        val x = newsettings(i) match{
            case y : Int => "Int"
            case y : Boolean => "Bool"
            case _ => 0
        }
        println("x:", x)

代碼編譯,運行,我得到:

List(, 1, 2, 0, 0, true)
ArrayBuffer(0, 1, 2, 0, 0, true)
RecursiveSettings(0,0,0,0,0,true)
(newsettings_i,0)
(x:,Int)
(newsettings_i,1)
(x:,Int)
(newsettings_i,2)
(x:,Int)
(newsettings_i,0)
(x:,Int)
(newsettings_i,0)
(x:,Int)
(newsettings_i,true)
(x:,Bool)

但是,當我重新添加i match語句時,會收到很多此類投訴:

~/match.scala:44: error: type mismatch;
found   : AnyVal
required: Int
            case 0 => result.recursiveFrom = x

有人可以幫我了解一下:

  1. 為什么簡單類型匹配會產生期望的結果,但是並沒有傳遞給對象?

  2. 我該怎么做才能更正我的代碼?

在此先感謝您,這讓我動了好幾個小時!

編輯

好的,因此,基於@Alex Savitsky和@Jakub Zalas的信息(感謝伙計們),我已經對原始代碼進行了實質性修改,以使我希望它是功能更面向的東西,可以處理混合的init值類型:

object matcher2{
def main(args: Array[String]):Unit = {

    val init = Array("",1, "4", null, "0", false)
    matchf(init)
}
def matchf(args : Array[_] ) : RecursiveSettings = {
    val settings : RecursiveSettings = args.map{
        case "" => 0
        case "true" => true
        case "false" => false
        case b : Boolean => b
        case s : String => s.toInt
        case i : Int => i
        case null => 0

    } match {
        case Array(recursiveFrom: Int, recursiveTo: Int, nonRecursiveFrom: Int, nonRecursiveTo: Int, betweenReach: Int, scoresamephrase: Boolean) =>
        RecursiveSettings(recursiveFrom, recursiveTo, nonRecursiveFrom, nonRecursiveTo, betweenReach, scoresamephrase)
    }
    println(settings)
    settings
}
}

作為Python的Scala(和Java)的新手,我仍然在功能和靜態類型方面苦苦掙扎,因此,任何評論/建議都深表感謝。

謝謝你的幫助。

您定義的模式匹配無法解析為單一類型:

val x = newsettings(i) match {
    case y : Int => y
    case y : Boolean => y
    case _ => 0
}

結果可以是IntBoolean ,因此x的類型將是AnyVal因為Scala無法推斷單個類型。

快速(又臟)的解決方案

修改代碼而不修改太多的最簡單方法可能是將x顯式轉換為期望的類型:

i match {
    case 0 => result.recursiveFrom = x.asInstanceOf[Int]
    case 1 => result.recursiveTo = x.asInstanceOf[Int]
    case 2 => result.nonRecursiveFrom = x.asInstanceOf[Int]
    case 3 => result.nonRecursiveTo = x.asInstanceOf[Int]
    case 4 => result.betweenReach = x.asInstanceOf[Int]
    case 5 => result.scoresamephrase = x.asInstanceOf[Boolean]
  }

更好的解決方案

我建議您嘗試使用不可變的數據結構重新設計代碼,並嘗試使用功能更強大的方法來解決問題。 這樣,您的代碼將更具可讀性,並且不易產生副作用。

例如,可以大大簡化從設置創建新設置的方式:

val settings = List("","1", "2", "0", "0", true)
val newsettings = settings map {
  case "" => 0
  case s : String => s.toInt
  case a  => a
}

您可以動態地將參數轉換為適當的類型,然后一次匹配整個集合:

// assuming your args is an array of ["", "1", "2", "0", "0", "true"]
val settings: RecursiveSettings = args.map {
    case "" => 0
    case "true" => true
    case "false" => false
    case s: String => s.toInt
} match {
    case Array(recursiveFrom: Int, recursiveTo: Int, nonRecursiveFrom: Int, nonRecursiveTo: Int, betweenReach: Int, scoresamephrase: Boolean) =>
        RecursiveSettings(recursiveFrom, recursiveTo, nonRecursiveFrom, nonRecursiveTo, betweenReach, scoresamephrase)
}

您還可以匹配部分提供的參數,只要您決定哪些參數將接收默認值即可(這種情況可以與“全”大小寫匹配一起使用):

    case Array(recursiveFrom: Int, recursiveTo: Int) =>
        RecursiveSettings(recursiveFrom, recursiveTo, 0, 2, 1, true)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM