[英]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
有人可以幫我了解一下:
為什么簡單類型匹配會產生期望的結果,但是並沒有傳遞給對象?
我該怎么做才能更正我的代碼?
在此先感謝您,這讓我動了好幾個小時!
編輯
好的,因此,基於@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
}
結果可以是Int
或Boolean
,因此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.