Stream: helpdesk (published)

Topic: using SomeModule: SomeModule vs. import SomeModule


view this post on Zulip Patrick Bouffard (Jan 11 2023 at 17:39):

Normally if I don't want all the exported names from a module I use import SomeModule and access certain names with SomeModule.somename, or sometimes to avoid verbosity, using SomeModule: somename.

Just recently I saw a pattern new to me, using SomeModule: SomeModule. Is there any difference between this and simply import SomeModule? And is there any difference between import SomeModule: somename and using SomeModule: somename?

view this post on Zulip Sukera (Jan 11 2023 at 17:47):

Yes, there is - import allows extension of somename with more methods, while using does not

view this post on Zulip Sukera (Jan 11 2023 at 17:48):

using SomeModule: SomeModule is like import SomeModule light - it only brings SomeModule into scope, but without making the names exported from SomeModule available for implicit extension without the SomeModule prefix

view this post on Zulip Mason Protter (Jan 11 2023 at 18:05):

Yeah, IMO using SomeModule: SomeModule should typically be preferred over import.

view this post on Zulip Patrick Bouffard (Jan 11 2023 at 19:17):

Ok that makes some sense; I guess a good way to remember is using = "I just want to use". @Mason Protter I assume what you're saying applies to using/import of names as well, i.e. usually using SomeModule: somename unless somename is to be extended.

view this post on Zulip Mason Protter (Jan 11 2023 at 19:19):

I'd even use it if I'm extending somename personally

view this post on Zulip Mason Protter (Jan 11 2023 at 19:20):

E.g. if I have MyType, I would never write

import Base: show
function show(::IO, ::MyType)
    ...
end

I would always write

function Base.show(::IO, ::MyType)
    ...
end

view this post on Zulip Mason Protter (Jan 11 2023 at 19:21):

This way it's clear at the function definition site that I'm extending a function that didn't originate here.

view this post on Zulip Patrick Bouffard (Jan 11 2023 at 19:23):

:100: ... in the second example you'd still need using Base: Base, no? (well, maybe not Base since I guess that's already in scope)

view this post on Zulip Patrick Bouffard (Jan 11 2023 at 19:24):

.. or does it need to be import SomeModule; SomeModule.methodbeingextended() = ...?

view this post on Zulip Mason Protter (Jan 11 2023 at 19:26):

Yeah, if it was another package, the package name needs to be in scope.

view this post on Zulip Mason Protter (Jan 11 2023 at 19:27):

using SomeModule: SomeModule, somefunction, anotherfunction
SomeModule.methodbeingextended() = ...

is my preferred pattern.

view this post on Zulip Notification Bot (Jan 11 2023 at 20:19):

Patrick Bouffard has marked this topic as resolved.

view this post on Zulip Notification Bot (Jan 11 2023 at 20:19):

Patrick Bouffard has marked this topic as unresolved.

view this post on Zulip Patrick Bouffard (Jan 11 2023 at 20:20):

So in what situations is import SomeModule needed? Is it in effect the same as using SomeModule: SomeModule?

view this post on Zulip Expanding Man (Jan 11 2023 at 20:21):

You can define new methods on functions that have been imported without explicitly declaring the parent module, which is a very dangerous foot-gun.

view this post on Zulip Patrick Bouffard (Jan 11 2023 at 20:23):

Agreed, and also a lot less clear.

view this post on Zulip Sukera (Jan 11 2023 at 20:24):

see also https://github.com/JuliaLang/julia/issues/39235

view this post on Zulip Brian Chen (Jan 11 2023 at 21:36):

Expanding Man said:

You can define new methods on functions that have been imported without explicitly declaring the parent module, which is a very dangerous foot-gun.

I don't believe exports are put in scope when you use import SomeModule sans colon, only using?

view this post on Zulip Expanding Man (Jan 11 2023 at 22:18):

You do have to explicitly import the specific functions, but the problem is the same.

view this post on Zulip Expanding Man (Jan 11 2023 at 22:19):

I guess some might argue that because the functions are imported explicitly it should not be confusing, but I used to do this and have spent a day debugging utterly bewildering bug I caused this way so now I never, ever do it.

view this post on Zulip Brian Chen (Jan 12 2023 at 00:21):

I'm inclined to agree. Maybe a good custom linter rule (once such a linter exists)

view this post on Zulip Expanding Man (Jan 12 2023 at 00:28):

To me the issue is not so much the risk that you might do this accidentally, but that if you do the failure mode will potentially be very weird.


Last updated: Oct 02 2023 at 04:34 UTC