scala DSL中final ==和!=(equals而非equals)方法的解决方法

时间:2010-11-17 10:43:57

标签: scala equals dsl

所以我要包装一些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,我需要返回一个代表所有这些参数的结构。

3 个答案:

答案 0 :(得分:4)

如果您在scala参考(第12.1节)中查看==!=的定义,您会发现它们是根据eq和{{来定义的1}}。

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

请注意,您可能还需要编写equals方法以确保确认 ∀o1,o2 hashCodeo1.equals(o2)

但是,如果您的DSL需要一些其他返回类型而不是(o1.hashCode.equals(o2.hashCode))或一般更灵活,您应该使用Boolean,例如Squeryl中所做的那样。

答案 1 :(得分:3)

这里有一些关于各种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")

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

答案 2 :(得分:0)

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

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

无论你做什么,它都会把它当作像

这样的东西
stringToLiteralString("some string" + <someDslConstruct>)

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