# Keywords using and import: are they really needed both?

**URL:** <https://discourse.julialang.org/t/keywords-using-and-import-are-they-really-needed-both/111104>\
**Category:** General Usage\
**Created:** [March 3, 2024, 7:51pm UTC](https://discourse.julialang.org/t/keywords-using-and-import-are-they-really-needed-both/111104 "2024-03-03T19:51:57Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [March 3, 2024, 7:51pm UTC](https://discourse.julialang.org/t/keywords-using-and-import-are-they-really-needed-both/111104/1 "2024-03-03T19:51:57Z")

</div>

A longish [discussion](https://github.com/JuliaLang/julia/pull/42080) has been going back and forth what to do about these two keywords.

Consider the following code:

```julia
module Foo
export nice, DOG
struct Dog end # singleton type, not exported
const DOG = Dog() # named instance, exported
nice(x) = "nice $x" # function, exported
notnice(x) = "not nice $x" # function, not exported
end

```

This table shows the equivalents:

| Purpose | Keyword `using` | Keyword `import` |
| --- | --- | --- |
| Get the module name: | `using .Foo: Foo` | `import .Foo` |
| Get all exported names: | `using .Foo` | NA |
| Get only selected names: | `using .Foo: nice` | `import .Foo: nice` |
| Get access to qualified names only: | `using .Foo: Foo` | `import .Foo` |
| Get access to add a method: | `using .Foo: Foo; Foo.nice(i::Int) = i` | `import .Foo; Foo.nice(d::Float64) = d` |
| Get access to add a method without needing a qualified name: | NA | `import .Foo: notnice; notnice(d::Float64) = -d` |

Question: are these differences really worth it to have two keywords?

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 3, 2024, 7:54pm UTC](https://discourse.julialang.org/t/keywords-using-and-import-are-they-really-needed-both/111104/2 "2024-03-03T19:54:38Z")

</div>

> <https://github.com/JuliaLang/julia/issues/39235>
>
> I would very much like to have just one import keyword in Julia 2.0. I don't muc…h care if it's \`import\` or \`using\` but since we talk about it as "importing" things, that may be more natural. With https://github.com/JuliaLang/julia/issues/39187 and some requirement for explicitly requesting extension of external generic functions, this would be possible.
> 
> | current form | new form | comment |
> |---|---|---|
> | \`import Foo\` | \`import Foo\` | just imports \`Foo\` |
> | \`import Foo: Foo, bar\` | \`import Foo: bar\` | in 2.0 \`import Foo: bar\` imports \`Foo\` also |
> | \`import Foo: bar\` | \`import Foo as \_: bar\` | use \`Foo as \_\` to discard that name |
> | \`using Foo\` | \`import Foo...\` | |
> | \`using Foo\` | \`import Foo: ...\` | longer version of the previous one |
> | \`using Foo; using Foo: bar\` | \`import Foo: bar, ...\` | implicit and explicit imports on one line |
> | \`using Foo as \_\` | \`import Foo as \_: ...\` | use \`Foo as \_\` to discard that name |
> 
> In 2.0 I think we should eliminate the distinction between the "soft binding" that \`using\` creates and the hard binding that \`import\` creates and just make all explicit bindings hard and all implicit bindings soft: if you asked for it by name, it's a hard binding, if you didn't, it's a soft binding. When someone wants to extend an implicitly imported generic function, they have to fully qualify it.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 4, 2024, 1:08am UTC](https://discourse.julialang.org/t/keywords-using-and-import-are-they-really-needed-both/111104/3 "2024-03-04T01:08:25Z")

</div>

I’m not sure if I read the issues completely right, but assuming “soft binding” there means you need to qualify the module to extend a function while “hard binding” means you just need the function name, I think I basically arrived at the suggested 2.0 import by doing `using` with no list for implicit exports and `import` with a list of explicit names, and only the latter in source code.

I never liked any justification for “soft bindings” that need module qualification when extending a function but not anytime else. Even in an interactive context where it’s convenient not to write out explicit lists, it’s not so convenient when I forget I needed to qualify the module, and I either run into an error or irreversibly make a new function shadowing the imported name.

> **Erroring case, also works for non-functions.**
>
> ```julia
> julia> module B
> export g
> g(x) = 1
> end; using .B
> 
> julia> f() = g(1)
> f (generic function with 1 method)
> 
> julia> f()
> 1
> 
> julia> g(x) = 10
> ERROR: invalid method definition in Main: function B.g must be explicitly imported to be extended
> 
> ```

> **Irreversible shadowing case, also works for non-functions.**
>
> ```julia
> julia> module B
> export g
> g(x) = 1
> end; using .B
> 
> julia> f() = g(1)
> f (generic function with 1 method)
> 
> julia> g(x) = 10
> g (generic function with 1 method)
> 
> julia> f()
> 10
> 
> julia> B.g === g
> false
> 
> ```

> **Mixing qualified modules and explicit renaming also gets inconsistent.**
>
> ```julia
> julia> module B
> g(x) = 1
> end; using .B: g as gB
> 
> julia> gB(1)
> 1
> 
> julia> gB() = 0
> ERROR: invalid method definition in Main: function Main.gB must be explicitly imported to be extended
> ...
> julia> B.gB() = 0
> ERROR: UndefVarError: `gB` not defined
> ...
> julia> B.g() = 0
> 
> ```

As far as I’m concerned, I should pick one of `B.g`, `g`, or `gB` to write when they would all mean the same thing. I would like the implication that `B.g !== g` when both are written. A currently missing piece to do that fully is not being able to reassign explicitly imported names, as the recent `setglobal!` could only work with a qualified module. I would hope a “hard binding” doesn’t need a qualified module to lower to its `setglobal!` call or an equivalent.

A nice thing about `...` being used to denote implicit thus soft bindings in `import Foo: ...` is that it’s simpler to discourage than `using Foo`, which on the surface looks like `import`’s equal. That’s evidently confusing enough to beginners who already often struggle to distinguish imports and `include`.
