# "unintern" symbol

**URL:** <https://discourse.julialang.org/t/unintern-symbol/12316>\
**Category:** General Usage\
**Tags:** proposal\
**Created:** [July 11, 2018, 1:31pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316 "2018-07-11T13:31:35Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2018, 1:31pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/1 "2018-07-11T13:31:35Z")

</div>

This is a common error for interactive development:

```julia
julia> struct MyType a end

julia> isapprox(a::MyType, b::MyType) = abs(a.a-a.b) ≤ 10 # FORGOT TO IMPORT
isapprox (generic function with 1 method)

julia> import Base.isapprox # SO LET'S MAKE UP FOR IT
WARNING: import of Base.isapprox into Main conflicts with an existing identifier; ignored.

```

In Common Lisp, this is handled by [`cl:unintern`](http://www.lispworks.com/documentation/HyperSpec/Body/f_uninte.htm).

I wonder if it would be possible to do something similar for Julia. Strictly for interactive development. The only remedy I know of is restarting (and of course not doing development in `Main`, but that just happens).

---

<div class="post-metadata">

**Author:** ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)\
**Post date:** [July 11, 2018, 1:49pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/2 "2018-07-11T13:49:34Z")

</div>

There might be a starting point here [Support method deletion by timholy · Pull Request #57 · timholy/Revise.jl · GitHub](https://github.com/timholy/Revise.jl/pull/57)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2018, 2:19pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/3 "2018-07-11T14:19:26Z")

</div>

I may have missed something, but AFAICT that (awesome) package has code for deleting methods from the method table, not binding from a module.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [July 11, 2018, 2:28pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/4 "2018-07-11T14:28:50Z")

</div>

Another approach, complementary, would be [as illustration] to inquire “do you want to import `isapprox`?” As it is, it is much much rarer to parallel operationalize an importable namthan it is to omit the module qualification. Others will have better ways to get here. imo this is an incremental way forward, allowing Julia’s collaborative spirit to just work more so while we do.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2018, 2:32pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/5 "2018-07-11T14:32:23Z")

</div>

> [@JeffreySarnoff](#):
>
> it is much much rarer to parallel operationalize an importable namthan it is to omit the module qualification

I don’t think I agree, I tend to reuse names with different bindings a lot. I would prefer a “fix it later” approach to Julia trying to guess what I am doing.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 11, 2018, 2:45pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/6 "2018-07-11T14:45:48Z")

</div>

You can always do this:

```julia
julia> isapprox(args...) = Base.isapprox(args...) # SO LET'S MAKE UP FOR IT
isapprox (generic function with 2 methods)

```

It is not exactly the same thing as importing first. (Your method will be called even if a more specific one exists in base.) But it’s probably good enough in most cases.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [July 11, 2018, 2:53pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/7 "2018-07-11T14:53:21Z")

</div>

I understand that – and, as you like is best.

I have chosen to avoid doing so much of the time, simply to allow the code to be clearer to me after doing other things. **I used to do it your way _with great glee_.**

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 11, 2018, 5:02pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/8 "2018-07-11T17:02:34Z")

</div>

`unintern` seems like a weird name for this since the symbol is not the issue, it’s the resolved binding that’s the issue. The current situation is pretty annoying and it would be great to figure out a way that trying the wrong thing doesn’t force you to restart your REPL session.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2018, 5:42pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/9 "2018-07-11T17:42:07Z")

</div>

Yes, it is weird in Julia since Julia does not intern symbols. That’s why I put it in quotes.

What I want is basically undo

```julia
f_not_yet_defined(...) = ...
const v_not_yet_defined = ...

```

in an interactive session.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 11, 2018, 6:56pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/10 "2018-07-11T18:56:16Z")

</div>

Julia _does_ intern symbols, but doing so is unrelated to resolving bindings.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 12, 2018, 6:28am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/11 "2018-07-12T06:28:13Z")

</div>

