【问题标题】:Represent T* as concrete type将 T* 表示为具体类型
【发布时间】:2014-02-24 18:16:50
【问题描述】:

(T,T)*在擦除后解析为Seq[(T,T)],但是如何将(T,T)*本身表示为一个类型?

我问的原因是我使用的 API 定义了:

def foo(bar: (String,String)*) = ...

但当我尝试传入Seq[(String,String)] 时失败。

我的拉取请求添加:

def foo(bar: Seq[(String,String)]) = ...

由于两个方法在擦除后具有相同的类型而导致崩溃。

星形投影可以表示为具体类型吗?

【问题讨论】:

  • 没有类型T*(对于任何T)。它仅作为一种模式相关,用于将多个实际参数绑定到具有某种Seq[T] 的单个形式参数。

标签: scala types projection concrete


【解决方案1】:

如果你跟随:_*,你可以传递Seq,如下所示:

val s:Seq[(String, String)] = Seq( ("a", "b"), ("c", "d"), ... )
foo(s:_*)

所以你不应该需要两个签名。

【讨论】:

  • +1 谢谢!我不希望在每个调用站点都使用 :_*,这有点麻烦/神秘,但比我为满足 API 方法的重载之一而采用的隐式 ListMap hack 更好。
  • 我同意。我希望有一种方法可以让签名在这两种情况下都能干净地工作,但我不知道有一个。也许其他人会过来告诉我们如何让它发挥作用。
  • 这有点奇怪,但考虑到其他形式的魔法可能会造成多么混乱,例如 autotupling,如果它能够无缝地隐藏 vargs 而不会令人惊讶,那将是令人惊讶的。
【解决方案2】:

消除已擦除签名的歧义:

scala> class X { def f(is: Int*) = is.sum }
defined class X

scala> class Y extends X { def f(is: Seq[Int])(implicit d: DummyImplicit): Int = f(is: _*) }
defined class Y

scala> new Y().f(1 to 10)
res3: Int = 55

或者这样更好,集合中的签名总是看起来像这样表示“两个或更多”:

scala> class X {
     | def f(i: Int): Int = i
     | def f(is: Seq[Int]): Int = is.sum
     | def f(i: Int, j: Int, rest: Int *): Int = i + j + rest.sum
     | }
defined class X

scala> new X().f(3)
res9: Int = 3

scala> new X().f(3,4)
res10: Int = 7

scala> new X().f(3,4,5)
res11: Int = 12

scala> new X().f(1 to 10)
res12: Int = 55

你不能引用重复的参数类型,就像你不能引用一个按名称的参数类型一样。所以你不能转换成它。但是,您可以通过名称反射性地检测到它:

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> typeOf[X].member(TermName("f")).asMethod.paramss.flatten.head.asTerm.typeSignature.typeSymbol.name
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
res4: reflect.runtime.universe.Symbol#NameType = <repeated>

有内部 API,definitions.isRepeated(sym),如果你想强制转换的话。

【讨论】:

  • +1 详尽的解释,如果能在此同时给出两个答案,那就太好了。现在我明白为什么 API 定义了 (T,T)* 而不是 Seq[(T,T)],重复参数。
猜你喜欢
  • 2012-08-01
  • 1970-01-01
  • 2016-10-28
  • 2019-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 2020-10-29
相关资源
最近更新 更多