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 invokelatests 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.