One could define typeof(x::T) where T = T
. So why is it built-in instead of coded in Julia?
You really don’t want it to be overloadable, because then people might try that. For that purpose a builtin is just fine. Not to mention that the compiler can generate efficient code for typeof
even when it doesn’t know the type of the variable while your proposed definition would fall back to a dynamic dispatch (that then internally calls jl_typeof
in C). That’s all optimizable of course, but there’s just no benefit to making it a generic function.
Recently I had a similar issue with ifelse
. What is the benefit of it being built-in? Is it because then the compiler can avoid branching and if it were overloadable it would not be possible?
No, ifelse
is horrible and will go away.
Thanks! Good to know, because this is what I thought it should be, but low level stuff is often tricky.
Can you eliminate it before Julia 2.0?
Sure, just define ifelse(b, x, y) = b ? x : y
.
For introductory users, the ternary operator is pretty tough for them to mentally parse… So I hope that this sort of definition stays around in one form or another (for when short circuiting isn’t needed, and clarity is at a premium)
Honestly I think condition ? value : othervalue
is very clear.
Why is it horrible?
Ah you mean no longer making it a builtin.
Primarily because type inference/optimizations can’t use the conditional to reason about the arguments (e.g. type inference may know that the condition implies something about the types of the arguments, but since the arguments are evaluated first it can’t use that to optimize without turning ifelse back into ?:
).
I thought that the purpose of ifelse
was to reap performance benefits by avoiding branching, and that for example vectorization was prevented by branching. Is that no longer relevant?
The hardest thing for the vectorizer about branches is to proof that both branches are free of side effects. The branch itself isn’t an issue (at least on latest llvm). So a eagerly evaluating branch is still somewhat useful but it can just be implemented as a branch and an intrinsic isn’t useful.