# Capture the current definition of a method

**URL:** <https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215>\
**Category:** New to Julia\
**Created:** [August 28, 2021, 11:13am UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215 "2021-08-28T11:13:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 11:13am UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/1 "2021-08-28T11:13:46Z")

</div>

How can I capture the current definition of a method in order to be able to invoke it even if it is later redefined ? That is, how to defeat both the standard method redefinition and Revise ?

I’ve looked at the doc, googled it, and searched here for this… it seems I’m missing the right keywords.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [August 28, 2021, 11:55am UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/2 "2021-08-28T11:55:41Z")

</div>

Like, you want to somehow do this:

```julia
julia> f() = 5

julia> f() = 6

julia> @previous_method f()
5

```

?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 12:01pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/3 "2021-08-28T12:01:02Z")

</div>

```julia
julia> f() = 3
f (generic function with 1 method)

julia> Base.get_world_counter()
0x0000000000007a08

julia> f() = 5
f (generic function with 1 method)

julia> Base.invoke_in_world(0x0000000000007a08, f)
3

```

> [@ylvain](#):
>
> That is, how to defeat both the standard method redefinition and Revise ?

but why?

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 2:49pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/4 "2021-08-28T14:49:39Z")

</div>

Thanks, but it does not ensure the version of the method.

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 2:52pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/5 "2021-08-28T14:52:23Z")

</div>

This is that! 😀  
Why? For “security” reason to ensure I can call the Base method I’m expecting to call. Also to use delegate part of a redefinition to the previous specific definition.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 2:53pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/6 "2021-08-28T14:53:36Z")

</div>

> [@ylvain](#):
>
> to ensure I can call the Base method

if you need to rely on this to get the correct result, you’re in the wrong place…Also be warned this will be SLOW.

> [@ylvain](#):
>
> Also to use delegate part of a redefinition to the previous specific definition

PLEASE DON’T TO THIS. Use different names instead, for example, let `func()` call `_func()` where the latter is your “internal” function

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:00pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/7 "2021-08-28T15:00:36Z")

</div>

1. Slow: I get this (I’m new to julia but a compiler guy). I don’t get why I’m in the wrong place w.r.t. security ? When the runtime start I can capture some methods, I can be certain to have “first hand” if my module init is in a sysimage. Then I’m protected against any redefinition of the method ? Is there as way to bypass this ? (assuming Base.invoke\_in\_world itself is protected likewise and excluding low-level stuff like direct llvm/asm generation ?  
(note: this is not a question of correction but of security, as in protection against adversarial behavior of some code loaded after mine. The scare quotes on “security”… hum… because there so much you can do with such a dynamic semantics)

2. This use case is dual of 1). I don’t get your reply : if I want to override some method of, say, Base.foo but Base.foo is big and does of lot of work and I only need to change a subpath, then I must redefine Base.foo, no ? It is still useful (“safer”) to delegate the larger part of the work to the original Base.foo, and thus inherit any future improvements ?

(I’m from the FP world, but, sometime, only sometime, virtual based inheritance is convenient 😅)

(edit: clarity, typo… and again, sorry)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 3:10pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/8 "2021-08-28T15:10:31Z")

</div>

what are you trying to protect against? The methods you “captured” is useless if user don’t also do `invoke_in_world` when they are not calling your public-facing function. And say they are calling your function, what’s stopping a later package from changing your outer-most functions’ methods?

> [@ylvain](#):
>
> as in protection against adversarial behavior of some code loaded after mine

you understand they could just override your whole module right?

> [@ylvain](#):
>
> Base.foo is big and does of lot of work and I only need to change a subpath

use a internal function to do the un-changing part of your function. Don’t dynamically time-tarvel with invoke, compiler can’t optimize that.

In the end you can do whatever you want, but know that the package produced with this recipe will be hard to integrate into the ecosystem and likely slow (if performance matters)

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:18pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/9 "2021-08-28T15:18:57Z")

</div>

hum… thank for your reply but I still don’t really get it 😅

> Don’t dynamically time-tarvel with invoke, compiler can’t optimize that.

I get it… written a few compilers in a previous life

> use a internal function to do the un-changing part of your function.

it is not unchanging, it is un-changed. They there is an exported, public API method in Base. Let’s call it Base.foo(…). It is 100 lines long. I want to have, say, a custom REPL experience. The REPL do call Base.foo(…). I can override it to customize. But I need only to change a tiny part of Base.foo(…), say a little case depending on some input value. I think it is still better if by override of Base.foo(…) do delegate to the original implementation. (actually I don’t see _any_ other solution but to copy/past the full origin code of Base.foo(…))

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 3:21pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/10 "2021-08-28T15:21:11Z")

</div>

> [@ylvain](#):
>
> I don’t see _any_ other solution

if your new `foo` rely on old `foo`, just call the old `foo` → `_foo`. This is a common pattern, where the `foo` is high level / flexible, `_foo` is directly doing the fixed set of heavy lifting.

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:23pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/11 "2021-08-28T15:23:38Z")

</div>

> you understand they could just override your whole module right?

