# Possibility of \`local import\` statements in future?

**URL:** <https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611>\
**Category:** Internals & Design\
**Tags:** scope\
**Created:** [April 29, 2018, 8:41pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611 "2018-04-29T20:41:39Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 2:19pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/21 "2018-04-30T14:19:42Z")

</div>

Alright, the `@force using ModuleName` macro exists now in a new package `ForceImport`

> **[GitHub - chakravala/ForceImport.jl: Macro that force imports conflicting...](https://github.com/chakravala/ForceImport.jl)**
>
> Macro that force imports conflicting methods in modules - GitHub - chakravala/ForceImport.jl: Macro that force imports conflicting methods in modules

It works for modules that are in packages, otherwise it can’t find the source code.

The good thing is it gives warnings when it overwrites methods, so you have record of what happened.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 2:29pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/22 "2018-04-30T14:29:54Z")

</div>

As I said above, you should check Reexport to see how you can implement this. In particuclar, reading the source code is just wrong… You can just import the package and loop over the exported names.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 2:34pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/23 "2018-04-30T14:34:55Z")

</div>

And before you ask, I mean to `import` the module first, not `using`.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 2:35pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/24 "2018-04-30T14:35:51Z")

</div>

> [@yuyichao](#):
>
> You can just import the package and loop over the exported names.

It wasn’t clear to me how you can get a list of exported names from a defined module. is it `names`? that’s a very handy function, I was looking for one like that for a while. It only contains exported items?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 2:37pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/25 "2018-04-30T14:37:29Z")

</div>

> [@chakravala](#):
>
> It wasn’t clear to me how you can get a list of exported names from a defined module. Could you elaborate.

i.e.

> [@yuyichao](#):
>
> check Reexport to see how you can implement this

> <https://github.com/simonster/Reexport.jl/blob/master/src/Reexport.jl#L23>

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 3:02pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/26 "2018-04-30T15:02:36Z")

</div>

Then this macro turns out very simple

```nohighlight
macro force(import_module)
    import_module.head ≠ :using && throw(error("not a using statement"))
    pkg = import_module.args[1]
    s = :(Expr(:toplevel,[Expr(:import,Symbol($(string(pkg))),j) for j ∈ names($pkg)]...))
    return :(import $pkg; eval($s))
end

```

Still opposed to it being a standard feature? And yea, I updated it to handle multiple pkgs in the repo.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 3:16pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/27 "2018-04-30T15:16:32Z")

</div>

> [@chakravala](#):
>
> very simple

That’s exactly why I expect you to be able to do it from what’s in `Reexport`.

> [@chakravala](#):
>
> Still opposed to it being a standard feature?

Yes. Being simple has nothing to do with whether it should be in Base. You can easily write a function called `plus_three(x) = x + 3` and that’s not at all a good reason for it to go into Base. In fact, the exact opposite is true. If it wasn’t so easy to implement, that will be an argument to improve the support in Base.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 3:18pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/28 "2018-04-30T15:18:48Z")

</div>

> [@yuyichao](#):
>
> In fact, if it wasn’t so easy to implement, that will be an argument to improve the support in Base.

That doesn’t seem like a good criterion. The NPM disaster happened exactly because people made a lot of one-liner packages. My preference is for not putting things like this into a package, but if it’s not in Base then it has to be its own package.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 30, 2018, 3:33pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/29 "2018-04-30T15:33:56Z")

</div>

> [@chakravala](#):
>
> Anyway, it’s not like you are the single person responsible for that decision.

No, but various proposals for forced/automatic resolution of import conflicts have been discussed extensively and repeatedly (see e.g. [Function name conflict: ADL / function merging? - #38 by kristoffer.carlsson](https://discourse.julialang.org/t/function-name-conflict-adl-function-merging/10335/38) for a recent example) and most of the core developers seem to be generally opposed to anything in Base that promotes silent overwriting of symbols without explicitly enumerating them. You can certainly submit a PR to `julia`, of course, but I personally doubt it will get much traction.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 7:11pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/30 "2018-04-30T19:11:14Z")

</div>

> [@stevengj](#):
>
> You can certainly submit a PR to julia, of course, but I personally doubt it will get much traction.

Did some more testing, and found that the macro only works if it is defined in `Main`. If you do

```Julia
julia> using ForceImport

julia> module Foo
           export +
           +() = "hey"
       end
Foo

julia> @force using Foo
ERROR: UndefVarError: Foo not defined

```

I think this might have to be included with `Base` afterall, because as a package it doesnt work, unless I am misunderstanding something about how macro evaluation works.

The macro does work if I manually enter it into the REPL or put it into `.juliarc.jl`.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 30, 2018, 7:16pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/31 "2018-04-30T19:16:47Z")

</div>

It is a good idea to use `@macroexpand` to see what the macro expands to when debugging a macro.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 7:18pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/32 "2018-04-30T19:18:02Z")

</div>

1. As a syntax, you need `using .Foo`.
2. And then you need to fix your handling of `using` parameter to make sure you support non-trivial import statements.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 7:30pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/33 "2018-04-30T19:30:24Z")

</div>

This is what it expands to

```nohighlight
quote 
    import Foo
    (ForceImport.eval)((ForceImport.Expr)(:toplevel, [(ForceImport.Expr)(:import, (ForceImport.Symbol)("Foo"), j) for j = (ForceImport.names)(ForceImport.Foo)]...))
end

```

The problem is that it prefixes everything with `ForceImport`, like `ForceImport.names(ForceImport.Foo)`

Is there a way to determine which module the call came from?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 7:37pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/34 "2018-04-30T19:37:11Z")

</div>

See the macro hygiene section in the manual, in particular the `esc` I’ve already mentioned above. And as I said, you also need `.Foo` instead, especially on 0.7.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 7:41pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/35 "2018-04-30T19:41:14Z")

