Memoize functions defined in `SymPy.jl`

Is there a way to memoize a function that is defined in another module?

Ideally, I would like to to something along the lines of

import OtherModule: func
using Memoization

# I want this to replace `func` with a memoized version of `func` in the current scope
@memoize func

function myfunc(x)
    a = func(x)    # this call should ideally be memoized
    y = # do some stuff with a 
    return y
end

My current work-around is

import OtherModule: func
using Memoization

# I want this to replace `func` with a memoized version of `func` in the current scope
@memoize memoized_func(args...; kwargs...) = func(args...; kwargs...)

function myfunc(x)
    a = memoized_func(x)    # this call should ideally be memoized
    y = # do some stuff with a 
    return y
end

but this doesn’t feel very elegant, because I use func in many places in my code and want it to be memoized everywhere.

Edit:
The OtherModule in question is SymPy.jl and one of the calls I want to memoize is sym.rewrite(sin) where sym is a SymPy symbol. So bonus points for a way to memoize calls to such member functions.

A few things about Memoization first: you can either memoize the functions definition or function calls.

So we can forget at this point about memoization the function definitions from other modules (they are already defined).

The closest solution to what you want is very similar to the workaround you already use:

import OtherModule
using Memoization

# I want this to replace `func` with a memoized version of `func` in the current scope
@memoize func(args...; kwargs...) = OtherModule.func(args...; kwargs...)

function myfunc(x)
    a = func(x)    # this call should ideally be memorized (and it is now)
    y = # do some stuff with a 
    return y
end

In this way, you can use the name of the original function. Basically I defined the desired memoized func function in the current module and linked it’s functionality to the desired target (without importing that in the current module scope).

Please keep in mind that if your func has multiple methods - and you want to memoize more methods, you’ll need to repeat the memoized redefinition for those (e.g., memorization works at the method level, not function level - at least this is the case for Memoization package).

Nice idea of importing OtherModule instead of using it!

Regarding your second comment: Does this mean I have to @memoize all possible methods, and the generic @memoize func(args...; kwargs...) = OtherModule.func(args...; kwargs...) does not automatically memoize all possible methods?

In fact @memoize func(args...; kwargs...) only produces one method - so you are safe if you want to stick with this approach.

@memoize is only looking at the returned value and the arguments of your method.

My comment was more general - if you actually end up defining multiple methods, then you need to memoize each of them at the definition site.

P. S. I rewrote that part in my previous post - to make things clearer for potential readers.

1 Like