I’ve really wanted something like this too, but one problem with this approach is that while your @lazy
macro can invokelatest
the decorated function call, its not as easy to do so for downstream objects returned by the function. E.g. this errors:
using LazyModules
@lazy import ComponentArrays
function foo()
x = ComponentArrays.ComponentVector(x=1)
2 * x
end
foo() # error because 2 * ComponentArray is too new
At one point I made a similar macro called @dynamic
(see here, not in a package yet, or maybe ever) which requires you to put the import in the function, and invokelatest
s the entire function “from the beginning”, with some hacks to figure out how to re-call the running function with the right arguments. It looks like:
using MyHypotheticalDynamicImportPackage
function foo()
@dynamic import ComponentArrays
x = ComponentArrays.ComponentVector(x=1)
2 * x
end
Foo.foo() # works now
which basically expands to
function foo()
if !is_already_loaded(ComponentArrays)
@eval import ComponentArrays
return invokelatest(foo)
end
x = ComponentArrays.ComponentVector(x=1)
2 * x
end
This has some issues too though because anything above the @dynamic
will get called twice, there were some subtleties with closures, and the overhead is way worse than yours.
Anyway, yours definitely fills a certain use-case, although I’m still curious if anyone can think of a more robust solution than either of these two approaches.