Scala模式匹配返回预期的类型,但随后生成类型不匹配
我有以下scala对象定义:Scala模式匹配返回预期的类型,但随后生成类型不匹配,scala,types,pattern-matching,Scala,Types,Pattern Matching,我有以下scala对象定义: case class RecursiveSettings ( var recursiveFrom: Int, var recursiveTo: Int, var nonRecursiveFrom: Int, var nonRecursiveTo: Int, var betweenReach: Int, var scoresamephrase: Boolean ) 我试图从ArrayBuffer中获取变量: i
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
}
}
}
但是,当我将“我匹配”语句添加回时,我收到了很多此类投诉:
~/match.scala:44: error: type mismatch;
found : AnyVal
required: Int
case 0 => result.recursiveFrom = x
有人能帮我理解一下:
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)匹配{
案例y:Int=>y
案例y:布尔=>y
大小写=>0
}
结果可以是Int
或Boolean
,因此x
的类型将是AnyVal
,因为Scala无法推断单一类型
快速(脏)解决方案
修复代码而不进行大量修改的最简单方法可能是显式地将x
转换为预期类型:
i匹配{
案例0=>result.recursiveFrom=x.asInstanceOf[Int]
案例1=>result.recursiveTo=x.asInstanceOf[Int]
案例2=>result.nonRecursiveFrom=x.asInstanceOf[Int]
案例3=>result.nonRecursiveTo=x.asInstanceOf[Int]
案例4=>result.betweenReach=x.asInstanceOf[Int]
案例5=>result.scoresamephrase=x.asInstanceOf[Boolean]
}
更好的解决方案
我建议您尝试使用不可变的数据结构重新设计代码,并尝试使用更实用的方法来解决问题。这样,您的代码将更具可读性,并且不易产生副作用
例如,通过设置创建新闻设置的方式可以简化很多:
val设置=列表(“,“1”,“2”,“0”,“0”,真)
val newsettings=设置映射{
案例“”=>0
大小写s:String=>s.toInt
案例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)
}
您还可以匹配部分提供的参数,只要您决定哪些参数将接收默认值(此案例可与“完整”案例匹配一起使用):
谢谢@JakubZalas是的,这已经解决了问题,我理解其中的原因,尽管我知道正如你所说,Scala中的类型转换是肮脏的。对于我自己的学习,如果你或其他人有时间,我有兴趣看到一个更优雅的解决方案。再次感谢。很高兴我能帮忙。不要犹豫接受答案。我提出了一个改进建议,可以让你知道该去哪里。我真的不知道你想解决什么问题来建议最好的最终解决方案。你能做的最好的事情就是努力改进你的代码,并在你进步的过程中问更多的问题。另外,这是stackoverflow,您应该努力;)完成;)感谢您让我开始,最后是我在寻找的数组上的大小写匹配。为了跟进@JakubZelas答案中的建议,可以更简单地通过模式匹配列表来实现:
val first::second::third::fourth::fifth::Nil=list(“,”1“,”2“,”3“,true)
,然后定义一个函数来转换字符串(调用iff
),然后定义递归设置(f(first),f(second),…,fifth)。顺便说一句,请查看这篇阿尔文·亚历山大的文章,这篇文章非常有用,是@hoyland的起点,谢谢。这个答案非常有用,谢谢。唯一的问题是数组[String]不允许我处理包含布尔值的OP case。我添加了一个编辑,说明了我选择的处理方法。再次感谢。我假设Array[String]
是您尝试转换的main
方法的原始args
。如果情况并非如此,并且您已经从一个列表[Any]
开始,那么您完全可以不进行布尔
转换(只剩下Int
转换),并且将匹配列表上的而不是数组
;除此之外,代码将只是后续的sameThanks。是的,“List[Any]”在混合大小写中对我有效,但在纯字符串大小写中出现了类型错误。原始数据来自用户通过db接口输入的数据,我还没有构建该接口,并使用“Document.get()”下拉,因此可以是任何类型。。。这就是为什么我最终选择了“数组”。。。如果这是有意义的话……这是完全有意义的,因为Array[\u]
相当于Array[Any]
,非常适合存储各种类型。至于类型错误(我假设这些是不是Integer
s的String
s的转换错误),您可以使用scala.util.control.Exception.allCatch
将字符串
转换为整数
(如果可以转换),或者将其保留为String
(如果不能转换)以实用的方式感谢@Alex,所有这些都非常有用。很抱歉,我无法正确地更新您的答案-等待足够的代表!)
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
}
}
// 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)