The following is a trivial MWE of something I find myself doing sometimes in my code: I define some new struct
struct M x::Float64 y::String end
and I want to build accessor functions for getting the fields from an instance of the type. Rather than two lines of code, I use one line, exploiting common features of both functions:
[ eval(parse("get$(fn)(m::M) = m.$(fn)")) for fn in ["x", "y"] ]
Two questions (from someone who doesn’t really understand meta-programming):
1) Is there anything wrong with writing code like this? My understanding is that it is both safe and performant, since I’m not evaling any user generated strings, just my own code (so it is safe), and all the evaling is happening at compile time (so it is performant). Is this understanding correct?
2) The examples from the docs (e.g. the section on code-generation) all tend to use the
@eval macro for code generation, rather than parsing and evaling strings like I have done above. I can’t for the life of me see how I would write the above code using the
@eval macro (but I really am new to this stuff). The main issue is that I’m not extending existing function names, so I feel like I need to use the string interpolation trick in order to get the function names that I want and simultaneously reference the fields that I’m interested in, but no doubt there is a simple and obvious way around this issue. Could anyone re-write my above MWE but using the
@eval macro? That might be all I need to get past this mental obstacle (and hopefully I’ll be able to generalise to more complicated real-world use-cases).
Thanks in advance to all responders,