Julia does it an order of magnitude better, though.
A generic `f` will probably be similar to the Common Lisp one. However, as soon as you use `f` in a context where types are known (e.g. if you use multimethods to overload a function that calls `f`), it will be specialized and JIT-compiled for the specific type (int, float, matrix, ...), with no extra work for the programmer.
> The JIT compiler works incrementally as functions are applied, but the JIT compiler makes only limited use of run-time information when compiling procedures, since the code for a given module body or lambda abstraction is compiled only once. The JIT’s granularity of compilation is a single procedure body, not counting the bodies of any lexically nested procedures.
If I understand correctly, functions are inlined[0] (not saying this is bad, just different). If you declare functions as inline then you can get rid of the dispatching code in contexts where the type is known in advance.
Yes, small and explicitly tagged functions can inline directly into the caller. But even when that doesn't occur, Julia is able to avoid dynamic dispatch overhead by doing the dispatch at compile-time, making the function call point directly at the specialized method.
In order to do that with CLOS, we have to add an explicit "inline" directive (as shown by lispm in another comment), because methods can be redefined anytime. Taking a shortcut to an effective method could break the code.
A generic `f` will probably be similar to the Common Lisp one. However, as soon as you use `f` in a context where types are known (e.g. if you use multimethods to overload a function that calls `f`), it will be specialized and JIT-compiled for the specific type (int, float, matrix, ...), with no extra work for the programmer.