So I want to create models that have a similar calculation graph but differ in small aspects.
Each model is represented as a struct with matching dispatches for function calc.
To demonstrate what I have so far, I created the following script:
#file: demonstration.jl
abstract type AbstractT end
""" concreteT1 and concreteT2 have different parameter sets """
struct concreteT1 <: AbstractT
a
b
c
end
struct concreteT2 <: AbstractT
a
b
c
p
end
""" the function body into which expressions have to be inserted via
expression ex_de """
macro calc_body(ex_de)
return esc(quote
a = ob.a
b = ob.b
c = ob.c
d,e = $ex_de
d += 1
e += 2
return a + b / (d*e)
end)
end
""" calc shall be able to be called with both concreteT1 and concreteT2"""
function calc(ob::AbstractT)
@calc_body(inserted_expression(ob))
end
""" expressions which can be inserted into calc_body """
macro de1()
return esc(:((0, 0)))
end
macro de2()
return esc(:((a/b, a*b*p)))
end
""" these functions decide, with type information about ob, which expression
will be inserted into calc_body during a call to calc(AbstractT)"""
@generated function inserted_expression(ob::concreteT1)
return @de1
end
@generated function inserted_expression(ob::concreteT2)
return @de2
end
function main()
""" works as expected """
ob = concreteT1(1, 2, 3)
""" UndefVarError will be thrown when trying to access a
(that should be known inside calc_body)"""
#ob = concreteT2(1, 2, 3, 4)
result = calc(ob)
println(result)
end
main()
So far, only calc(concreteT1) works, but not calc(concreteT2). An UndefVarError is thrown when trying to access variable “a” that, from my point of view, should be known within calc_body, where the returned expression from macro de2 is inserted.
I tried to esc() the returned expression from inserted_expression(concreteT2) but I it wouldn’t help either…
Why am I not just using functions instead of trying to generate functions?
I would like to be able to access every temporary variable known in calc_body and not think about what exactly goes into the code which calculates “d” and “e”.
Why am I not just moving the content from de2 to inserted_expression(concreteT2)?
In reality, calc_body can be modified at multiple points, not just with “ex_de”. If I then add concreteT3 that shares “ex_de” with concreteT1, but has another “ex_xy” (just an example), i want to reuse the expression that the existing macro de1 already returns.
I hope that I could make clear what my question is: Why do I get the UndefVarError? Can i change my code so that “a” will be known in the expression that de2 returns?
I am also open to criticism regarding my architecture itself.