Yeah… but for scenario 1) I’m in the sysimage. Otherwise I couldn’t do anything meaningful anyway. I don’t care what the code calling my code will do. I just want strongest guarantee that if my code do run, then it does what it was designed to do. E.g. equivalently, all calls from my code could be inlined, full transitive closure downtown Core! (bad idea, but this would be equivalent to what I tried to describe in point 1)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 3:25pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/12 "2021-08-28T15:25:46Z")

</div>

> [@ylvain](#):
>
> equivalently, all calls from my code could be inlined

but this is not gonna happen if you use invoke everywhere?.. I’m probably not understanding your complex use-case

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:26pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/13 "2021-08-28T15:26:13Z")

</div>

> if your new `foo` rely on old `foo` , just call the old `foo` → `_foo` . This is a common pattern, where the `foo` is high level / flexible, `_foo` is directly doing the fixed set of heavy lifting.

I’m afraid I’m missing something important here…  
The old foo is in Base (the actual Base of the Julia distribution).  
How can I do this `foo` → `_foo` ? Really I don’t get it…

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 3:27pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/14 "2021-08-28T15:27:15Z")

</div>

which function do you have in mind in Base and what do you want to do with it that you think you need `invoke`?

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:31pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/15 "2021-08-28T15:31:11Z")

</div>

Again, there are two very different cases

1. Say Base.rm or anything like that that could have catastrophic side effects

2. Say Base.repl\_cmd (to continue the example given above)

```julia
# My Code
function Base.repl_cmd(cmd, out)
   if cmd.exec == ["foo-bar"]
       # special handling
   else
       orginal_base_repl_cmd(cmd, out)
   end
end

```

How can I define `orginal_base_repl_cmd` without `invoke_in_world` ?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 28, 2021, 3:32pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/16 "2021-08-28T15:32:29Z")

</div>

> [@ylvain](#):
>
> How can I define `orginal_base_repl_cmd` without `invoke_in_world` ?

You cannot.

> [@ylvain](#):
>
> Say Base.rm or anything like that that could have catastrophic side effects

That in and of itself is not a problem, no? What do you want to protect yourself against by forcing an older world age?

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:34pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/17 "2021-08-28T15:34:34Z")

</div>

thank you… So I’m not mad 😃  
`invoke_in_world` is indeed what I was looking for… and the _only_ possible way given the fully dynamic nature of the overrides (with back-link and code re-generation).

Question: why is it not in the doc ? I understand that users could abuse it… But the use cas defined in 2) above seems… well useful ?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [August 28, 2021, 3:37pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/18 "2021-08-28T15:37:09Z")

</div>

the reason is that usually you want to use the latest methods, everywhere… if somehow X is designed to be customizable but you can’t customize it without doing this hack, then X is poorly designed.

[https://github.com/JuliaInterop/Cxx.jl/blob/ce1bbf4a79d348252f07f8a5774e90da75ebbf44/src/CxxREPL/replpane.jl#L243-L252](https://github.com/JuliaInterop/Cxx.jl/blob/ce1bbf4a79d348252f07f8a5774e90da75ebbf44/src/CxxREPL/replpane.jl#L243-L252)

I mean at least you definitely don’t need `invoke` for making a new REPL mode…

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 28, 2021, 3:39pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/19 "2021-08-28T15:39:01Z")

</div>

> [@ylvain](#):
>
> why is it not in the doc ?

Because “world age” is an implementation detail to achieve compiled functions in the context of a dynamic programming language with `eval`.

> [@ylvain](#):
>
> But the use cas defined in 2) above seems… well useful ?

You don’t have to use `invoke_in_world` for that.

```julia
@eval Base function foo()
     [.. old definition of foo]
     new_var = 5
     do_with_func(new_var)
     [... old definition of foo]
end

```

Getting the old definition itself can be done by looking up its source code, parsing the code and manipulating the resulting AST (though of course you have no guarantee that the source on disk is the same one that was used to compile the original function in the first place).

That aside, [Cassette.jl](https://juliahub.com/ui/Packages/Cassette/UGnBd/0.3.8) is one tool doing something like this, but it comes with HUGE compiler and performance drawbacks and on top of that it’s a very brittle tool for all the right reasons.

---

<div class="post-metadata">

**Author:** ![ylvain](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ylvain/32/28495_2.png) [@ylvain](https://discourse.julialang.org/u/ylvain)\
**Post date:** [August 28, 2021, 3:51pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/20 "2021-08-28T15:51:08Z")

</div>

I’ve looked at some of the rewriting tools (Cassette, macro + MacroTools or MLStyle, what was done in the context of the source-to-source autodiff, etc…). It’s very nice.

But it’s heavy for a little thing like…

```julia
# My Code
function Base.repl_cmd(cmd, out)
   if cmd.exec == ["foo-bar"]
       # special handling
   else
       orginal_base_repl_cmd(cmd, out)
   end
end

```

after thinking a tiny bit about it… it is not clear what semantics `orginal_base_repl_cmd` could have without a global world age. A chain of method re-definition (a “function age” for given fixed symbol) seems tricky with the specialization… Could maybe be defined for monomorphic functions… anyway… thanks for all the info.

[Next page](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215.md?page=2)
