Hacker News new | ask | show | jobs
by hnarayanan 1244 days ago
I get confused by this every time this comes up. Is multiple dispatch the same as function-overloading (e.g. in C++)?
2 comments

They're different. IIRC, multiple dispatch is dynamic (i.e., happens at runtime) while C++'s function overloading is static (happens at compile time).
One interesting thing is that if julia can prove what types a function will be called with at compile time, it doesn't have to do dynamic dispatch, so it has no overhead. It's what the julia folks call type-stable code
If ifs and buts were candy and nuts...
This becomes an important part of optimizing Julia code. There is some tooling for this. Below, identity is a type stable function because we know that an Int64 argument results in a Int64 output. The macro code_warntype reveals the type analysis:

``` julia> @code_warntype identity(5) MethodInstance for identity(::Int64) from identity(x) @ Base operators.jl:513 Arguments #self#::Core.Const(identity) x::Int64 Body::Int64 1 ─ nothing └── return x ```

This is type unstable and results in dynamic dispatch because we are not sure if the argument to identity will be an Int64 or a Float64.

``` julia> f(x) = identity(x ≥ 0 ? x : x + 0.0) f (generic function with 1 method)

julia> @code_warntype f(5) MethodInstance for f(::Int64) from f(x) @ Main REPL[4]:1 Arguments #self#::Core.Const(f) x::Int64 Locals @_3::Union{Float64, Int64} Body::Union{Float64, Int64} 1 ─ %1 = (x ≥ 0)::Bool └── goto #3 if not %1 2 ─ (@_3 = x) └── goto #4 3 ─ (@_3 = x + 0.0) 4 ┄ %6 = @_3::Union{Float64, Int64} │ %7 = Main.identity(%6)::Union{Float64, Int64} └── return %7 ```

Now with better formatting...

This becomes an important part of optimizing Julia code. There is some tooling for this. Below, identity is a type stable function because we know that an Int64 argument results in a Int64 output. The macro code_warntype reveals the type analysis:

  julia> @code_warntype identity(5)
  MethodInstance for identity(::Int64)
    from identity(x) in Base at operators.jl:526
  Arguments
    #self#::Core.Const(identity)
    x::Int64
  Body::Int64
  1 ─     return x


  julia> f(x) = identity(x ≥ 0 ? x : x + 0.0) 
  f (generic function with 1 method)

  julia> @code_warntype f(5)
  MethodInstance for f(::Int64)
    from f(x) in Main at REPL[6]:1
  Arguments
    #self#::Core.Const(f)
    x::Int64
  Locals
    @_3::Union{Float64, Int64}
  Body::Union{Float64, Int64}
  1 ─ %1 = (x ≥ 0)::Bool
  └──      goto #3 if not %1
  2 ─      (@_3 = x)
  └──      goto #4
  3 ─      (@_3 = x + 0.0)
  4 ┄ %6 = @_3::Union{Float64, Int64}
  │   %7 = Main.identity(%6)::Union{Float64, Int64}
  └──      return %7
>happens at runtime

is not technically true, because that implies a massive slow-down. instead it's more accurate to say behavior-wise it's always equivalent to a dynamic dispatch, but because Julia's Just-Ahead-of-Time compilation, often you eliminate the dynamic dispatch during run time.

It is technically true, Julia and other programming language's implementation of multiple dispatch notwithstanding.

First sentence from the Wikipedia article on multiple dispatch:

"Multiple dispatch or multimethods is a feature of some programming languages in which a function or method can be dynamically dispatched based on the run-time (dynamic) type or, in the more general case, some other attribute of more than one of its arguments."

And later:

"Multiple dispatch should be distinguished from function overloading, in which static typing information, such as a term's declared or inferred type (or base type in a language with subtyping) is used to determine which of several possibilities will be used at a given call site, and that determination is made at compile or link time (or some other time before program execution starts) and is thereafter invariant for a given deployment or run of the program."

The dispatch is based on the "runtime type", but that does not necessarily "happen at runtime", because the runtime/dynamic type can often be determined statically.
Yes, thank you! I keep re-learning and forgetting this. Trying to research now and see how this manifests in practice.
This video helps understand the difference. https://youtu.be/kc9HwsxE1OY