0

Scala 是否有任何等效于 GCC 的typeof扩展?(或 C++ decltype?)

我正在生成引用一些外部代码(可能尚不可用)的代码,并且我需要一种方法来在方法定义中引用该代码的类型

对于单例对象,我可以使用Foo.type,但如果Foo是任意表达式,则不起作用。

更新:

这是一个显示问题的简化示例:

def f(x: typeof(Foo))(implicit M: Monoid[typeof(Foo)]) =
  M.append(Foo, M.append(x, Foo))

Foo我正在处理的代码除了它是 Scala 表达式的字符串表示之外一无所知。它将上述代码输出到一个.scala文件,该文件稍后将作为单独项目的一部分进行编译。

当然,这些typeof(Foo)位不起作用。Foo.type仅当Foo是单例时才使用。

基本上,我想知道是否有可以替代的东西可以typeof(Foo)用于任意 Scala 表达式。

4

2 回答 2

3

在 Scala 中没有typeof这种情况。

我们可以尝试修改添加类型参数的方法

def f[F](foo: F)(x: F)(implicit M: Monoid[F]) =
  M.append(foo, M.append(x, foo))

并称其为,要替换的表达式在f(Foo)(...)哪里,则应在编译时推断。FooF

否则我可以想象以下工作流程。我们可以使用 Scalameta 的SemanticDBFoo从自身的字符串表示中生成表达式类型的字符串表示,然后插入表达式的字符串表示,然后生成该类型的字符串表示。FooFoo

另一种选择是生成带有宏注释的树

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.blackbox

class generate(foo: String) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro generateMacro.impl
}

object generateMacro {
  def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
    import c.universe._
    val str: String = c.prefix.tree match {
      case q"new generate($s)" => c.eval[String](c.Expr(s))
    }
    val tree = c.typecheck(c.parse(str))
    val tpe = tree.tpe.widen
    annottees match {
      case q"$mods def $name[..$_](...$_): $_ = $_" :: _ =>
        q"""
            $mods def $name(x: $tpe)(implicit M: Monoid[$tpe]): $tpe =
              M.append($tree, M.append(x, $tree))
          """
    }
  }
}

@generate("1 + 1")
def f(): Unit = ()
// def f(x: Int)(implicit M: Monoid[Int]): Int = M.append(2, M.append(x, 2))

https://github.com/travisbrown/type-provider-examples/

https://docs.scala-lang.org/overviews/macros/typeproviders.html


实际上,我想这与所要求的很接近

class TypeOf[A](a: A) {
  type T = A
}

val tp = new TypeOf(Foo)

def f(x: tp.T)(implicit M: Monoid[tp.T]) = M.append(Foo, M.append(x, Foo))
于 2019-07-11T21:07:42.387 回答
0

您是否有要使用的类型的参考类?否则定义一个自定义类,并使用:

classOf [Class_Name] 

是等价的 typeOf

如果您想知道自定义对象的类,请使用:

object_name.getClass
于 2019-07-11T15:10:01.780 回答