Another implementation of `@memoize` which is type inference friendly & generic functions

FANG_Colin
Sun, 09 Apr 2017 23:37:38 +0000
Package Announcements

I made another Memoize.jl package for daily use of Julia.

Suggestions & criticisms are welcom.

Overview

This package provides basic support for type inference friendly generic function memoization. It allows to customize cache key from function arguments.

Type inference friendly

Cache invalidation

Each method of a generic function has its own cache

Custom cache key

Recursive functions

Limitation

Keyword arguments or default arguments are not supported.

Require standard function definition with return type annotated.

Parametric functions are not supported.

Use Dict for cache, not ObjectIdDict.

Work best with Julia v0.6 since automatic recompilation of dependent functions is fixed.

Exposed Verbs

export @memoize, clear_cache, get_cache

Usage

Pkg.clone("https://github.com/colinfang/Memoize.jl.git")

using Memoize

@memoize function fib(x::Int)::Int
   x <= 2 ? x : fib(x - 1) + fib(x - 2)
end

@memoize function fib(x::Float64, y)::Float64
   x + y
end

julia> fib(3), fib(1.0, 5)
(3, 6.0)

julia> @time fib(100)
0.000073 seconds (199 allocations: 14.166 KiB)
juila> @time fib(100)
0.000005 seconds (5 allocations: 176 bytes)

julia> get_cache(fib)
Dict{Tuple,Dict} with 2 entries:
  (Float64, Any) => Dict{Any,Float64}(Pair{Any,Float64}((1.0, 5), 6.0))
  (Int64,)       => Dict{Any,Int64}(Pair{Any,Int64}(68, 117669030460994),Pair{A…

julia> clear_cache(fib)
julia> get_cache(fib)
Dict{Tuple,Dict} with 2 entries:
  (Float64, Any) => Dict{Any,Float64}()
  (Int64,)       => Dict{Any,Int64}()

julia> @time fib(100)
0.000027 seconds (5 allocations: 176 bytes)

julia> Base.return_types(fib, (Int,))
1-element Array{Any,1}:
 Int64

# Assume `y` doesn't affect the result.
function Memoize.make_key(::typeof(fib), x, y)
   x
end

julia> fib(1.0, 5)
6.0
julia> fib(1.0, 6)
6.0

Macro Expand

@macroexpand Memoize.@memoize function fib(x::Int)::Int
   x <= 2 ? x : fib(x - 1) + fib(x - 2)
end

quote
    let
        local #55#pt = (Int,)
        local cache = (Memoize.get!)((Memoize.Dict){Memoize.Any, Int}, Dict{Tuple,Dict}(), #55#pt)
        global fib
        function fib(x::Int)::Int
            function unmemoized()::Int
                if x <= 2
                    x
                else
                    fib(x - 1) + fib(x - 2)
                end
            end
            key = (Memoize.make_key)(fib, x)
            (Memoize.get!)(unmemoized, cache, key)
        end
    end
end

github.com

GitHub - colinfang/Memoize.jl: Type inference friendly generic function...

Type inference friendly generic function memoization

1 post - 1 participant