How about an undo buffer at the REPL? Hitting Cmd-Z would strike out the last command(s) and restore the global state. This might require a lot of memory shuffling, but other memory-intensive software like Photoshop still do it.  
(Of course the size of the buffer should be user-definable, and setting it to zero would disable the feature.)

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [July 12, 2018, 7:53am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/12 "2018-07-12T07:53:09Z")

</div>

I wonder if this can be achieved via forking in linux.

Separate the “actual” julia process that runs work from the REPL.

Like before each REPL command is run it forks the “actual” julia process and let that process sleep.

Then when you undo, it sleeps the current julia process (so you can redo),  
and wakes up the fork.

The important part of the trick is that linux fork’s share references to the same memory,  
until one of them writes to it, then it creates a copy (i.e. Copy On Write)

This would avoid dublicating large unchanged memory.  
But it would make every operation that did change memory slooooow.  
Since changing 1 element of an array would copy that whole array.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 12, 2018, 8:17am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/13 "2018-07-12T08:17:39Z")

</div>

> [@oxinabox](#):
>
> But it would make every operation that did change memory slooooow.  
> Since changing 1 element of an array would copy that whole array.

Not that slow. I think only one page (maybe 4 kb) would be copied if one element of a large array is changed. And the delay only happens when the user hits “Enter”. I think the key-press itself will take more time than the memory copy most of the time.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 12, 2018, 8:43am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/14 "2018-07-12T08:43:13Z")

</div>

Another place to do this would be in Jypyter notebooks. If the Julia/Python/whatever process is forked before executing each code cell, then one could at any time modify a cell and re-evaluate the rest of the document without having to re-run any previous cells. (And then one could undo the entire change with Cmd-Z.)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 12, 2018, 9:17am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/15 "2018-07-12T09:17:26Z")

</div>

I don’t think one needs to resort to (potentially very expensive) hacks, as I hope that a solution will be provided by Julia in the medium run.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 12, 2018, 9:38am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/16 "2018-07-12T09:38:54Z")

</div>

A general undo feature would also be helpful if you accidentally modify the wrong array at the REPL, or even if you get a core dump. These are things that could never be handled by the language itself.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 12, 2018, 10:01am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/17 "2018-07-12T10:01:41Z")

</div>

Helpful, yes, but also very difficult to implement and I imagine mostly orthogonal to the original question.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [July 12, 2018, 10:05am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/18 "2018-07-12T10:05:25Z")

</div>

> I don’t think one needs to resort to (potentially very expensive) hacks, as I hope that a solution will be provided by Julia in the medium run.

You mean “surprisingly cheap” hacks. 😛

I don’t know that julia can do anything meaningfully better than this; at least performance-wise.  
I think an undo requires storing the global state, in a turing complete language.  
Or at least storing the parts of the state that can possibly change.  
(Working out which parts can definitely (rather than possibly) change I think runs into the halting problem)  
There is no better mechanism for that than copy-on-write.

Of course, if it is just unbinding, rather than an univeral undo, that statement does not apply,  
at least not as much.  
Feels a lot like #265

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 12, 2018, 11:47am UTC](https://discourse.julialang.org/t/unintern-symbol/12316/19 "2018-07-12T11:47:19Z")

</div>

Or being able to undo arbitrary changes to the state of the entire world…

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 12, 2018, 2:07pm UTC](https://discourse.julialang.org/t/unintern-symbol/12316/20 "2018-07-12T14:07:21Z")

</div>

> [@oxinabox](#):
>
> Of course, if it is just unbinding, rather than an univeral undo, that statement does not apply,

Just to clarify: my question is about removing or at least overwriting bindings in the namespace of a module, not about undoing arbitrary changes to the state of the world.

This is purely a workflow/convenience question, and yes, very much like the famous [#265](https://github.com/JuliaLang/julia/issues/265). Fixing that issue, combined with the amazing [Revise.jl](https://github.com/timholy/Revise.jl), cut my restarts by at least 80%.

Is there an open issue for this?
