Scala中的通用元组getter方法,可以保留动态类型。

10 浏览
0 Comments

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

我知道之后可以将结果转换回我想要的类型,但这对我来说行不通,因为我不总是知道应该转换为什么类型。

像这样的操作是否可能?谢谢!

0
0 Comments

无法这样做。如果使用Product,元组中的值的(编译时)类型会丢失。此外,方法无法根据传入的值来自适应其返回类型(并非完全正确,参见dependent method types,但对于Int而言是正确的)。

如果不知道要转换成什么类型,可以使用模式匹配:

subscript_get(..., 1) match {
  case v: Int    => // 对Int类型进行操作
  case v: String => // 对String类型进行操作
  // 忽略其他情况
  case _ => sys.error("不知道如何处理这个值")
}

0
0 Comments

问题的出现原因是需要实现一个通用的getter方法来获取Scala中元组的元素,同时要保留动态类型。解决方法是使用Scala的宏系统来实现这个方法。

在给出的代码中,使用了宏来实现at方法,该方法接受一个元组t和一个整数index作为参数。宏的实现在at_impl方法中,通过检查index的值和元组t的类型来动态获取元组的元素。

具体实现中,首先导入了Scala的宏相关库:import scala.language.experimental.macrosimport 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方法传入一个超出范围的索引或者非字面量的整数,将会得到一个友好的编译时错误。

这种实现方式非常方便和灵活,但可惜需要使用字面量来作为索引。是否可以使用隐式证据来推断索引值呢?

0