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

Reply via email to