gpt4 book ai didi

scala - 在 Scala 中,我可以仅将某些文字隐式转换为我的自定义类型吗?

转载 作者:行者123 更新时间:2023-12-04 15:54:34 24 4
gpt4 key购买 nike

在我的应用程序中,我会跟踪用户拥有的积分数。为了添加一些类型检查,我使用了 Credits类类似于这个:

case class Credits(val numCredits: Int) extends Ordered[Credits] {
...
}

假设我有一个函数 def accept(creds: Credits): Unit我想打电话。有没有办法让我用
process(Credits(100))
process(0)

但不是这样吗?
process(10)

即,我只想从文字 0 提供隐式转换没有别的。现在,我只有 val Zero = Credits(0)在伴随对象中,我认为这是相当好的做法,但无论如何我对答案感兴趣,包括其他评论,例如:
  • 这可以通过 2.10 中的宏隐式转换来完成吗?
  • 应该Credits而是扩展 AnyVal 而不是 2.10 中的案例类?
  • 最佳答案

    这种编译时检查是使用宏的好地方,宏将在 2.10 中可用

    一个名叫 Jason Zaugg 的非常聪明的人已经实现了与您需要的类似的东西,但它适用于正则表达式:正则表达式编译时间检查。

    您可能想查看它的 Macrocosm 以了解它是如何完成的以及如何以相同的目的编写自己的宏。

    https://github.com/retronym/macrocosm

    如果你真的想更多地了解宏,首先我会说你需要勇敢,因为现在文档很少,而且 API 可能会改变。 Jason Zaugg 可以在 2.10-M3 上正常编译,但我不确定它是否适用于较新的版本。

    如果你想从一些阅读开始:

  • 一个很好的切入点是 scalamacros 网站 http://scalamacros.org/和 SIP 文档 https://docs.google.com/document/d/1O879Iz-567FzVb8kw6N5OBpei9dnbW0ZaT7-XNSa6Cs/edit?pli=1
  • 如果您有时间,您可能还想阅读 Eugene Burmako 的演讲:
    http://scalamacros.org/talks/2012-04-28-MetaprogrammingInScala210.pdf

  • 现在,进入主题,Scala 宏是 :“编译时 AST 转换”。
    抽象语法树是编译器表示源代码的方式。编译器将随后的转换应用于 AST,并在最后一步实际生成 Java 字节码。

    现在让我们看看 Jason Zaugg 的代码:
     def regex(s: String): scala.util.matching.Regex = macro regexImpl

    def regexImpl(c: Context)(s: c.Expr[String]): c.Expr[scala.util.matching.Regex] = {
    import c.universe._

    s.tree match {
    case Literal(Constant(string: String)) =>
    string.r // just to check
    c.reify(s.splice.r)
    }
    }

    正如你所看到的,regex 是一个特殊的函数,它通过调用宏 regexImpl 接受一个字符串并返回一个正则表达式

    宏函数在第一个参数列表中接收上下文,在第二个参数列表中以 c.Expr[A] 的形式接收宏的参数,并返回 c.Expr[B]。请注意,c.Expr 是路径依赖类型,即它是在 Context 内部定义的类,因此如果您有两个上下文,以下内容是非法的
    val c1: context1.Expr[String] = ...
    val c2: context2.Expr[String] = ...
    val c3: context1.Expr[String] = context2.Expr[String] // illegal , compile error

    现在,如果你看看代码中发生了什么:
  • 有一个匹配块匹配 s.tree
  • 如果 s.tree 是一个包含常量 String 的文字,则 string.r 被称为

  • 这里发生的事情是在 Predef.scala 中定义了从 string 到 StringOps 的隐式转换,它会在每个 scala 源的编译中自动导入
    implicit def augmentString(x: String): StringOps = new StringOps(x)
    StringOps 扩展了 scala.collection.immutable.StringLike,其中包含:
    def r: Regex = new Regex(toString)

    由于宏是在编译时执行的,这将在编译时执行,如果抛出异常则编译将失败(即从无效的正则表达式字符串创建正则表达式的行为)

    注意:不幸的是,API 非常不稳定,如果您查看 http://scalamacros.org/documentation/reference.html您将看到指向 Context.scala 的断开链接。右边的链接是 https://github.com/scala/scala/blob/2.10.x/src/reflect/scala/reflect/makro/Context.scala

    关于scala - 在 Scala 中,我可以仅将某些文字隐式转换为我的自定义类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11575890/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com