Scala中的通用元组getter方法,可以保留动态类型。
Scala中的通用元组getter方法,可以保留动态类型。
我希望编写一个Scala方法,它接收一个任意大小和类型的元组以及一个索引,并返回元组中该索引位置的元素。我知道如何实现所有功能,但是无法保留类型。我还没有找到一种方法使返回值能够动态匹配元组项的类型。
这是我目前的函数:
def subscript_get(tup: Product, index: Int): Any = { return tup.productElement(index) }
使用示例:
subscript_get((0,1,2,3),0) --> Int = 0
subscript_get((0,1,"asdf",3),2) --> java.lang.String = asdf
我知道之后可以将结果转换回我想要的类型,但这对我来说行不通,因为我不总是知道应该转换为什么类型。
像这样的操作是否可能?谢谢!
无法这样做。如果使用Product
,元组中的值的(编译时)类型会丢失。此外,方法无法根据传入的值来自适应其返回类型(并非完全正确,参见dependent method types,但对于Int
而言是正确的)。
如果不知道要转换成什么类型,可以使用模式匹配:
subscript_get(..., 1) match { case v: Int => // 对Int类型进行操作 case v: String => // 对String类型进行操作 // 忽略其他情况 case _ => sys.error("不知道如何处理这个值") }
问题的出现原因是需要实现一个通用的getter方法来获取Scala中元组的元素,同时要保留动态类型。解决方法是使用Scala的宏系统来实现这个方法。
在给出的代码中,使用了宏来实现at
方法,该方法接受一个元组t
和一个整数index
作为参数。宏的实现在at_impl
方法中,通过检查index
的值和元组t
的类型来动态获取元组的元素。
具体实现中,首先导入了Scala的宏相关库:import scala.language.experimental.macros
和import scala.reflect.macros.Context
。然后定义了一个名为ProductIndexer
的对象,其中包含了at
方法和at_impl
方法。
at_impl
方法使用了上下文c
和类型T
的隐式类型标记WeakTypeTag
。在方法体内部,首先导入了c.universe._
,然后通过检查index
的值来判断是否是整数字面量。
如果是整数字面量,且值大于等于0,并且元组t
的类型中存在一个名为"_" + (n + 1).toString
的方法,那么就返回t
的"_" + (n + 1).toString
方法的结果。否则,如果index
的值是整数字面量,但在元组t
的类型中不存在对应的方法,则抛出一个编译时错误。最后,如果index
的值不是整数字面量,则同样抛出一个编译时错误。
通过调用at
方法并传入一个元组triple
和一个整数index
,可以获取到元组中对应索引位置的元素,并且返回的结果是静态类型的。如果给at
方法传入一个超出范围的索引或者非字面量的整数,将会得到一个友好的编译时错误。
这种实现方式非常方便和灵活,但可惜需要使用字面量来作为索引。是否可以使用隐式证据来推断索引值呢?