【问题标题】:Scala DSL, Object and infix notationScala DSL,对象和中缀表示法
【发布时间】:2010-05-19 18:40:49
【问题描述】:

在 Scala 中,如果我想实现 DSL,有没有办法做到以下几点:

我有一个名为“Draw”的对象,其中包含函数def draw(d:Drawable)

我怎样才能做到这一点,以便我可以导入对象并在对象外部调用它,例如:

draw ball

如果球扩展了 Drawable 特性?问题是我想以一种中缀表示法使用draw,但我不想通过表示它正在实现类/对象来限定函数draw。

【问题讨论】:

标签: scala dsl scala-2.8 infix-notation


【解决方案1】:

你做不到。除了四个前缀运算符之外,在任何运算符表示法中,第一个标记都表示对象。

【讨论】:

  • 实际上,Felix 可以通过将draw 设为对象并将ball 设为引用真实对象的隐式转换的匿名类的方法来做到这一点。我怀疑他或其他任何人会更喜欢这个,所以 +1 这个答案。
【解决方案2】:

我很快就试了一下,但完全可以使用对象使其工作。在那里我不得不使用 draw(ball) 而不是 draw ball,就像你想要的那样:


Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).

scala> trait Drawable{def doSomething} defined trait Drawable

scala> object Draw {
def draw(d:Drawable) = d.doSomething } defined module Draw

scala> val ball = new Drawable{def doSomething = println("doing ball")} ball: java.lang.Object with Drawable = $anon$1@3a4ba4d6

scala> import Draw._ import Draw._

scala> draw ball :11: error: missing arguments for method draw in object Draw; follow this method with `_' if you want to treat it as a partially applied function draw ball ^

scala> draw(ball) doing ball

但是,通过将 Draw 定义为一个类,它确实起作用了:


scala> trait Drawable{def doSomething: Unit}
defined trait Drawable

scala> class Draw {
def draw(d:Drawable) = d.doSomething } defined class Draw

scala>

scala> val ball = new Drawable{def doSomething = println("doing ball")} ball: java.lang.Object with Drawable = $anon$1@36a06816

scala> val d = new Draw d: Draw = Draw@7194f467

scala> d draw ball doing ball

我不完全确定为什么这对对象的工作方式不同,可能是一个错误或者可能是指定的行为。不过暂时没时间查。

【讨论】:

  • 第一个版本的问题是 Scala 的“运算符符号”需要一个明确的接收者,这就是类示例有效的原因。
  • 我认为 draw(ball) 可能是可接受的语法。我会在 someOpenGlPanel 上的 (x,y,z) 处有类似 draw(ball) 的东西。无论如何,这只是做一个小型 DSL 的测试 :) 感谢您的回答。顺便说一句:也许有人可以接受一些填充符号,例如 Draw -> ball 或其他任何东西......重新思考:)
  • 另一种选择是将绘制方法重命名为“the”。这样,您的示例将变为:“画球”
猜你喜欢
  • 2016-11-29
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 2011-08-01
  • 2018-11-05
  • 2011-09-23
  • 2011-05-27
相关资源
最近更新 更多