【问题标题】:Inferred type in a Scala programScala 程序中的推断类型
【发布时间】:2014-04-21 00:57:11
【问题描述】:

Scala REPL 显示表达式的推断类型。有没有办法知道普通 Scala 程序中的推断类型?

例如,

val x = {
//some Scala expressions
}

现在我想知道 x 的实际类型。

【问题讨论】:

  • val x : String = { } 你指的是这个吗?
  • 是的,在某些情况下很容易知道推断的类型(在这种情况下为 String),但在其他情况下可能会更复杂。
  • 所以你想在运行时检查它是什么类型?喜欢if(x.isInstanceOf[String])
  • 不,我想编写程序打印推断的类型是字符串,就像它在 REPL 上一样。
  • 对不起,我对 REPL 不太熟悉。据我所见,它会打印出x: java.lang.String = abc 之类的类型,对吗?

标签: scala type-inference read-eval-print-loop


【解决方案1】:

也许TypeTag 就是您要找的东西?

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

scala> def typeOf[T](x:T)( implicit tag: TypeTag[T] ) = tag
typeOf: [T](x: T)(implicit tag: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]

scala> class Foo( a:Int )
defined class Foo

scala> trait Bar
defined trait Bar

scala> val x = new Foo(3) with Bar
x: Foo with Bar = $anon$1@62fb343d

scala> val t = typeOf(x)
t: reflect.runtime.universe.TypeTag[Foo with Bar] = TypeTag[Foo with Bar]

scala> t.tpe
res20: reflect.runtime.universe.Type = Foo with Bar

scala> t.tpe.toString
res21: String = Foo with Bar

并且只是为了证明它产生表达式的静态类型而不是对象的动态类型:

scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)

scala> val s:Seq[Int] = l
s: Seq[Int] = List(1, 2, 3)

scala> typeOf(s)
res22: reflect.runtime.universe.TypeTag[Seq[Int]] = TypeTag[scala.Seq[Int]]

【讨论】:

  • Scala REPL 内部使用什么?
  • REPL 早在 TypeTag 被引入之前就存在了,所以至少有一次 REPL 没有使用它们。我对 REPL 的实现了解不多,但显然它会编译你输入的代码;也许类型信息是编译器 API 提供的一部分。
  • 也许您真正想知道的是,您从 TypeTag 获得的结果是否与您从 REPL 获得的结果相同,或者其他一些类似类型的信息。他们是一样的;当您像我们在这里一样使用 TypeTag 时,编译器只会创建一个 TypeTag 对象,其中包含编译期间产生的类型信息。
【解决方案2】:

表达式的类型在编译时是静态已知的。

要在运行时访问它,您可以使用 TypeTag 和其他答案一样,或者使用微不足道的宏:

scala> import scala.language.experimental.macros
import scala.language.experimental.macros

scala> import reflect.macros.blackbox.Context
import reflect.macros.blackbox.Context

scala> def impl(c: Context)(x: c.Expr[Any]): c.Expr[String] = { import c.universe._
     | c.Expr[String](Literal(Constant(c.typecheck(x.tree.duplicate).tpe.toString))) }
impl: (c: scala.reflect.macros.blackbox.Context)(x: c.Expr[Any])c.Expr[String]

scala> def f(x: =>Any) = macro impl
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
defined term macro f: (x: => Any)String

scala> trait A; trait B extends A; trait C extends A
defined trait A
defined trait B
defined trait C

scala> f(List(new B{}, new C{}))
res2: String = List[A]

REPL 也只报告编译器分配给表达式树的类型。

【讨论】:

    猜你喜欢
    • 2012-11-29
    • 1970-01-01
    • 2023-03-08
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多