That is a relevant question. It must do the simple stuff simply.
@maybeUse("Meade")
# which might expand to
requires("Meade") && include( full_path("Meade.jl") )
On Tuesday, July 12, 2016 at 11:40:05 PM UTC-4, Chris Rackauckas wrote:
>
> Hey,
> I wanted to look more into using conditional dependencies, and am
> looking for insight from both developers who have done this successfully
> and feedback from users on what is more intuitive.
>
> Just so we're all on the same page, a conditional dependency is a
> package which your package does not need in most cases. One big example is
> Plots.jl which allows you to use different backends (PyPlot.jl, GR.jl,
> etc.) for your plotting. As you can see here
> <https://github.com/tbreloff/Plots.jl/blob/master/src/backends/gr.jl> there
> is an eval code which will import something like the GR backend during some
> initialization step the first time GR is needed. Another way this is used
> is somewhere like JuMP + friends. In this ecosystem, where (specifically
> for MathProgBase.jl) solvers may be imported by users
> <http://mathprogbasejl.readthedocs.io/en/latest/solvers.html#choosing-solvers>
> and
> then the appropriate functions are passed in. From my understanding, this
> means that the definitions of the abstract types must be in a different
> package, which the semi-dependencies must import and extend? It seems that
> there is another system here
> <https://github.com/JuliaOpt/MathProgBase.jl/blob/master/src/defaultsolvers.jl>
> where
> some things are actually imported to MathProgBase? (I am wondering if
> someone who knows this code could explain a little bit what's going on
> here).
>
> In DifferentialEquations.jl, I am using a third method for doing this
> via directly looking towards the Main module. An example is in the sde
> solvers
> <https://github.com/ChrisRackauckas/DifferentialEquations.jl/blob/master/src/sde/sdeSolvers.jl>
> where
> if a boolean is given and isdefined(Main,:Atom)==true, then Juno/Atom's
> progress bar is used by the solver by calling
>
> (atomLoaded && progressBar) ? Main.Atom.progress(t/T) : nothing #Use
> Atom's progressbar if loaded
>
> every so often in the loop. This method for a conditional import requires,
> like in the MathProgBase.jl implementation with passing the solver, that
> the user explicitly put "using Atom" at the top of the code for it to work.
> Luckily Juno does this automatically so this ends up seemless.
>
> I am wondering what the pros/cons of these different methods for
> implementing conditional dependencies are in order to start "ballooning" my
> feature list, while not tagging on a large number of dependencies. There
> are two different places where I see new conditional dependencies being
> added in my code. One place is with "new solver methods". As you can see
> from something like the ODE solvers
> <https://github.com/ChrisRackauckas/DifferentialEquations.jl/blob/master/src/ode/odeSolvers.jl>,
>
> I allow a user to choose a large number of different ways of solving the
> method. I plan on, in the very near future, making it conditional -> loop
> instead of having the conditional in the loop (that was just because of how
> I first wrote it!), and once that's the case, the next goal is to add other
> ODE solvers from other people's packages, i.e. make a new part of the
> conditional "if alg==:ode23" call ODE.jl's ode23 on the ODE. In this case,
> the dependency may be pretty obvious to the user, maybe it's better to
> require that the user do "using ODE" in their code and make it explicit?
> The Plots.jl method would have it silently import ODE and throw a good
> error message if it doesn't exist. What are the pros/cons here?
>
> However, a very different case for adding new conditional dependencies
> is something like seen in the implementation of the trapezoidal method. The
> loop for the solver for this is simply:
>
> elseif alg=="Trapezoid"
> uOld = copy(u)
> u = vec(u)
> nlres = nlsolve((u,resid)->rhs(u,resid,uOld,t,Δt),u)
> u = reshape(nlres.zero,sizeu...)
>
>
> i.e. it just solves an appropriate implicit equation using NLsolve.jl.
> Because of this (and a few other solvers which use an implicit solver),
> DifferentialEquations.jl currently depends on NLsolve, though in many
> (maybe most) cases the user won't need it. A simple implementation by using
> Main.nlsolve would require the user to have "using NLsolve" at the top of
> their code which may scare a lot of people away (thinking there is a bug
> instead of a missing package), so I think a Plots.jl implementation of
> silently importing the package when needed and throwing an error if it
> doesn't exist would be most suitable?
>
> I am quite interested in what people think about this. I wonder if
> anything is really becoming "standard" for implementing these kinds of
> conditional dependencies and will follow whatever standard makes sense to
> both users and other developers (Stefan mentions this as something that
> may be coming later in Julia, so maybe we should starting thinking about
> the best way to do this now! <https://www.youtube.com/watch?v=5gXMpbY1kJY>).
> [And sorry for the current state of the DifferentialEquations.jl code base,
> it was written to work first, and I know it needs some cleaning/re-naming,
> and slight re-structuring of the main loop to put the conditionals out...]
>