是否可以匹配Scala中的参数类型?假设我有一个函数接收两个参数:value
和type
。我想使用模式匹配来进行类型转换。
这样的事情:
datatype match {
case IntegerType => return value.toInt
case FloatType => return value.toFloat
case StringType => return value
case DecimalType(_,_) => return BigDecimal(value) // this is not working
case _ => return strrepr
}
此处DecimalType
接受两个参数来指定所需精度的精度。它可以是例如:
org.apache.spark.sql.types.DecimalType = DecimalType(10,2)
我尝试了几个选项,似乎没有任何工作:
对于 case DecimalType => return BigDecimal(value)
,我得到:
error: pattern type is incompatible with expected type;
found : org.apache.spark.sql.types.DecimalType.type
required: org.apache.spark.sql.types.DataType
Note: if you intended to match against the class, try `case DecimalType(_,_)`
对于 case DecimalType(_,_) => return BigDecimal(value)
,我得到:
error: result type Boolean of unapply defined in method unapply in object DecimalType does not conform to Option[_] or Boolean
对于 case DecimalType[_,_] => return BigDecimal(value)
,我得到:
error: org.apache.spark.sql.types.DecimalType does not take type parameters
答案 0 :(得分:4)
问题是在代码中使用return
。你说你在某个地方使用这个代码片段。该函数的返回类型是什么?显然,你打算有时它是Integer,有时是String,有时是BigDecimal;但是如果使用return
,它将查看返回对象的类型以确定函数的返回类型。通常,您应该强烈避免在Scala代码中使用return
。返回函数体中的最后一个求值。使用return
的唯一情况是,您希望强制在函数体中的其他位置返回值。但是,更好的方法是将返回对象保存在变量中,并在函数体的最后一行评估该变量。永远不要使用退货!
没有return
可行
scala> val datatype = DecimalType(10, 2)
datatype: org.apache.spark.sql.types.DecimalType = DecimalType(10,2)
scala> val value = BigDecimal(10)
value: scala.math.BigDecimal = 10
scala> datatype match {case DecimalType(_,_) => value}
res150: scala.math.BigDecimal = 10
**返回问题**
scala> def test = {datatype match {case DecimalType(_,_) => return value}}
<console>:138: error: method test has return statement; needs result type
def test = {datatype match {case DecimalType(_,_) => return value}}
scala> def test:BigDecimal = {datatype match {case DecimalType(_,_) => return value}}
test: BigDecimal
scala> def test:DataType = {datatype match {case DecimalType(_,_) => return value}}
<console>:138: error: type mismatch;
found : scala.math.BigDecimal
required: org.apache.spark.sql.types.DataType
def test:DataType = {datatype match {case DecimalType(_,_) => return value}}
scala> def test3 = {datatype match {case DecimalType(_,_) => value}}
test3: scala.math.BigDecimal
答案 1 :(得分:4)
原来只有DecimalType模式与零参数匹配:
case DecimalType() => ...
如果您需要精度和比例,您必须定义案例的类型并手动提取它们:
datatype match {
case dt: DecimalType =>
val precision = dt.precision
val scale = dt.scale
...
答案 2 :(得分:0)
可能是我正在处理的代码所特有的,或者可能因SQL供应商而异,但是我发现DecimalType
没有单一的基础类型。有时我会收到火花Decimal
,而其他时候会收到Java BigDecimal
。如果我尝试将getAs[Decimal]
设为BigDecimal
时遇到异常。如果我尝试将getAs[BigDecimal]
设为Decimal
,则会出现异常。
要解决此问题,我必须在匹配DecimalType
之后再进行一些嗅探:
case d: DecimalType =>
// Oddly a column that matches to DecimalType can be of several different
// class types and trying to getAs[Decimal] when it's a BigDecimal and/or
// trying to getAs[BigDecimal] when the column is a Decimal results in an
// exception, so make the right decision based on the instance class.
val decimal = row.get(index) match {
case bigDecimal: java.math.BigDecimal => Decimal(bigDecimal)
case decimal: Decimal => decimal
case _ => throw(
new RuntimeException("Encountered unexpected decimal type")
)
}
知道decimal
的类型为Decimal
,您就可以从那里进行任何操作。