</div>

Yep, it’s the hygiene. It was never quite clear to me what the point of `esc` was, so this is what it primarily does? It clears out these kind of prefixes to the namespace?

I’m not entirely sure I understand what you mean by `using .Foo`. Do you mean `import .Foo`? Since the actual command that is used is import and not using. Using is only for the input to the macro.

It would be good if the `@force` command also works within other modules, not just in `Main`, so would `.` affect its ability to work inside modules, is that just for`Foo`’s that are defined in Main?

How can the name of the module which made the call to the macro be determined?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 7:58pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/36 "2018-04-30T19:58:17Z")

</div>

The `.` (or in general support for other using syntax) is needed to import anything that’s not a package. I think the document should contain description of all of them. (On phone, had to search/paste doc).

I do mean `using .Foo`, which should be then translated to `import .Foo` by the macro.

Hygiene is just making sure the code is evaluated in the right scope, i.e. exactly the problem you were facing) `esc` is one of the tools provided for this and it makes sure code is evaluated in caller’s (user) scope rather than callee’s (macro  
) scope.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 8:02pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/37 "2018-04-30T20:02:13Z")

</div>

What if I need to use `eval` inside of an expression returned from a macro, then how do I specify the module?

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [April 30, 2018, 8:32pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/38 "2018-04-30T20:32:03Z")

</div>

Got it all sorted out. Using `$(esc(:eval))` did the trick.

```nohighlight
macro force(mod)
    mod.head ∉ [:using,:toplevel] && throw(error("$mod not a using statement"))
    pkgs = mod.head ≠ :using ? mod.args : [mod]
    out = []
    for p ∈ pkgs
        m = p.args[end]
        s = :([Expr(:import,Symbol($(string(m))),j) for j ∈ names($(esc(m)))])
        push!(out,Expr(:import,p.args...),:($(esc(:eval))(Expr(:toplevel,$s...))))
    end
    return Expr(:block,out...)
end

```

Now the `@force` macro works in modules, in REPL, in Main, and works as a standalone package.

It also supports the `.` syntax and other namespaces, I believe.

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [April 30, 2018, 8:39pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/39 "2018-04-30T20:39:27Z")

</div>

What do you think about the following architecture:  
Functions will be named meta containers bound to a module, it will contain all methods (functions with the same name  
but different signature in the arguments) defined inside the module and a list of all modules that exported the same function name and were imported into the current module using the keyword `using` … usually in this case Julia complains about  
both modules exporting the same name and that use needs to be qualified.

Instead whenever the function is parsed/compiled it should infer the most concrete match for the argument type  
from the local method table and use that if there is one, if not it should look in all the modules listed as exporting  
that function name and try and find a match in their local method table.

If there is more than one match only then you get an error “Modules $A and $B both export function $name , which satisfies given $args … use case must be qualified”

There can be a keyword or macro to give precedence for a Module: when searching for a method if there are two matches one from a module without precedence and one with, then there is no conflict and no error and the module which was imported with precedence get dispatched.

Thats it, I think it solves all unnaturalness of importing functions from Base and extending them.

it also prevents the following abominations:

```julia
module SelfDestruct
    import Base.+
    (+)(s::Int64,t::Int64) = "muhahahaha"
end

```

and:

```julia
module A
    import Base.+
    (+)(s::String,t::String) = s*t
end

module B
    const C = "hello " + "world"
end

```

importing module B can be done only if module A was imported first.

In other words this change in architecture increases the encapsulation of modules while preserving multiple dispatch in a natural way without needing the concept of importing a function and extending a function.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [April 30, 2018, 8:41pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/40 "2018-04-30T20:41:09Z")

</div>

`eval($mod, exp)` is slightly better, mod is `current_module()` on 0.6 and ` __module__ ` on 0.7

[Previous page](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611.md?page=1)

[Next page](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611.md?page=3)
