# 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:** 1

<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 29, 2018, 8:41pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/1 "2018-04-29T20:41:39Z")

</div>

Is there any possibility that Julia will have `local import` in the future? I’m aware some people think this is a silly idea; however, this would actually solve a very real problem some users might face.

Namely, people want to extend operations like `+,-,*,^`, etc on `Symbol` and `Expr` types, and it would be desirable to have these definitions in a sub-module of a package to make extensions optional. The problem is, any new module that is defined with `import` statements extend on a global scope before `using` it.

Therefore, it would have language applicability if the `import` statement could be handled locally, and then optionally extended to the main scope with `using`. I’ve been told it isn’t possible with Julia, but I am optimistic. It would require some kind of a table that keeps track of which method extensions are available in what scope. Saying that it is entirely impossible seems rather improbable to me.

Perhaps, having this could speed up the method-look-up in some cases, since there would be fewer extensions to search through in a given scope.

Before you try to shove this issue under the rug, consider that multiple packages that all define arithmetic operations on symbols and expressions cannot be loaded at once because of this issue. However, if `local import` where possibe, then different packages that depend on different extensions of the same methods can be used together without interference (because then scope determines the method extension selection).

---

<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 29, 2018, 8:54pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/2 "2018-04-29T20:54:08Z")

</div>

Just use assignment, like `+ = Module.:+`.

> [@chakravala](#):
>
> Perhaps, having this could speed up the method-look-up in some cases, since there would be fewer extensions to search through in a given scope.

Method lookup does not care about any names.

---

<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 29, 2018, 9:02pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/3 "2018-04-29T21:02:15Z")

</div>

That replaces the `+` function, doesn’t extend it.

---

<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 29, 2018, 10:17pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/4 "2018-04-29T22:17:26Z")

</div>

Essentially, what I am noticing is a greater extent of `context sensitive ambiguity` in the Julia language. What prevents the Julia language from truly being able to have a 1-1 correspondence with mathematical vernacular is its ability to discern context sensitive ambiguities. Mathematicians are able to do this, but most programming languages, including Julia, cannot.

One example of contex sensitive ambiguity is the fact that Julia cannot discern between the overloaded definitions of `+` by scope.

Another example is that Julia is unable to discern the context sensitive ambiguity of order of operations for the definitions of `+` by scope.

If you wanted to be able to turn Julia into an extremely flexible theorem-prover type of mathematical vernacular / language, you would definitely have to be able to discern those two examples of ambiguity.

The one common trait of all these ambiguities is that they are contex-sensitive, i.e. they should depend on the scope of the evaluation, i.e., determined by what is in the local namespace.

Mathematicians, for example, make many new definitions of the same symbols in different contexts, and in these different contexts you might need different definitions of the same exact thing, further with possibly diferent order algebraic of operations or associativity.

These are some things that the language designers might want to think about, in my hope…

---

<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 29, 2018, 10:47pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/5 "2018-04-29T22:47:37Z")

</div>

> [@chakravala](#):
>
> That replaces the + function, doesn’t extend it.

It’s the same as global `import`. You could still extend the `+` with `eval` (method definition must be at global 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 29, 2018, 11:21pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/6 "2018-04-29T23:21:45Z")

</div>

For example, what if I want the `+` to work on both numbers in the regular way, and I want the `+` to also be defined for `Symbol` types, but only in module `Test2`. If I am outside `Test2` or have not imported it, I do not want the definition of `+` that also takes symbol arguments, but I still want the standard `+`.

```nohighlight
module Test
  module Test2
    Base.:+(::Symbol,::Symbol) = 2
  end
end

:x + :x # 2

```

It doesn’t work, there is currently no way to do it. Without `using Test` or `using Test.Test2`, the definition for `+` has been updated at a global scope. Now in all scopes it gives that result. But what if in another package somebody wants to extend the `Base.:+` function on `Symbol` types differently. Then you cannot have both extended `+` functions simultaneously, even though they are in different scopes. Theoretically, one might want to be able to have both of those simultaneously, but Julia would have to discern the scope.

---

<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, 12:10am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/7 "2018-04-30T00:10:19Z")

</div>

As I said above, you’ve mixed up name lookup and method dispatch. The two are completely unrelated. If you want to have two things (functions) to dispatch differently, they cannot be the same object. Therefore, what you need is a different `+`, which you can get by `+(::Symbol, ::Symbol) = 2; +(args...) = Base.:+(args...)`. You can then use the `+` you’ve defined that’s independent of `Base.:+` in whichever scope you want.

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [April 30, 2018, 1:49am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/8 "2018-04-30T01:49:19Z")

</div>

What about the following:

```julia
module Foo
    +(a,b) = Base.:+(a,b)
    +(a::Symbol, b::Symbol) = 2
    println( 1 + 2 )
    println( :silly + :bar)
end

```

