I kind of like it, evil as it is. Can you get rid of the second eval by capturing the returned function object and applying it to the arguments?
On Thu, Dec 19, 2013 at 8:07 AM, Jacob Quinn <[email protected]> wrote: > I've been playing around with some code that uses abstract types as > parameter "tags" (think Ptr{Void}, Ptr{Int64}, etc.), and more recently > using a hierarchy of abstract tag types. The other hurdle in what I'm > trying to do is the use of external data files that need to be loaded and > used in the construction of specific tag types (i.e. a separate file for > each sub-tag type). I started out with just the regular type constructor > with a check to isdefined to see if the data had already been loaded, load > if not, otherwise use it in constructing the specific type. This felt a > little clunky and had a performance hit with the reflection, so I came up > with a possibly heretical approach. > > > abstract Tag > abstract MoreSpecificTag > > type TagType{T<:Tag} > x > end > > # Fallback/Default constructor > function TagType(x,t) #where t <: Tag > # External data file loaded for specific Tag type t > # Data used in processing the TagType{MoreSpecificTag} constructor > eval(:(function TagType(x,t::Type{$t}) > # TagType{MoreSpecificTag} construction > # Manually inline data points, etc. > return TagType{t}(x) > end > )) > return eval(:(TagType($x,$t))) > end > > # 1st call dispatches to fallback > # Generates TagType{MoreSpecific} constructor, then calls it > TagType(1,MoreSpecificTag) > # 2nd call auto-dispatches to generated constructor > TagType(1,MoreSpecificTag) > > Is this crazy? Potential concerns? In some light testing, it seems to all > work as expected, but I just wanted to pitch it to see if this is too hacky > or not. >
