我正在尝试为某些特定任务编写迷你DSL。为此我一直试图解决下面这样的问题(不使用parantheses):
give me 5 like romanLetter
give me 5 like word
第一行返回“V”,第二行返回“五”
我对第一部分的定义给我5 看起来像这样
def give = { clos -> clos() }
def me = { clos -> [:].withDefault { it
println it}
}
然后给我5 打印5
问题是如何在右侧添加更多的元类方法。 E.g。
give me 5 like romanLetter -> prints V OR
give me 5 like word -> prints five
我的直觉是我将和定义为
Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"}
else {println "five"} }
这个metaClass方法就像一样,只有当左边有一个返回值才能应用,对吗?我尝试在左侧的所有闭包中添加一个return语句,但我总是收到
groovy.lang.MissingPropertyException: No such property: like
for class: com.ontotext.paces.rules.FERulesScriptTest ...
你知道我该怎么办?
========================================
以下是我要求的应用。 我想制定如下规则
add FEATURE of X opts A,B,C named Y
其中 add 是一个闭包,,opts 和名为是MetaClass方法(至少这是我的想象), X,A,B,C,Y 是最可能是字符串的参数, FEATURE 是MetaClass属性,或者是没有参数的闭包或带参数的闭包。
如果 FEATURE 不接受参数,那么 add 将 FEATURE 作为参数就足够了,并返回一个值
Object.metaClass.of将使用参数X
执行Object.metaClass.opts将在返回的OF值上执行,参数为A,B,C
Object.metaClass.named将在带有参数Y
的opts值返回时执行这些元类方法中的每一个都将其参数设置为map中的值,当调用 named 时,该值将传递给JAVA方法。
我不确定这是解决这个问题的最佳解决方案,但在我看来这一刻。问题是如果FEATURE不是属性本身而是一个带参数的闭包(例如feature1 ARG1)。然后
add feature1 ARG1 of X opts A,B,C named Y
这就是我坚持的情况。 添加feature1 ARG1 是给我5 部分,我正在尝试将其余内容添加到其中。
=============================================== =========
实施例: 我需要完成以下两项工作:
add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"
在第一种情况下,通过解析规则,每当调用每个元类方法,opts,named 时,我在下面的地图中填写相应的值:
params = [feature: "text",
of: 1,2,3,
opts: "upperCase",
named: "TO_UPPER"]
这个地图填写完毕,当解析名为时会发生这种情况,我称之为java方法 setFeature(params.of,params.named,params.opts,params.feature)
在第二种情况下,长度预定义为length =“length”,参数值仅为
params = [feature : length,
of: null,
opts: null,
named: "LENGTH"]
并且因为是null,将调用另一个java方法,即addSurfaceFeature(params.feature,params.named)。第二种情况或多或少地向前发展,但第一种情况是我无法管理的情况。
提前致谢! IV
答案 0 :(得分:0)
你可以做这种事情......这会让你接近吗?
def contextFeature( type ) {
"FEATURE_$type"
}
// Testing
new IvitaParser().parse {
a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
b = add length named "LENGTH"
c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}
assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
// Implementation
class IvitaParser {
Map result
def parse( Closure c ) {
c.delegate = this
c.resolveMethod = Closure.DELEGATE_FIRST
c()
}
def propertyMissing( String name ) {
name
}
def add( String param ) {
result = [ feature:param, of:null, opts:null, named:null ]
this
}
def of( Object... values ) {
result.of = values
this
}
def named( String name ) {
result.named = name
result
}
def opts( String opt ) {
result.opts = opt
this
}
}
您甚至可以删除定义中的引号:
a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH
由于propertyMissing方法只是将未知属性转换为其名称的字符串