【问题标题】:How can I access implicit "implicit" i.e. def a[A :B] or def a[A <% B]?如何访问隐式“隐式”,即 def a[A :B] 或 def a[A <% B]?
【发布时间】:2012-02-27 18:45:20
【问题描述】:

例如,我需要访问函数def a[A:ClassManifest] 中的清单以获取擦除类。我可以使用 Predef.implicitly 函数,但在这种情况下,我的代码将与使用完整形式 def a[A](implicit b:ClassManifest[A]) 一样长。 那么这些隐式参数是否有方便的生成名称?

【问题讨论】:

  • 你总是可以用更小的名字声明一个方法,但是你应该依赖于Scalac生成的魔法名字。

标签: scala implicit-conversion implicit


【解决方案1】:

Predef 中有三个预定义的方法可以用于Manifests、ClassManifests 和OptManifests:分别为manifest[T]classManifest[T]optManifest[T]。您可以根据相同的模式为其他类型类编写自己的此类“隐式 getter”。例如manifest[T]:

def manifest[T](implicit m: Manifest[T]) = m

所以你可以这样写自己的:

trait UsefulTypeclass[A] {
  def info = 42 // sample method
}

// the “implicit getter”
def usefulTypeclass[A](implicit tc: UsefulTypeclass[A]) = tc

// a method that uses the implicit getter
def foo[A: UsefulTypeclass] =
  usefulTypeclass[A].info

【讨论】:

  • 一个巧妙的技巧:如果将隐式 getter 命名为“apply”并将其放在 UsefulTypeclass 的伴生对象上,则可以使用“UsefulTypeclass[T]”作为代表 T 的类型类实例的值无需导入类型类本身以外的任何内容。
  • @RM 不错的把戏。我想它必须是UsefulTypeclass[T]()(加上额外的())。
  • 其实它不需要括号。如果你有(请原谅缺少格式) object TC { def apply[T](implicit x: TC[T]) = x } 你可以只用“TC[SomeClass]”来调用它,因为正在定义“apply”作为具有隐式参数列表的无参数方法,[SomeClass] 将其与对 TC 对象的引用消除歧义。它对 TC.apply[SomeClass](theImplicitValue) 脱糖
  • @RM 哦,很好。谢谢你的解释。
【解决方案2】:

去救援!

我拿了这个代码:

object TestThing extends App {
  def one { println("one") }
  def two[T] { println("two") }
  def three[T : Manifest] { println("three") }
  def four[T: Manifest, U : Manifest] { println("four") }
}

并通过 scalap 运行它。这是我得到的:

object TestThing extends java.lang.Object with scala.App with scala.ScalaObject {
  def this() = { /* compiled code */ }
  def one : scala.Unit = { /* compiled code */ }
  def two[T] : scala.Unit = { /* compiled code */ }
  def three[T](implicit evidence$1 : scala.Predef.Manifest[T]) : scala.Unit = { /* compiled code */ }
  def four[T, U](implicit evidence$2 : scala.Predef.Manifest[T], evidence$3 : scala.Predef.Manifest[U]) : scala.Unit = { /* compiled code */ }
}

如您所见,第一个隐式 Manifest 称为 evidence$1。第二个和第三个——虽然在不同的范围内!——被称为evidence$2evidence$3。所以...这就是您引用清单的方式。

尽管如此,删除类中较高的 Manifest 会更改文件中较低的 Manifest 的名称,这对我来说似乎有点可怕。同样,IntelliJ Scala 插件的语法高亮似乎认为 four() 范围内的 Manifest 变量是 evidence$1evidence$2 也无济于事,并且它认为 evidence$3 不是有效的那里的变量(即使它是,而evidence$1 不是)。总的来说,也许这些事情应该被视为关于使用隐式 Manifest 变量的警告信号?

【讨论】:

  • 当然,这些名称应该是内部实现细节,而不是依赖!
  • 这就是为什么你使用implicitly...试图在你的代码中使用evidence$1等将无法编译。
  • @LuigiPlinge 实际上,它确实可以编译......足够可怕。
猜你喜欢
  • 1970-01-01
  • 2011-03-26
  • 1970-01-01
  • 2012-02-08
  • 2015-06-12
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
相关资源
最近更新 更多