Generic code relies on specialization instead of dynamic dispatches to be generic with respect to input types. That is, for each new input type, a new method gets compiled (allowing the dispatch to be resolved statically).
Generic code relies on specialization instead of dynamic dispatches to be generic with respect to input types. That is, for each new input type, a new method gets compiled (allowing the dispatch to be resolved statically).
Here is the relevant quote from [1]: "In the context of julia though, compile time type simply do not exist ...."
[1]: https://discourse.julialang.org/t/claim-false-julia-isnt-mul...
Also, that comment is saying "compile time type" does not exist. I don't know C++, so I cannot comment on it, but from the sound of Yu Yichao's comment, C++ has separate concepts for runtime vs compile time types. Julia does not (as already said by adgjlsfhk1).
While it is not part of the language semantics, there certainly is, in the current implementation, a time at which any given method in Julia is (JAOT) compiled (via SSA-form IR, LLVM IR, and finally to native machine code) -- and whether or not types are able to be inferred at this time is sufficiently important that it has its own name: type stability [e.g., 2], with type-stable code being generally a couple orders of magnitude faster than equivalent type-unstable code.
[1] https://stackoverflow.com/questions/28078089/is-julia-dynami...
[2] https://www.juliabloggers.com/writing-type-stable-julia-code...
There are some weak mechanisms to prevent useless overspecialization such as @nospecialize and there are attempts to add smarter recompilation strategies by some packages.
Once this method is compiled, it will be used whenever the same function is called with the same argument types.
If function f(...) calls g(...) then the first time you call f(...), g(...) would normally also get compiled. The compilation is specialized on the type of input arguments (the method is selected by multiple dispatch and code is specialized further by concrete type information).
If the concrete types of ... in the g(...) call are inferrable, then g(...) is specialized and compiled to native code immediately, and possibly even inlined. If those types can't be inferred, it will repeat this process when it is called (there is also a cache of specialized code so it only compiles once, but you need to "look up" the function in cache dynamically in that case).
In many situations the types of an entire program can be inferred and be "compiled" ahead of time, but the semantics are always that of an interpretter.