What is the difference between `using` and `import` in Julia when building a module?

The Julia Modules documentation states:

The import keyword [...] only operates on a single name at a time. It does not add modules to be searched the way using does. import also differs from using in that functions must be imported using import to be extended with new methods. [...] Functions whose names are only visible via using cannot be extended.

(Emphasis mine.)

For example, you can use import to add methods to Base.show to pretty-print your own types, but not with using.

There is also importall that imports all exported names of a module.

(This answer refers to Julia 0.6; the documentation was reworded for 1.0.)


The documentation (updated link for Julia 1.4) about this is excellent. Here's the excerpt which I find to be the most succinct summary:

(a demo module to make the examples below specific)

module MyModule

export x, y

x() = "x"
y() = "y"
p() = "p"

end

(this is a table in the documentation, but StackOverflow still won't add support for tables so... reformatted)

Command

  • using MyModule
    • in-scope: All exported names (x and y), MyModule.x, MyModule.y, and MyModule.p
    • extensible: MyModule.x, MyModule.y, and MyModule.p
  • using MyModule: x, p
    • in-scope: x and p
    • extensible: (nothing)
  • import MyModule
    • in-scope: MyModule.x, MyModule.y, and MyModule.p
    • extensible: MyModule.x, MyModule.y, and MyModule.p
  • import MyModule.x, MyModule.p
    • in-scope: x and p
    • extensible: x and p
  • import MyModule: x, p
    • in-scope: x and p
    • extensible: x and p

A summary of the main difference, in a way that I find easy to remember:

  1. using NiceStuff allows usage access to exported names without the module qualifier, which import NiceStuff doesn't; and
  2. import NiceStuff: nice allows extension access (adding methods) to the specified function without the module qualifier, which using NiceStuff: nice doesn't.

And a minor difference:
X as Y syntax is allowed for individual identifiers with both using and import (using Random: randstring as rstr, import Random: randstring as rstr) but for the module name itself, import Random as Rnd is allowed while using Random as Rnd is an error.

Some other points I found useful from the Modules docs page

using ModuleName is the only form for which export lists matter at all.

import NiceStuff is equivalent to using NiceStuff: NiceStuff.