groovy Command Expression как сделать вложенное выражение? - PullRequest
0 голосов
/ 18 февраля 2012

Я разрабатываю симпатичный маленький DSL с Groovy.

Мне действительно нравится выражение команды с функциями более высокого порядка.

с небольшим кодом, который я могу сделать:

timerange = from today to tomorrow

это на самом деле

timerange = from(today).to(tomorrow)

но теперь я хотел бы сделать что-то вроде этого:

difference = difference from today to tomorrow

, что должно привести к чему-то вроде этого:

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

Я всегда получаю ошибку:

Нет такого свойства: from для класса: Script1.

Вот тестовый класс с основным методом.Третье утверждение не выполнено:

Кто-нибудь может показать мне пример, как это сделать?

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)

Ответы [ 2 ]

1 голос
/ 08 октября 2014

Если вы добавите метод getDifference к возвращаемому диапазону, вы можете вызвать difference в конце выражения, но кроме этого groovy не будет анализировать difference from start to end как 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)

    }

Неужели два с половиной года спустя слишком поздно?

0 голосов
/ 19 февраля 2012

Используйте именованные параметры: difference from: today, to: tomorrow

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

Подробнее об обсуждении в списке рассылки Groovy [groovy-user]: выражение команды groovy, как сделать вложенное выражение?

...