scala – 在没有实例的情况下查找产品类型的arity

我想定义一个由通用Product类型参数化的函数,但它可以解决Product的问题.这是一个示例代码段.我想在调用f(…)时进行arity检查,而不是在调用f(…)()时进行.我怎样才能做到这一点?

def f[T<:Product](names:Seq[String],values:()=>T) = {
  () => {
    val x = values()
    if (x.productArity != names.size) scala.sys.error("Size mismatch")
    names.zip(x.productIterator.map(_.toString).toSeq).map(kv => kv._1+"="+kv._2)
  }
}

(这是一个非常无用的功能,仅用于演示.重要的一点是(1)它是按产品类型参数化的,(2)只有当产品的arity与我知道的某个值匹配时,该功能才有意义.调用函数,(3)当我调用函数时,我很难/不可能获得Product的实例.我的实际用例是基于spark RDD写出SQL语句的实用程序类.)

如果有必要,我可以写出一整套函数,每个函数对应一个元组.但这感觉很讨厌,我希望有更好的解决方案.

解决方法

使用类型类可以找到比编写不同方法更好的方法:

case class Arity[P]( get: Int )

object Arity {
  def apply[P]( implicit arity: Arity[P] ) = arity
  implicit def tuple2[A,B] = Arity[(A,B)]( 2 )
  implicit def tuple3[A,B,C] = Arity[(A,C)]( 3 )
  //...
} 

def f[T<:Product:Arity](names:Seq[String],values:()=>T) = {
  () => {
    val x = values()
    if ( Arity[T].get != names.size) scala.sys.error("Size mismatch")
    names.zip(x.productIterator.map(_.toString).toSeq).map(kv => kv._1+"="+kv._2)
  }
}

当然,您需要为所有可能的元组大小写下Arity对象.您可以使用代码生成或使用宏(如果您是大胆和耐心)自动化它.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...