Doesn’t that work as you’d like?  
You have a version of `+` that is specific to module Foo, (you can even use it outside of Foo by writing `Foo.:+`)

---

<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:45am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/9 "2018-04-30T07:45:03Z")

</div>

The problem with that is that you do not retain the 180 methods of multiple dispatch from `+`. Your version only has the `Any` defintion of `+` and the `Symbol` definition. I suppose that could work though.

The point of it is to have an extended version of `+`, but with possibly different extensions in different scopes.

With your solution, the user has to manually call `+ = Foo.:+` for every single extended function to import in the new scope, when `using Foo`. But the user should be able to do something like `using Foo` or `importall Foo` and have the new definition of `+` instead of the Base definition. But that doesn’t happen, making it impractical when a large number of functions needs to be treated this way.

---

<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, 9:09am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/10 "2018-04-30T09:09:40Z")

</div>

> [@chakravala](#):
>
> The problem with that is that you do not retain the 180 methods of multiple dispatch from +.

Yes you do. Did you try what yuyichao wrote?

---

<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, 9:56am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/11 "2018-04-30T09:56:18Z")

</div>

Yea, tried it. Like I said, I suppose it could do, but it is not properly extending the function and it cannot be imported en masse for a large number of functions without having to evaluate many more assignments.

```nohighlight
module Foo
    export +
    +(a,b) = Base.:+(a,b)
    +(a::Symbol, b::Symbol) = 2
end

julia> importall Foo
WARNING: ignoring conflicting import of Foo.+ into Main

```

Instead, the user has to be asked to do `+ = Foo.:+` for every single function. Theoretically, one could create a function that generates the code to do all those assignments for you, but the user would still have to enter something like `eval(Foo.generated_assignments())`, and evaluated in the `Main` scope.

```nohighlight
julia> module Foo
           export +
           +(a,b) = Base.:+(a,b)
           +(a::Symbol, b::Symbol) = 2
           generated_assignments() = :(+ = Foo.:+)
       end
Foo

julia> :x+:y
ERROR: MethodError: no method matching +(::Symbol, ::Symbol)

julia> eval(Foo.generated_assignments())
WARNING: imported binding for + overwritten in module Main
+ (generic function with 2 methods)

julia> :x+:y
2

```

It would be preferable if the language itself could handle this properly.

Specifically, instead of ignoring conflicting imports, it could replace them instead. Then this would change how everything works slightly, but would be more flexible perhaps. Or a new keyword should exist so that the imports can be forced to overwrite the existing function, like `local import Foo`, but with the same effect as having `eval(Foo.generated_assignments())`. That should’nt be too difficult to add to Julia, right?

People said it was impossible, but here we are. Looks like a `local import` can happen, it only needs to be part of the language now.

---

<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, 11:38am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/12 "2018-04-30T11:38:20Z")

</div>

