[ANN] Accouncing LazyModules.jl: delay the heavy dependency loading to its first use

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.

4 Likes