在scala 2或3中,是否可以在运行时调试隐式解析过程? [英] In scala 2 or 3, is it possible to debug implicit resolution process in runtime?

查看:97
本文介绍了在scala 2或3中,是否可以在运行时调试隐式解析过程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在scala语言中,隐式解析通常是在编译时完成的,有时会抛出混淆的错误信息,此类错误的一个著名示例是当无形状的Generic抛出诸如以下的错误信息时:

In scala language, implicit resolution is often done in compile-time and sometimes throws obfuscating error information, one famous example of such error is when shapeless Generic throws error information like:

error: could not find implicit value for parameter encoder: CsvEncoder[Foo]

(请参见 https://books.underscore.io/shapeless-guide/shapeless-guide.html 了解详情)

此问题的解决方案是在运行时中运行隐式分辨率算法(内部应为图查询算法),这至少有两个好处:

A solution to this problem is to run implicit resolution algorithm (should be a graph query algorithm internally) in runtime, this has at least 2 benefits:

    可以使用
  • 调试工具来逐步重现解决过程,因此,即使错误信息&文档不完整,很容易发现错误.

  • debugging tools can be used to reproduce the resolution process step-by-step, so even error information & documentations are incomplete it would be easy to spot the error.

可能无法在编译时确定类型信息(例如,取决于控制流的类型).如果不能将隐式转换延迟到运行时阶段,则定义隐式转换的许多好处将被取消.

in many cases type information can be impossible to be determined in compile-time (e.g. type depending on the control flow). If implicit conversion cannot be delayed to runtime phase, many benefit of defining implicit conversion will be nullified.

所以我的问题是,此功能是否存在于Scala 2.x或Dotty中?还是在路线图上?

So my question is, does this feature exist in Scala 2.x or Dotty? Or is it on the roadmap?

非常感谢您的意见.

推荐答案

您可以在编译时调试隐式:

You can debug implicits at compile time:

  1. 打开-Xlog-implicits

尝试手动解析隐式(也许还指定类型参数)并查看编译错误

try to resolve implicits manually (maybe specifying type parameters as well) and see compile errors

implicitly[...](...manually...)

  • 使用scala.reflect

    println(reify { implicitly[...] }.tree)
    

  • 使用IDE功能显示隐式

  • use IDE functionality to show implicits

    将宏与编译器内部一起使用,您可以调试隐式分辨率

    using macros with compiler internals you can debug implicit resolution

    创建模棱两可的低优先级隐式

    使用"Scala"查找可用的类型类实例

    查找隐式第二个匹配项

    https ://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/package.scala#L119-L168

    如果要开发类型类,请不要忘记使用注释@implicitNotFound@implicitAmbiguous.

    If you're developing a type class don't forget to use annotations @implicitNotFound and @implicitAmbiguous.

    您始终可以将程序的编译推迟到运行时.因此,而不是程序

    You can always postpone compilation of your program till runtime. So instead of program

    object App {
      def main(args: Array[String]): Unit = {
        println("test") // test
      }
    }
    

    你可以拥有

    import scala.reflect.runtime.currentMirror
    import scala.reflect.runtime.universe._
    import scala.tools.reflect.ToolBox
    val toolbox = currentMirror.mkToolBox()
    
    toolbox.eval(q"""
      object App {
        def main(args: Array[String]): Unit = {
          println("test")
        }
      }
    
      App.main(Array())
    """) // test
    

    而不是

    implicitly[Numeric[Int]]
    

    你可以拥有

    toolbox.compile(q"""
      implicitly[Numeric[Int]]
    """)
    

    toolbox.inferImplicitValue(
      toolbox.typecheck(tq"Numeric[Int]", mode = toolbox.TYPEmode).tpe, 
      silent = false
    )
    

    但是,过于乐观地认为将程序编译推迟到运行时,您将能够在运行时而不是在编译时更轻松地调试隐式.实际上,将程序编译推迟到运行时,您还要添加一个间接级别,即使调试变得更困难.

    But it's too optimistic to think that postponing program compilation till runtime you'll be able to debug implicits easier at runtime rather than at compile time. Actually postponing program compilation till runtime you add one level of indirection more i.e. make things harder to debug.

    这篇关于在scala 2或3中,是否可以在运行时调试隐式解析过程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