简体   繁体   English

Scalafiddle中的Simulacrum:宏扩展期间的例外

[英]Simulacrum in Scalafiddle: exception during macro expansion

I wanted to use Simulacrum in Scalafiddle, like: 我想用拟像在Scalafiddle,如:

import simulacrum._

@typeclass trait Ordering[T] {
    def compare(x: T, y: T): Int
    @op("<") def lt(x: T, y: T): Boolean = compare(x, y) < 0
    @op(">") def gt(x: T, y: T): Boolean = compare(x, y) > 0
}

This gives me the following error: 这给了我以下错误:

ScalaFiddle.scala:3: error: exception during macro expansion: 
scala.reflect.macros.TypecheckException: not found: type op
    at scala.reflect.macros.contexts.Typers.$anonfun$typecheck$3(Typers.scala:32)
    ...

Here is the fiddle: https://scalafiddle.io/sf/vT0X9FR/4 这是小提琴: https//scalafiddle.io/sf/vT0X9FR/4

Do I miss something? 我错过了什么吗?

There's nothing wrong with your code, the problem is with ScalaFiddle. 您的代码没有任何问题,问题在于ScalaFiddle。

If I attempt to run your code in scastie (similar web IDE for Scala), and print out the type trees generated by it, you can see the following: 如果我尝试在scastie (类似Scala的Web IDE)中运行代码,并打印出由它生成的类型树,您可以看到以下内容:

|-- class Playground BYVALmode-EXPRmode (site: package <empty>) 
|    |-- new op("<") EXPRmode (silent: class Playground) 

You can see that scastie is causing the generated code to be wrapped inside a Playground class, which is not defined in your code, but provided for you by the web IDE. 您可以看到scastie导致生成的代码被包装在Playground类中,该类未在您的代码中定义,而是由Web IDE为您提供。

If I compile the same example in IDEA, I see the following: 如果我在IDEA中编译相同的示例,我会看到以下内容:

|-- new op("<") EXPRmode (silent: package github) 
|    |-- new op BYVALmode-EXPRmode-FUNmode-POLYmode (silent: package github) 

As you can see, there is no wrapping of the op type created by simulacrum. 正如您所看到的,没有包含由simulacrum创建的op类型。 Because of this wrapping, simulacrum is not able to find the op type it generated, because it's full namespace at compile time is Playground.op . 由于这种包装,simulacrum无法找到它生成的op类型,因为它在编译时的完整命名空间是Playground.op

To avoid this and as a workaround, wrap your traits inside an object: 要避免这种情况并将其作为解决方法,请将您的特征包装在对象中:

import simulacrum._

object Foo {
  @typeclass trait Ordering[T] {
    def compare(x: T, y: T): Int
    @op("<") def lt(x: T, y: T): Boolean = compare(x, y) < 0
    @op(">") def gt(x: T, y: T): Boolean = compare(x, y) > 0
  }

  @typeclass trait Numeric[T] extends Ordering[T] {
    @op("+") def plus(x: T, y: T): T
    @op("*") def times(x: T, y: T): T
    @op("unary_-") def negate(x: T): T
    def zero: T
    def abs(x: T): T = if (lt(x, zero)) negate(x) else x
  }

  import Foo.Numeric.ops._
  def signOfTheTimes[T: Numeric](t: T): T = -(t.abs) * t
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM