Thanks for making this video. Here are my comments regarding the questions you had for the viewers: I use `import` almost all the time, unless I use methods from a package a lot in my current project or package (e.g., functions from LinearAlgebra). Like Dave mentioned in the video, It has to do with the cognitive overhead of remembering which function came from which package. I feel more comfortable having more control of what is in my current global namespace by doing `import`; this is just a personal style preference. For teaching, I suggest saying "we now load package XYZ from the active environment", instead of "we now import/using XYZ". This forces the students to remember that they need to add & instantiate XYZ in their active environment, and make sure the correct environment is activated for the task at hand.
Julia's `using` and Python's `import *` are very different. Python's `import *` gives you all^ variables defined in the module. That is almost never a good idea. Julia's `using` only gives the variables from a pre-defined list of exports, so it's a limited subset that the developers decide has a very small chance of conflicting and are reasonably widely used. That said, `using` is good for the REPL and `import` is safer for internals of a package. ^ Details, "if xyz module defines an __all__ variable, it will import all the names defined in this sequence, otherwise it will import all names, except these which start with an underscore." So the problem with Python's `import *` is that its the exact opposite of Julia's using. Julia by default exports nothing and people opt symbols in. `import *` gives everything unless someone defines __all__ to start opting things in (and thus by default, you have to define __all__ to opt things out!).
Thanks for filling in some details, Christopher! I agree that Julia’s `using` is a much better than Python’s `import *` in that Julia takes an “export nothing by default” approach whereas Python takes a “export everything by default” approach. That said, if you had to describe `using` to a Python developer, would you not compare it to `import *`? The internals are different, but the essential premise is the same. Both potentially dump a bunch of names into whatever surrounding namespace you’re importing them into. If you haven’t gone and looked at the export list, you don’t know what all those names are and whether or not there will be a collision. So I say they are pretty similar in net effect! ~ David
@@TalkJulia "Similar in net effect" is not true though. `import *` is the closest thing in Python, but saying that it's similar is really missing some major differences. The default is a big one of course, but that's not even all of it. The other major caveat is multiple dispatch. LinearSolve.jl, NonlinearSolve.jl, DifferentialEquations.jl, GalacticOptim.jl, etc. all export `solve`, yet you will see that none of them cause an issue with a user doing `solve(prob,alg)`. It's similar in the data science community where there's tens to hundreds of packages exporting a `predict` function, but it's all fine. Why? The answer is that Julia uses multiple dispatch. In all of these cases, there is a single function with multiple methods dispatching. So there's solve(prob::LinearProblem,alg::LinearAlgorithm) vs solve(prob::ODEProblem,alg::ODEAlgorithm) and so one function does not cause conflicts. Thinking that it is similar to Python's `import *` action has a connotation that it is much more dangerous than it really is because of this connection to multiple dispatch and the safe defaults to accompany its more broad use. That said, I'm still not advocating for using it in say a package where some developers may not know the exported functionality. But for nice and simple REPL scripts, you should not expect anything like the Python `import *` issues from Julia's `using`, except in a few clear cases (like plot), and the REPL gives a warning whenever that occurs (rather than silently taking the second import like Python).
When I say “similar in net effect” what I’m really thinking about is the cognitive overhead involved with now having to remember what names come from which module. Not comparing all of the language internals. I think Julia has done a fantastic job with the `using` implementation. I’m not trying to denegrate it with a comparison to `import *`. I still see them as similar in spirit, but with two different approaches. I appreciate all the extra context, though!
Hey, thanks for the shoutout! I love the podcast format. Good luck with the channel!
Thanks for making this video. Here are my comments regarding the questions you had for the viewers:
I use `import` almost all the time, unless I use methods from a package a lot in my current project or package (e.g., functions from LinearAlgebra). Like Dave mentioned in the video, It has to do with the cognitive overhead of remembering which function came from which package. I feel more comfortable having more control of what is in my current global namespace by doing `import`; this is just a personal style preference.
For teaching, I suggest saying "we now load package XYZ from the active environment", instead of "we now import/using XYZ". This forces the students to remember that they need to add & instantiate XYZ in their active environment, and make sure the correct environment is activated for the task at hand.
finally i understand difference between using and import!
Julia's `using` and Python's `import *` are very different. Python's `import *` gives you all^ variables defined in the module. That is almost never a good idea. Julia's `using` only gives the variables from a pre-defined list of exports, so it's a limited subset that the developers decide has a very small chance of conflicting and are reasonably widely used. That said, `using` is good for the REPL and `import` is safer for internals of a package.
^ Details, "if xyz module defines an __all__ variable, it will import all the names defined in this sequence, otherwise it will import all names, except these which start with an underscore." So the problem with Python's `import *` is that its the exact opposite of Julia's using. Julia by default exports nothing and people opt symbols in. `import *` gives everything unless someone defines __all__ to start opting things in (and thus by default, you have to define __all__ to opt things out!).
Thanks for filling in some details, Christopher!
I agree that Julia’s `using` is a much better than Python’s `import *` in that Julia takes an “export nothing by default” approach whereas Python takes a “export everything by default” approach.
That said, if you had to describe `using` to a Python developer, would you not compare it to `import *`? The internals are different, but the essential premise is the same. Both potentially dump a bunch of names into whatever surrounding namespace you’re importing them into.
If you haven’t gone and looked at the export list, you don’t know what all those names are and whether or not there will be a collision.
So I say they are pretty similar in net effect!
~ David
@@TalkJulia "Similar in net effect" is not true though. `import *` is the closest thing in Python, but saying that it's similar is really missing some major differences. The default is a big one of course, but that's not even all of it. The other major caveat is multiple dispatch. LinearSolve.jl, NonlinearSolve.jl, DifferentialEquations.jl, GalacticOptim.jl, etc. all export `solve`, yet you will see that none of them cause an issue with a user doing `solve(prob,alg)`. It's similar in the data science community where there's tens to hundreds of packages exporting a `predict` function, but it's all fine. Why? The answer is that Julia uses multiple dispatch. In all of these cases, there is a single function with multiple methods dispatching. So there's solve(prob::LinearProblem,alg::LinearAlgorithm) vs solve(prob::ODEProblem,alg::ODEAlgorithm) and so one function does not cause conflicts. Thinking that it is similar to Python's `import *` action has a connotation that it is much more dangerous than it really is because of this connection to multiple dispatch and the safe defaults to accompany its more broad use.
That said, I'm still not advocating for using it in say a package where some developers may not know the exported functionality. But for nice and simple REPL scripts, you should not expect anything like the Python `import *` issues from Julia's `using`, except in a few clear cases (like plot), and the REPL gives a warning whenever that occurs (rather than silently taking the second import like Python).
When I say “similar in net effect” what I’m really thinking about is the cognitive overhead involved with now having to remember what names come from which module. Not comparing all of the language internals.
I think Julia has done a fantastic job with the `using` implementation. I’m not trying to denegrate it with a comparison to `import *`. I still see them as similar in spirit, but with two different approaches.
I appreciate all the extra context, though!
Are these machine learning lectures online?