scala DSL 中的final == 和!=(等于和不等于)方法的解决方法
因此,我正在包装 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 中被声明为最终的 对此有标准的解决方法吗?也许我应该只使用“= =”和“!==”来代替?
(我想一个好的答案可能是总结一些不同的 scala DSL 如何选择解决这个问题,然后我就可以做大多数人所做的事情。)
编辑:请注意,我我并没有尝试实际执行相等比较。相反,我试图观察用户在 scala 代码中指示的比较运算符,保存该比较的基于对象的描述,并将该描述提供给服务器。具体来说,以下 scala 代码:
Worker_Locale == "US"
将导致以下参数被添加到我的请求中:
&QualificationRequirement.1.QualificationTypeId=000000000000000000L0
&QualificationRequirement.1.Comparator=EqualTo
&QualificationRequirement.1.LocaleValue.Country=US
因此我无法覆盖 equals
因为它返回一个 Boolean
,并且我需要返回一个表示所有这些参数的结构。
So I'm wrapping bits of the Mechanical Turk API, and you need to specify qualification requirements such as:
Worker_Locale == "US"
Worker_PercentAssignmentsApproved > 95
...
In my code, I'd like to allow the syntax above and have these translated into something like:
QualificationRequirement("00000000000000000071", "LocaleValue.Country", "EqualTo", "US")
QualificationRequirement("000000000000000000L0", "IntegerValue", "GreaterThan", 95)
I can achieve most of what I want by declaring an object like:
object Worker_PercentAssignmentsApproved {
def >(x: Int) = {
QualificationRequirement("000000000000000000L0", "IntegerValue", "GreaterThan", x)
}
}
But I can't do the same thing for the "==" (equals) or "!=" (not equals) methods since they're declared final in AnyRef. Is there a standard workaround for this? Perhaps I should just use "===" and "!==" instead?
(I guess one good answer might be a summary of how a few different scala DSLs have chosen to work around this issue and then I can just do whatever the majority of those do.)
Edit: Note that I'm not trying to actually perform an equality comparison. Instead, I'm trying to observe the comparison operator the user indicated in scala code, save an object based description of that comparison, and give that description to the server. Specifically, the following scala code:
Worker_Locale == "US"
will result in the following parameters being added to my request:
&QualificationRequirement.1.QualificationTypeId=000000000000000000L0
&QualificationRequirement.1.Comparator=EqualTo
&QualificationRequirement.1.LocaleValue.Country=US
So I can't override equals
since it returns a Boolean
, and I need to return a structure that represents all these parameters.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您查看 scala 参考(第 12.1 节)中
==
和!=
的定义,您会发现它们是根据定义的eq
和等于
。eq
是引用相等性,也是final
(在这种情况下它仅用于检查null
),但您应该能够覆盖等于
。请注意,您可能还需要编写
hashCode
方法来确保∀ o1, o2 与
o1.equals(o2)
⇒(o1.hashCode.equals(o2.hashCode))
。但是,如果您的 DSL 需要除
Boolean
以外的其他返回类型或一般情况下需要更大的灵活性,则可能应该使用===
,如 Squeryl 。If you look at the definition of
==
and!=
in the scala reference, (§ 12.1), you’ll find that they are defined in terms ofeq
andequals
.eq
is the reference equality and is alsofinal
(it is only used to check fornull
in that case) but you should be able to overrideequals
.Note that you’ll probably also need to write the
hashCode
method to ensure∀ o1, o2 with
o1.equals(o2)
⇒(o1.hashCode.equals(o2.hashCode))
.However, if you need some other return type for your DSL than
Boolean
or more flexibility in general, you should maybe use===
, as has been done in Squeryl for example.下面是对各种 DSL 在此类事情上的用途的一个小调查。
Liftweb 使用
===< Javascript 表达式中的 /code>:
Squeryl 使用
===
对于 SQL 表达式:querydsl 使用
$eq 对于 SQL 表达式:
Prolog-in-Scala使用
===
作为 Prolog 表达式:Scalatest 使用
===
来获取Option
而不是Boolean
:所以我认为共识主要是使用<代码>===。
Here's a little survey of what various DSLs use for this kind of thing.
Liftweb uses
===
in Javascript expressions:Squeryl uses
===
for SQL expressions:querydsl uses
$eq
for SQL expressions:Prolog-in-Scala uses
===
for Prolog expressions:Scalatest uses
===
to get anOption
instead of aBoolean
:So I think the consensus is mostly to use
===
.我一直在考虑类似的问题。我正在考虑创建一个 DSL 来编写特定于领域的公式。问题是用户可能也想进行字符串操作,而你最终会得到这样的表达式:“
无论你做什么,它都会将其词法为类似的东西”,
我认为摆脱这个坑的唯一潜在方法是尝试使用 宏。在您的示例中,也许您可以有一个宏来包装 scala 表达式并将原始 AST 转换为查询?对任意表达式执行此操作是不可行的,但如果您的域受到足够好的约束,那么它可能是一个可行的替代解决方案。
I've been considering a similar problem. I was thinking of creating a DSL for writing domain-specific formulas. The trouble is that users might want to do string manipulation too and you end up with expression like
No matter what you do its going to lex this as a something like
I think the only potential way out of this pit would be to try using macros. In your example perhaps you could have a macro that wraps a scala expression and converts the raw AST into a query? Doing this for arbitrary expressions wouldn't be feasible but if your domain is sufficiently well constrained it might be a workable alternative solution.