groovy 命令表达式 如何做嵌套表达式?

发布于 2025-01-07 05:59:38 字数 7374 浏览 3 评论 0原文

我正在使用 Groovy 开发一个不错的小型 DSL。

我真的很喜欢具有高阶函数的命令表达式。

我可以做的代码很少:

timerange = from today to tomorrow

这实际上是

timerange = from(today).to(tomorrow)

但现在我想做这样的事情:

difference = difference from today to tomorrow

这应该会导致这样的结果:

difference = difference(from(today).to(event.start))

我总是收到错误:

没有这样的属性:来自类:Script1。

这是一个带有 main 方法的测试类。第三个断言失败:

任何人都可以向我展示如何执行此操作的示例吗?

import groovy.time.DatumDependentDuration

/**
 * Created by IntelliJ IDEA.
 * User: nils
 * Date: 2/18/12
 * Time: 4:41 PM
 */
class SimpleTest {

    def static today = new Date();
    def static tomorrow = new Date() + 1;

    def loadDSL(Closure cl) {

        cl.delegate = this
        return cl()

    }

    def toMethod = { date ->
        [to: { timeThing ->
            if (timeThing instanceof Date) {
                use(groovy.time.TimeCategory) {
                    (date..timeThing) //return Range
                }
            }
        }]
    }

    def from(Date date) {
        toMethod(date)
    }

    def difference(Range range) {
        range.size() //for the sake of simplicity
    }

    static void eval(dslContent, assertion) {
        SimpleTest runner = new SimpleTest()
        def dsl = """
      run {
        ${dslContent}
      }
    """

        def binding = new Binding()
        binding.run = { Closure cl -> runner.loadDSL(cl) }

        binding.today = today;
        binding.tomorrow = tomorrow;

        GroovyShell shell = new GroovyShell(binding)
        shell.evaluate(dsl)
        assert binding.variables.x == assertion

    }

    static void main(String[] args) {
        eval("x = from today to tomorrow", (today..tomorrow))
        eval("x = difference(from(today).to(tomorrow))", 2)
        eval("x = difference from today to tomorrow ", 2)

    }

}

这是完全的例外:

Exception in thread "main" groovy.lang.MissingPropertyException: No such property: from for class: Script1
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
    at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231)
    at Script1$_run_closure1.doCall(Script1.groovy:3)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at Script1$_run_closure1.doCall(Script1.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at SimpleTest.loadDSL(SimpleTest.groovy:17)
    at SimpleTest$loadDSL.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at SimpleTest$loadDSL.call(Unknown Source)
    at SimpleTest$_eval_closure2.doCall(SimpleTest.groovy:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1099)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1055)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at Script1.run(Script1.groovy:2)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:580)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrap.invoke(PogoMetaMethodSite.java:247)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:64)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at SimpleTest.eval(SimpleTest.groovy:54)
    at SimpleTest$eval.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:50)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:169)
    at SimpleTest.main(SimpleTest.groovy:62)

i am developing a nice little DSL with Groovy.

I really like the Command Expression with higher order functions.

with little code i can do:

timerange = from today to tomorrow

this is actually

timerange = from(today).to(tomorrow)

but now i would like to do something like this:

difference = difference from today to tomorrow

which should result in something like this:

difference = difference(from(today).to(event.start))

I always get the error:

No such property: from for class: Script1.

Here is a test class with a main Method. The third assertion fails:

Anyone can show me an example how to do this?

import groovy.time.DatumDependentDuration

/**
 * Created by IntelliJ IDEA.
 * User: nils
 * Date: 2/18/12
 * Time: 4:41 PM
 */
class SimpleTest {

    def static today = new Date();
    def static tomorrow = new Date() + 1;

    def loadDSL(Closure cl) {

        cl.delegate = this
        return cl()

    }

    def toMethod = { date ->
        [to: { timeThing ->
            if (timeThing instanceof Date) {
                use(groovy.time.TimeCategory) {
                    (date..timeThing) //return Range
                }
            }
        }]
    }

    def from(Date date) {
        toMethod(date)
    }

    def difference(Range range) {
        range.size() //for the sake of simplicity
    }

    static void eval(dslContent, assertion) {
        SimpleTest runner = new SimpleTest()
        def dsl = """
      run {
        ${dslContent}
      }
    """

        def binding = new Binding()
        binding.run = { Closure cl -> runner.loadDSL(cl) }

        binding.today = today;
        binding.tomorrow = tomorrow;

        GroovyShell shell = new GroovyShell(binding)
        shell.evaluate(dsl)
        assert binding.variables.x == assertion

    }

    static void main(String[] args) {
        eval("x = from today to tomorrow", (today..tomorrow))
        eval("x = difference(from(today).to(tomorrow))", 2)
        eval("x = difference from today to tomorrow ", 2)

    }

}

this here is the complete exception:

Exception in thread "main" groovy.lang.MissingPropertyException: No such property: from for class: Script1
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
    at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231)
    at Script1$_run_closure1.doCall(Script1.groovy:3)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at Script1$_run_closure1.doCall(Script1.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at SimpleTest.loadDSL(SimpleTest.groovy:17)
    at SimpleTest$loadDSL.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at SimpleTest$loadDSL.call(Unknown Source)
    at SimpleTest$_eval_closure2.doCall(SimpleTest.groovy:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1099)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1055)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at Script1.run(Script1.groovy:2)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:580)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrap.invoke(PogoMetaMethodSite.java:247)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:64)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at SimpleTest.eval(SimpleTest.groovy:54)
    at SimpleTest$eval.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:50)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:169)
    at SimpleTest.main(SimpleTest.groovy:62)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘年祭陌 2025-01-14 05:59:38

如果您将 getDifference 方法添加到返回范围,则可以在表达式末尾调用difference,但除此之外,groovy 不会解析difference从开始到结束作为difference(from(start).to(end)),而是作为difference(from).start(to).end

    def toMethod = { date ->
        [to: { timeThing ->
            if (timeThing instanceof Date) {
                use(groovy.time.TimeCategory) {
                    def range = date..timeThing
                    range.metaClass.getDifference = { difference delegate } 
                    return range
                }
            }
        }]
    }

你的测试有一个小变化:

    static void main(String[] args) {
        eval("x = from today to tomorrow", (today..tomorrow))
        eval("x = difference(from(today).to(tomorrow))", 2)
        eval("x = from today to tomorrow difference", 2)

    }

两年半以后还来得及吗?

If you add a getDifference method to the returning range, you can call difference at the end of your expression, but other than that, groovy won't parse difference from start to end as difference(from(start).to(end)), but rather as difference(from).start(to).end

    def toMethod = { date ->
        [to: { timeThing ->
            if (timeThing instanceof Date) {
                use(groovy.time.TimeCategory) {
                    def range = date..timeThing
                    range.metaClass.getDifference = { difference delegate } 
                    return range
                }
            }
        }]
    }

And a small change in your tests:

    static void main(String[] args) {
        eval("x = from today to tomorrow", (today..tomorrow))
        eval("x = difference(from(today).to(tomorrow))", 2)
        eval("x = from today to tomorrow difference", 2)

    }

Is two and half years later too late?

弥繁 2025-01-14 05:59:38

使用命名参数:区别于:今天,到:明天

def difference(args){
    Math.abs(args.from - args.to)
}

查看有关 Groovy 邮件列表讨论的更多信息 [groovy-user]:groovy 命令表达式如何进行嵌套表达?

Use named parameters: difference from: today, to: tomorrow

def difference(args){
    Math.abs(args.from - args.to)
}

See more on the Groovy mailing list discussion [groovy-user]: groovy Command Expression howto do nested expression?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文