> [@chakravala](#):
>
> it is not properly extending the function

What do you mean by “properly”? I’ve already proved above that you cannot extend `Base.:+`. What you want is fundamantally different.

> [@chakravala](#):
>
> has to be asked to do + = Foo.:+ for every single function

You can do `import Foo: +`. Also, how is that different from import? You defining conflicting names and it’s far more clear to be have to be explicit about it. For anything that’s not base, `using` and `importall` are extremely confusing anyway.

> [@chakravala](#):
>
> `eval(Foo.generated_assignments())`

And if you really don’t want to be explict, just use a macro is much cleaner.

> [@chakravala](#):
>
> like `local import Foo`

There’s really nothing local about it though. It’s just implicit about what you’ve imported.

---

<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, 11:50am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/13 "2018-04-30T11:50:14Z")

</div>

> [@yuyichao](#):
>
> You can do import Foo: +. Also, how is that different from import?

Sure, you can do that. But then the user has to explicitly list possibly 50 different function names if he wants to import all of them.

> [@yuyichao](#):
>
> For anything that’s not base, using and importall are extremely confusing anyway.

Actually, when you want to import a lot of functions, it would make sense to be able to import them all simultaneously to overwrite all of them at once. Whether it confuses you or not does not matter, since some people will actually need to use this, and not having it part of the language and having some kind of hack with `eval(Foo.generated_assignments())` would be even more confusing and less obvious than a simple import statement that imports all of them and replaces everyting “locally” in whatever module it is imported.

> [@yuyichao](#):
>
> There’s really nothing local about it though. It’s just implicit about what you’ve imported.

The point is not about it being local, the point is that Julia doesn’t have a feature that does that. And by the looks of it, it would be a fairly simple feature to create.

---

<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, 11:59am UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/14 "2018-04-30T11:59:06Z")

</div>

> [@chakravala](#):
>
> People said it was impossible, but here we are. Looks like a local import can happen, it only needs to be part of the language now.

Also, just to be clear. I never said it was impossible. In fact, I’ve showed you in the very first reply that local import (import a name to a local instead of global scope) is possible. What I did say was impossible was locally extend, i.e. extending (mutating) an object but has that effect only visible in some scope for the same object. But I then show that it’s just defining new functions and you can do that just fine. The only problem is that you want to do something fundamentally confusing (ambiguious?) so you have to make a choice.

> [@chakravala](#):
>
> But then the user has to explicitly list possibly 50 different function names if he wants to import all of them.

Which is usually a good thing. Especially in this case. It’ll be extremely hard for the user to figure out which functions (and therefore which sets of methods) are actually being used in a scope. Copy pasting the import statement is literally the simplest thing to do and the easiest document for what is being used.

> [@chakravala](#):
>
> some kind of hack with eval(Foo.generated\_assignments())

This is a hack only because you didn’t use a macro. The only thing that’s confusing for the reader is that your `+` is different from everyone else’s without an obvious clue where that comes from. As long as you decide to hide the actual symbol, there’s nothing around it. It doesn’t matter if it’s a builtin feature or a user defined one.

> [@chakravala](#):
>
> the point is that Julia doesn’t have a feature that does that

And the point is that we don’t need that feature (edit: I mean we don’t need to implement this as a builtin feature since it can be done by the user easily and doesn’t offer anything by being builtin as shown below. I did not mean that the features and implementations I’ve shown above are features of the language to be removed.). It doesn’t really help to clearify anything compare to existing implementations. You can even make this more generic and implement a force import macro yourself if you don’t care about readers that haven’t used your library before (If you are using the library all the time it won’t be confusing at all but in my experience, anything like this will become pretty confusing if you stop using this for a few weeks/months). You can just spell it as `@force using Foo` and you can check how it can be implemented by looking at `Reexport`.

---

<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, 12:04pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/15 "2018-04-30T12:04:41Z")

</div>

> [@yuyichao](#):
>
> Also, just to be clear. I never said it was impossible.

On github you explicitly called me out and said it was impossible some months ago. There is a record of it online of you saying it is impossible, but whatever, deny it if you want. I’m not interested in making any personal comments, and I did not say in my post above that it was you, but now we have brought you into it

> [@yuyichao](#):
>
> The only thing that’s confusing for the reader is that your + is different from everyone else’s without an obvious clue where that comes from.

This would be explained in the readme and the documentation. I dont recommend using a package before reading the readme and the documentation. Of course, it will be made clear what exactly is happening.

The precise purpose of this is so that thse functions don’t get automatically imported. By default, they should be skipped. But a user should be able to do `force importall Foo` and get all of them if they really want to fully extend all the functions provided. There are literally around 50 or so functions that this needs to be applied to, so it is very impractical to ask the user to explicitly import 50 function names each time the module is loaded into the REPL, for example.

This would seem like a pretty standard feature to have in a language like Julia.

---

<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, 12:13pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/16 "2018-04-30T12:13:19Z")

</div>

> [@chakravala](#):
>
> On github you explicitly called me out and said it was impossible some months ago.

Judging from that the initial use of word was not accurate in this thread, I won’t be surprised that without clearification I’m talking about something different from what I understand you want to do in this thread. I’ve only found some possibly related discussion in [Rename parse(::String) · Issue #24349 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/24349) though the whole point there was to not make them the same function rather than having them as different function to satisfy some other requirements.

> [@chakravala](#):
>
> But a user should be able to do force importall Foo and get all of them if they really want to fully extend all the functions provided.

What’s the difference between that and `@force using Foo` or `@force importall Foo`?

> [@chakravala](#):
>
> This would seem like a pretty standard feature to have in a language like Julia.

Again, the point is that if forcing name overwrite is the only thing you want, having it in a package is perfectly fine and usually preferred.

---

<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, 12:14pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/17 "2018-04-30T12:14:28Z")

</div>

> [@yuyichao](#):
>
> What’s the difference between that and @force using Foo or @force importall Foo?

How can `Foo` provide the `@force` macro before `using Foo` is executed?

---

<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, 12:15pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/18 "2018-04-30T12:15:20Z")

</div>

`@force` can be provided by a small package (just like `Reexport`) to provide this function for all other packages.

---

<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, 12:17pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/19 "2018-04-30T12:17:43Z")

</div>

> [@yuyichao](#):
>
> @force can be provided by a small package (just like Reexport) to provide this function for all other packages.

That could be one way to do it, but why can’t the Julia language just provide that macro natively?

Then it can be placed into `Compat` for older versions.

---

<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, 12:20pm UTC](https://discourse.julialang.org/t/possibility-of-local-import-statements-in-future/10611/20 "2018-04-30T12:20:09Z")

</div>

> [@chakravala](#):
>
> why can’t the Julia language just provide that macro natively?

Like many other features, if a feature can be provided by a package, it should. If it is later proved that the feature is of significant interest (which I kind of doubt this is of **that** general interest even though I don’t deny that it may be of interest sometimes) it can become a standard package or be moved in base.

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