【问题标题】:workaround for final == and != (equals and not equals) methods in scala DSLscala DSL中最终==和!=(等于和不等于)方法的解决方法
【发布时间】:2010-11-17 10:43:57
【问题描述】:

所以我正在包装 Mechanical Turk API 的部分内容,您需要指定资格要求,例如:

Worker_Locale == "US"
Worker_PercentAssignmentsApproved > 95
...

在我的代码中,我想允许上面的语法并将它们翻译成如下内容:

QualificationRequirement("00000000000000000071", "LocaleValue.Country", "EqualTo", "US")
QualificationRequirement("000000000000000000L0", "IntegerValue", "GreaterThan", 95)

我可以通过声明如下对象来实现我想要的大部分内容:

object Worker_PercentAssignmentsApproved {
  def >(x: Int) = {
    QualificationRequirement("000000000000000000L0", "IntegerValue", "GreaterThan", x)
  }
}

但我不能对“==”(等于)或“!=”(不等于)方法做同样的事情,因为它们在 AnyRef 中被声明为 final。有没有标准的解决方法?或许我应该改用“===”和“!==”?

(我想一个很好的答案可能是总结一些不同的 scala DSL 是如何选择解决这个问题的,然后我可以做大多数人所做的任何事情。)

编辑:请注意,我并不是要实际执行相等比较。相反,我试图观察用户在 scala 代码中指示的比较运算符,保存该比较的基于对象的描述,并将该描述提供给服务器。具体来说,如下scala代码:

Worker_Locale == "US"

将导致以下参数添加到我的请求中:

&QualificationRequirement.1.QualificationTypeId=000000000000000000L0
&QualificationRequirement.1.Comparator=EqualTo
&QualificationRequirement.1.LocaleValue.Country=US

所以我不能覆盖equals,因为它返回一个Boolean,我需要返回一个代表所有这些参数的结构。

【问题讨论】:

    标签: scala equals dsl


    【解决方案1】:

    如果您查看 scala 参考中的 ==!= 的定义(第 12.1 节),您会发现它们是根据 eqequals 定义的。

    eq 是引用相等,也是final(在这种情况下它仅用于检查null)但您应该能够覆盖equals

    请注意,您可能还需要编写 hashCode 方法来确保
    ∀ o1、o2 与 o1.equals(o2)(o1.hashCode.equals(o2.hashCode))

    但是,如果您的 DSL 需要其他返回类型而不是 Boolean 或更灵活,您应该使用 ===,例如在 Squeryl 中所做的那样。

    【讨论】:

    • 我编辑了这个问题,以更清楚地说明equals 在这里确实不是一个可行的选择,因为它返回Boolean。不过感谢 Squeryl 的链接!
    【解决方案2】:

    这里有一个关于各种 DSL 用于此类事情的小调查。

    Liftweb 在 Javascript 表达式中使用 ===

    JsIf(ValById("username") === value.toLowerCase, ...)
    

    Squeryl=== 用于 SQL 表达式:

    authors.where(a=> a.lastName === "Pouchkine")
    

    querydsl$eq 用于 SQL 表达式:

    person.firstName $eq "Ben"
    

    Prolog-in-Scala=== 用于 Prolog 表达式:

    'Z === 'A
    

    Scalatest 使用=== 获取Option 而不是Boolean

    assert("hello" === "world")
    

    所以我认为共识主要是使用===

    【讨论】:

      【解决方案3】:

      我一直在考虑类似的问题。我正在考虑创建一个 DSL 来编写特定于域的公式。问题是用户可能也想做字符串操作,而你最终会得到像

      这样的表达式
      "some string" + <someDslConstruct>
      

      无论你做什么,它都会像这样

      stringToLiteralString("some string" + <someDslConstruct>)
      

      我认为摆脱这个坑的唯一可能方法是尝试使用macros。在您的示例中,也许您可​​以有一个包含 scala 表达式并将原始 AST 转换为查询的宏?对任意表达式执行此操作是不可行的,但如果您的域受到足够好的约束,它可能是一个可行的替代解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-01
        • 1970-01-01
        • 2013-06-17
        • 1970-01-01
        • 2012-10-21
        • 2013-09-16
        • 2011-04-20
        相关资源
        最近更新 更多