【问题标题】:Get information of type in Scala3 macro获取Scala3宏中的类型信息
【发布时间】:2021-05-06 16:52:57
【问题描述】:

我正在努力获取 Scala3 宏实现中的类型信息。我会通过代码来解释问题。

这里是应用逻辑:

object BlockServiceImpl extends BlockService:
  def authenticateUser0() = new ServiceCall[AuthUser,AuthUserResponse]:
     def invoke(request: AuthUser): Future[AuthUserResponse] = 
       println("BlockServiceImpl authenticateUser0 called")
       Future.successful(AuthUserResponse("test"))   

现在,对于我想借助宏创建端点的逻辑。

defineRoute("POST","/v1/block",BlockServiceImpl.authenticateUser0)

这是内联方法:

inline def defineRoute[Q: RootJsonFormat ,R: RootJsonFormat](method: String, uri: String,inline call: () =>  ServiceCall[Q,R]): AkkaHttpCall = ${ methodImpl[Q,R]('uri, 'call)}

这是宏的实现:

def methodImpl[Q: Type,R: Type](uri: Expr[String],expr: Expr[Function0[ServiceCall[Q,R]]])(using ctx: Quotes): Expr[AkkaHttpCall] = ...

如何在编译时的宏扩展过程中获取QAuthUser 类型的信息?

【问题讨论】:

  • Q: Type, R: Type 你的methodImpl 没有边界,你能相应地绑定它们吗? (我对新的宏不是很熟悉,但是如果类型没有边界,你怎么能强制执行某个类型呢?)
  • 如何绑定?
  • 我认为使用上限:Q <: AuthUser : Type.
  • 不同的Q类型会有不同的defineRoute调用。
  • @zlaja 如果类型层次结构定义明确,类型边界会非常有用。对于相同或子类,我们可以使用“上限”或“[T <: r>: R]”。我们可以使用“[T >: R <: w href="https://blog.knoldus.com/scala-type-bounds/" rel="nofollow" target="_blank">blog.knoldus.com/scala-type-bounds

标签: scala macros scala-macros


【解决方案1】:

一种可能的解决方案是在引用的表达式上使用模式匹配

例如,您可以定义一个用于检索编译时类型的方法:

def tag[A <: AnyKind] = throw new IllegalStateException("use it only to pattern match types")

然后,在宏扩展中,您可以执行模式匹配:

'{ tag[Q] } match {
      case '{ tag[AuthUser] } => // here I am sure that Q is AuthUser, since Q is matched with AuthUser
}

这是一个非常巧妙的技巧(并且不是很可扩展,因为您必须添加每种类型)所以请对我所说的一切持保留态度...我认为存在一个更清晰的解决方案取决于您的特定应用程序逻辑 :)

【讨论】:

  • 这可行。我不需要找出每种类型的信息,而只需要一种特殊情况。我稍后会尝试。
  • 我以不同的方式解决了它。我在序列化程序中添加了特殊类型的信息。因此,在序列化程序中,我知道它是否未使用,已完成。
  • 好,你为什么不自己回答这个问题,所以将来,其他人有可能解决这个问题吗? :)
  • 我忘了 :)。
【解决方案2】:

在函数中绑定参数的类型可以通过多种方式实现。


当使用像这样的泛型参数时:[T : Type] 我们正在给一个类型起别名

对于许多应用程序,包括您的应用程序,限制我们的泛型参数的类型可能是有益的。


有两个主要界限,一个“上限”和一个“下限”。

“上限”例如[T &lt;: U] 指定 T 必须是 U 类型,或者是 U 的子类

“下限”例如[T &gt;: U] 指定 T 必须是 U 类型,或者是 U 的超类

可以通过先指定下限然后指定上限来限制两个边界,例如[T &gt;: Cat &lt;: Animal]

【讨论】:

    【解决方案3】:

    如果 Q 和 R 是特殊情况(NotUsed、Done、..),我已经解决了这个问题。这个想法来自 Lagom 框架。

    【讨论】:

    • 您自己的答案包含零技术信息,可帮助他人解决类似问题。您基本上已经接受了一个答案,即“我已经使用名为 Lagom 的框架自己修复了它”,如果没有上下文,这对于修复相似但不完全相同的值没有帮助。这是 StackOverflow 问题和答案的目的,能够理解手头问题/问题的原因或机制。
    猜你喜欢
    • 2015-06-08
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    相关资源
    最近更新 更多