# Redefining a function on the fly

**URL:** <https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815>\
**Category:** General Usage\
**Created:** [January 19, 2019, 2:42pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815 "2019-01-19T14:42:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![lucaregini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucaregini/32/6801_2.png) [@lucaregini](https://discourse.julialang.org/u/lucaregini)\
**Post date:** [January 19, 2019, 2:42pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/1 "2019-01-19T14:42:41Z")

</div>

Is it possible to redefine a running function on the fly in Julia?  
For example given the two following functions:

function omy(i)  
sleep(100)  
println(“hello”)  
end

function test()  
for i=1:200  
omy(i)  
end  
end

If I compile both definitoons and then execute the following steps:

- Execute on the repl: test()
- Change the definition of omy while test is still running
- Reevaluate the new definition of omy() while test is still running

Will I be able to see the see the effects of the newly defined omy in the running loop inside test()?

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [January 19, 2019, 3:15pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/2 "2019-01-19T15:15:00Z")

</div>

Interesting question. The closest I could get was:

```julia
fref = Ref{Function}()
fref[] = ()->begin
    println("foo")
    sleep(1)
end

function outer()
    for i in 1:20
        fref[]()
        println(i)
    end
end

# run this, then redefine the function in `fref`
t = @async outer()

# run this if you want to see errors thrown by the task
wait(t)

```

But when you try to redefine the function you get a world-age error because `outer` is older than the function in `fref`. Generally in Julia when a `func1` calls `func2`, then `func2` gets redefined, Julia will recompile `func1` so that it’s up to date. The world age stuff is the mechanism to make sure that those dependencies are updated as needed.

---

<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:** [January 19, 2019, 3:33pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/3 "2019-01-19T15:33:37Z")

</div>

It would be more idiomatic to make the function behavior conditional on something that you can change — can be a parameter, a shared variable (if you are using threads), or something you read from a file. The implementation of how you propose to do

> [@lucaregini](#):
>
> Change the definition of omy while test is still running

is crucial. Also, perhaps you could give more context: what is it you are trying to do?

Finally, please quote your code.

> [@PSA: how to quote code with backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530):
>
> This is a short post on how to use backticks (` and ```) to quote code, so it is easy to read. This post can be linked to new users who are confused by this feature. Why By quoting your code, you get a monospaced font (which preserves indentation) and syntax highlighting. This makes it easier to read your code and help you. Displayed code looks like this: function displayed\_code(x::Int, y::Int) if x \< y println("x is smaller") else println("or not") end end Inline…

---

<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:** [January 19, 2019, 5:37pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/4 "2019-01-19T17:37:24Z")

</div>

> [@ssfrr](#):
>
> But when you try to redefine the function you get a world-age error because `outer` is older than the function in `fref` . Generally in Julia when a `func1` calls `func2` , then `func2` gets redefined, Julia will recompile `func1` so that it’s up to date. The world age stuff is the mechanism to make sure that those dependencies are updated as needed.

One way around it is to use `Base.invokelatest` to call the newest definition.

```Julia
help?> Base.invokelatest
  invokelatest(f, args...; kwargs...)

  Calls f(args...; kwargs...), but guarantees that the most recent method of f
  will be executed. This is useful in specialized circumstances, e.g.
  long-running event loops or callback functions that may call obsolete
  versions of a function f. (The drawback is that invokelatest is somewhat
  slower than calling f directly, and the type of the result cannot be
  inferred by the compiler.)

```

The performance of the function call is a bit slower though.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [January 20, 2019, 1:15am UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/5 "2019-01-20T01:15:24Z")

</div>

Ah yes, good idea. So the full working example looks like:

```julia
function inner()
    println("foo")
    sleep(1)
end

function outer()
    for i in 1:20
        Base.invokelatest(inner)
        println(i)
    end
end

t = @async outer()

# call this to get any errors thrown
wait(t)

```

---

<div class="post-metadata">

**Author:** ![lucaregini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucaregini/32/6801_2.png) [@lucaregini](https://discourse.julialang.org/u/lucaregini)\
**Post date:** [January 20, 2019, 3:48pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/6 "2019-01-20T15:48:46Z")

</div>

Hi Tamas,  
my question didn’t come from nowhere and had the specific purpose of comparing the level of interactivity provided by Julia’s REPL with respect to what is provided by other “lisp languages”.

The “omy” scenario is highly typical of Common Lisp and it’s also supported by some scheme implementations (i.e. Gambit).  
The best answers were by Chakravala and Ssfrr. Given that both of them were able to jump straight to the point and address the matter about late binding I believe that my question had more than enough context at least for them.  
Thanks,  
Regards,  
Luca

---

<div class="post-metadata">

**Author:** ![lucaregini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucaregini/32/6801_2.png) [@lucaregini](https://discourse.julialang.org/u/lucaregini)\
**Post date:** [January 20, 2019, 3:48pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/7 "2019-01-20T15:48:51Z")

</div>

Have just tried it both in Atom and in a bare REPL. It doesn’t seem to work. I am changing “foo” to “hello” and evaluating again inner without any apparent effect.

---

<div class="post-metadata">

**Author:** ![lucaregini](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucaregini/32/6801_2.png) [@lucaregini](https://discourse.julialang.org/u/lucaregini)\
**Post date:** [January 20, 2019, 3:48pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/8 "2019-01-20T15:48:53Z")

</div>

Thanks both, this is exactly what I was looking for.

---

<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:** [January 20, 2019, 4:24pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/9 "2019-01-20T16:24:54Z")

</div>

> [@lucaregini](#):
>
> Given that both of them were able to jump straight to the point and address the matter about late binding I believe that my question had more than enough context at least for them.

From your tone it is my impression that you may think I asked for something unreasonable.

Note however that @chakravala’s answer also points out that you will pay a performance penalty for `invokelatest`, as it does not mesh well with Julia’s performance model.

To give a CL example, this is a bit comparable to using `cl:eval` heavily: while technically you can, it is not idiomatic and you usually run into issues.

This can be easily illustrated by modifying the example above to use the result of `inner`, eg look at

```julia
inner(i) = (sleep(1); i)
outer(n) = sum([Base.invokelatest(inner, i) for i in 1:n])
@code_warntype outer(3)

```

The highlighted `Any`s you see in the output are a sign of [type inference problems](https://docs.julialang.org/en/v1/manual/performance-tips/#man-code-warntype-1).

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [January 20, 2019, 4:25pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/10 "2019-01-20T16:25:24Z")

</div>

@Tamas_Papp gave the most useful answer IMO. While it’s possible to do what you’re asking, it sounds like a thoroughly bad idea (at least in Julia), that is destined for code that’s hard to understand, bugs, and problems down the road.

---

<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:** [January 20, 2019, 5:36pm UTC](https://discourse.julialang.org/t/redefining-a-function-on-the-fly/19815/11 "2019-01-20T17:36:07Z")

</div>

> [@chakravala](#):
>
> (The drawback is that invokelatest is somewhat slower than calling f directly, and the type of the result cannot be inferred by the compiler.)

Another option is to annotate the type assertions, such as `Base.invokelatest(...)::T` when `T` is known
