I'm writing a small DSL for reactive evaluation, need help with metaprogramming in Groovy.
Sample DSL code:
Signal<Integer> a = var(1)
Signal<Integer> b = var(2)
Signal<Integer> c = signal { a(it) + b(it) }
The 'var' function creates new Signal
instance.
The signal
function needs a list of Signal
instances inside the closure (references to a
and b
in example).
Working implementation:
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)
}
Is there any way to awoit passing it
variable, so sample looks like
Signal<Integer> a = var(1)
Signal<Integer> b = var(2)
Signal<Integer> c = signal { a() + b() }
EDIT: Stub Signal
implementation for testing:
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
}
}
Test case for 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)
The question is: "Is there a way to avoid passing the it variable?" Since a and b are local variables and local variables are not taking part in the MOP, it should be impossible to do using runtime meta programming.
Using a transform it is possible, but I don't know if you want to go that far here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.