2012-05-22 5 views
1

Я пишу небольшую DSL для реактивной оценки, вам нужна помощь с метапрограммированием в Groovy.Вызов метода отслеживания в закрытии Groovy

Пример кода DSL:

Signal<Integer> a = var(1) 
Signal<Integer> b = var(2) 
Signal<Integer> c = signal { a(it) + b(it) } 

Функция 'вар' создает новый экземпляр Signal.

signal функция требует список Signal экземпляров внутри закрытия (ссылки на a и b в примере).

Работа реализация:

interface Signal<T> { 
    T now() 
} 

Signal.metaClass.call = { dependencies -> 
    dependencies?.add(delegate) 
    delegate.now() 
} 

def signal = { Closure<?> body -> 
    def dependencies = new HashSet<>() 
    body.call(dependencies) 
    createSignal(dependencies, body) 
} 

Есть ли способ awoit прохождения it переменной, так что образец выглядит

Signal<Integer> a = var(1) 
Signal<Integer> b = var(2) 
Signal<Integer> c = signal { a() + b() } 

EDIT: Заглушка Signal реализация для тестирования:

class SignalStub<T> implements Signal<T> { 
    T value 
    Collection<Signal<?>> dependencies 

    static def var(value) { new SignalStub<>(value: value, dependencies: [])} 
    static def createSignal(deps, body) { new SignalStub<Object>(value: body.call(), dependencies: deps) } 

    @Override 
    T now() { 
     return value 
    } 
} 

Тестовый пример для DSL:

def a = var(1) 
def b = var(2) 

def c = signal { a() + b() } 

assert c.now() == 3 
assert c.dependencies.contains(a) 
assert c.dependencies.contains(b) 
+0

что 'вар (1)' и 'вар (2)' делать? –

+0

@tim_yates создает новый экземпляр 'Signal' – miah

ответ

1

Возникает вопрос: «Есть ли способ избежать передачи переменной это?» Поскольку a и b являются локальными переменными, а локальные переменные не участвуют в MOP, это невозможно сделать, используя метапрограммирование времени выполнения.

Используя преобразование возможно, но я не знаю, если вы хотите пойти так далеко здесь