# Proposal for a first-class dispatch wrapper

**URL:** <https://discourse.julialang.org/t/proposal-for-a-first-class-dispatch-wrapper/1127>\
**Category:** Internals & Design\
**Tags:** proposal\
**Created:** [December 24, 2016, 2:29am UTC](https://discourse.julialang.org/t/proposal-for-a-first-class-dispatch-wrapper/1127 "2016-12-24T02:29:00Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [January 5, 2017, 8:51pm UTC](https://discourse.julialang.org/t/proposal-for-a-first-class-dispatch-wrapper/1127/2 "2017-01-05T20:51:25Z")

</div>

Following the discussion generated by [https://github.com/JuliaLang/julia/pull/19801](https://github.com/JuliaLang/julia/pull/19801), I think that the world-capturing behavior of that proposal was probably sub-par (complex to implement and use). I think the following is instead a much more useful model. For those following along with that issue, this is also intended to be a very close model for how I think the `cfunction` itself should also behave.

```julia
# a Callback is just a callable (plus a dispatch cache)
immutable Callback{ReturnType <: Type} <: Function
    func::Any
    cache::Ref{SimpleVector}
    function Callback(func::ANY)
        return new(func, Ref(svec()))
    end
end

# allow implicit conversion of Any -> Callback{T}
# and Callback{T} -> Callback{S} where S >: T
eltype{RT}(::Type{Callback{RT}}) = RT
convert{C <: Callback}(::Type{C}, x::ANY) = C(x)
convert{C <: Callback}(::Type{C}, x::Callback) =
    if (eltype(x) <: eltype(C))
        return C(x)
    else
        throw(TypeError(:Callback, "convert", eltype(C), eltype(x)))
    end

function (at::Callback{RT})(args...) where RT
    # this implementation is pseudo-code,
    # it would be actually implemented as an intrinsic
    # since in general I think this can be inlined and
    # optimized very effectively
    push(tls-world-age = world-counter)
    # during the following dispatch,
    # the lookup result may get cached
    # as `svec(Method, argtypes...)`
    # for faster results
    local retval = at.func(args...)::RT
    pop(tls-world-age)
    return retval
end

```

I find this to be much simpler in all of concept, implementation, and usage. This also serves to wrap an arbitrary object in a callable, and has optimization behavior figured out by the callee (rather than needing to be declared by the user).

This makes the above examples much simpler:

```julia
# type SomeType; callback::Callback{Any}; end
register_callback(func::ANY) = (this.callback = func; nothing)
do_callback(this::SomeType, args...) = this.callback(args...)

```

```julia
functions = Any[+, -, *, /]
arrows = [Callback{Float64}(f) for f in functions]
[arrow(1.0, 2) for arrow in arrows] # :: Vector{Float64}

```

```julia
function eval_something_newworld(func, args...)
    # return eval(current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode.(args)...))))
    return Callback{Any}(func)(args...)
end

```

(When called from inside a generated functions, they would still work, they’ll just fallback to acting like a normal dynamic dispatch, since for the generated functions, the newest world _is_ the world-age in which it was defined.)

---

_[View the full topic](https://discourse.julialang.org/t/proposal-for-a-first-class-dispatch-wrapper/1127)._
