# 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:** 7\
**Page:** 2

<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:56pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/21 "2021-08-28T15:56:00Z")

</div>

> [@ylvain](#):
>
> But it’s heavy for a little thing like…

Conceptually, what you’re asking about is similar to taking some existing compiled code (which _does not have source information anymore_ (unless you save it next to the compiled code, which is done right now but may not always be done in the future and isn’t something to rely on)), cutting it apart, splicing in your own stuff and then pretend you never did anything like that in the first place (when other code looks at the existing function). That… doesn’t mesh well with julias semantics (well, the “cutting it apart and splicing” part at least - overwriting old functions is just `eval`).

You’re in luck though - your true goal of writing a custom REPL mode _does not require this_.

I believe REPLMaker.jl is the tool you’d really want to look at, instead of code splicing tools:

[https://juliahub.com/ui/Packages/ReplMaker/TRU6e/0.2.5](https://juliahub.com/ui/Packages/ReplMaker/TRU6e/0.2.5)

---

<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, 4:16pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/22 "2021-08-28T16:16:06Z")

</div>

> You’re in luck though - your true goal of writing a custom REPL

Well actually all this came along only because I wanted to override Base.repl\_cmd. I’m on Windows, but Julia explicitly ignores JULIA\_SHELL with a (documented) @static Sys.iswindows… but there are shells now on Windows (ps, bash, etc…). It was only my little weekend fight against discrimination by Unixians 🤣

More seriously, I posted because I thought it was a good learning exercise for me. My understanding of Julia semantics lead me to seek something like `invoke_in_world` because my conclusion was that it is the _only_ possible way to do it. I worried I was missing something very important here given the first replies…

> writing a custom REPL mode _does not require this_ .

yeah… will want to do that at some point in this project. Thank for the link.

> Conceptually, what you’re asking about is similar to taking some existing compiled code…

I respectfully disagree. At code generation time of `# My Code function Base.repl_cmd...` we could have a primitive that build a closure of the currently existing `Base.repl_cmd` (kind of invoke\_latest) but _not_ for invocation. Only to grab a function pointer and all others metadata needed to issue a LLVM call. This could return a Function (with full internal type information) that could be used latter. Of course this Function would need to be `opaque` to method redefinition, handled as-if it had been defined with a different unique name. There are semantics difficulties, IMHO, only when the enclosing context is polymorphe and could be specialized many times. If it is monomorphe, you don"t need more that the super.f(…) of class-based object language (such as C++, Java, C#).

Hum… alternatively you could maybe specialize the captured function setting all polymorphic arguments to Any (making it monomorphic by supertype abstraction) and then rely on the dynamic dispatch at call sites inside it. I think it could work 🙂

TLDR: At the end of day, you just want to do an indirect call to a function pointer! That you _must_ have since you would have execute this call anyway.

---

<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, 4:18pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/23 "2021-08-28T16:18:32Z")

</div>

> [@ylvain](#):
>
> Only to grab a function pointer and all others metadata needed to

actually I think opaque closure should do this

> [@What are Opaque Closures?](https://discourse.julialang.org/t/what-are-opaque-closures/60006/1):
>
> Opaque closures on the other hand relax the requirements, and basically just promise to perform something equivalent in behaviour to their body. Except they always run in the world age they were created

---

<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, 4:23pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/24 "2021-08-28T16:23:45Z")

</div>

Holly fu…

I’ve read about them… and listened to the talk at JuliaCon…  
I had a use for them, but I fully missed the:

> Except they _always run in the world age they were created_

So yes! There will be a mean to detach a call site from the back-link of method redefinitions. This is much more important (semantically) that what I had understood. Thank you for pointing this out.

Something like:

```julia
const prev_repl_cmd = @opaque (cmd,out) -> Base.repl_cmd(cmd, out) # world N
function Base.repl_cmd(cmd, out)   
   if cmd.exec == ["foo-bar"]
       # special handling
   else
       prev_repl_cmd(cmd, out)
   end
end
# world N+1 after redefinition of Base.repl_cmd, without this new Base.repl_cmd itself evalued

```

(edit: pseudo code more likely to be ok… need to think about this more)

---

<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:** [August 28, 2021, 4:32pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/25 "2021-08-28T16:32:32Z")

</div>

If this is where your security perimeter is it’s already way too late.  
Even if this is just one of your security layers.  
This is less security in depth and more running trip-wires inside your living room.

There are reasons you might want to do this.  
But security isn’t one of them.

At the point this could possibly matter that means the attacker has already had a chance to run arbitrary code on your machine.  
And as they say at that point it is no longer your machine.

Nothing anywhere near this is security hardened.

But like go ahead and use invoke in world age, or even opaque closures if you are going to do something useful with them.  
But definitely don’t think of them as tools for the security toolbox.  
They are barely tools for the advanced user toolbox

---

<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, 4:39pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/26 "2021-08-28T16:39:11Z")

</div>

I fully and completely agree with all you’ve said above 😃  
(cue the scare quotes on security I’ve used)  
again… learning exercice for me.

(although I was more thinking like protecting some sensitive data… in a context where I generate the sysimage and General is not allowed - controlled LAN only)

I’m well aware you cannot do any sandboxing in Julia, or anything that downloads and run native artifacts from outside… must… not… think… about this… 👹 make me afraid 🤣

---

<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, 4:53pm UTC](https://discourse.julialang.org/t/capture-the-current-definition-of-a-method/67215/27 "2021-08-28T16:53:15Z")

</div>

> [@ylvain](#):
>
> At code generation time of `# My Code function Base.repl_cmd...` we could have a primitive

Right, but all that requires changes to how julia works internally right now, which I assumed wasn’t subject to change in this discussion. If we’re allowed to make arbitrary changes to how julia works, yeah of course anything goes.

> [@ylvain](#):
>
> There are semantics difficulties, IMHO, only when the enclosing context is polymorphe and could be specialized many times. If it is monomorphe, you don"t need more that the super.f(…) of class-based object language (such as C++, Java, C#).

As I understand it, julias functions are always polymorph. A function is just a name. Type restrictions only come into play when talking about a specific method/implementation of that function on a given number of argument types. That’s what makes this tricky semantically, because as I see it, this directly contradicts your desire for monomorphic behavior.

I hear you saying “well what about a subtype relationship between a function and its methods” but that’s not part of julias semantics. Methods don’t have types, functions do.

> [@ylvain](#):
>
> Hum… alternatively you could maybe specialize the captured function setting all polymorphic arguments to Any (making it monomorphic by supertype abstraction) and then rely on the dynamic dispatch at call sites inside it. I think it could work 🙂

…Aaaaaand I think you’ve just killed inlining (if you want to have this available generically) 😅 Having this sort of dynamicness available at all times kills static dispatch, a core reason why julia has dynamic semantics while still being able to compile & inline called functions instead of having to actually do dynamic dispatch all of the time.

> [@ylvain](#):
>
> TLDR: At the end of day, you just want to do an indirect call to a function pointer! That you _must_ have since you would have execute this call anyway.

Not if the “call” was inlined without compiling the inlined code seperately first, no. It’s not generally useful to think of “function pointers” when thinking about julia functions and methods. Julia is not C.

* * *

Have you checked out the [Phd thesis by jeff bezanson](https://github.com/JeffBezanson/phdthesis)? It talks in great detail about the type system. There’s also [World Age in Julia - Optimizing Method Dispatch in the Presence of Eval](https://arxiv.org/pdf/2010.07516.pdf), an analysis of how the whole world age mechanism works, what its consequences are in regards to `eval`, what kind of semantics follow etc.

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