Having used Julia on a fairly regular basis for almost a year now, one of the most common causes I see of unnecessarily poor performance is type instability. It’s wonderful that Julia is dynamically typed for cases where that sort of thing is useful, but the fact that Julia is, after all, dynamically typed creates lots of opportunities for users to unknowingly create sub-optimal code. Having been brought up on mostly C++ and a little Fortran, I tend to be quite aware of the types of the objects in my code, but in the last few years I’ve been around an increasing number of people who are primarily familiar with Python both in the scientific and commercial communities. Some of these people tend not to think about types at all. (Indeed, I find Python’s approach of pretending types don’t exist at all to be a glaring absurdity in what is, for the most part, an otherwise fairly well-thought-out language.) I am also certainly guilty, even as a fairly experienced user, of occasionally writing type-unstable code where it doesn’t belong.
My question is this: do we think that the current Julia syntax does enough to encourage users to at least be aware of (if not enforce) the type stability (or instability) of their code?
To make this more concrete, let me make one not-very-serious suggestion that I haven’t put a huge amount of thought into. I love that we can now make type assertions on function output using, for example
function f(phi::AbstractFloat)::Complex{Float64}
e^(im*phi)
end
but I wonder if it might be a good idea, to promote good habits, to require syntax like
function::Complex{Float64} f(phi::AbstractFloat)
e^(im*phi)
end
so that, most functions as they are currently implemented would require a function::Any
or f(x)::Any
. The only use this serves would be to force the user to think “I’m writing a function, but it’s return type isn’t controlled, so I better not put it in any performance critical code.” Of course my above example opens a can of worms with parametric types, so I’m certainly not claiming it is the best possible implementation of this type of idea. (On the other hand, I don’t think requiring type assertions on all input arguments is particularly useful, because of multiple dispatch.)
Some possibly negative side-effects of this would be that it might encourage less experienced users to write overly type-specific (and, possibly, as a result overly complicated) code. It would also likely be a big turn off to people coming from Python, a crowd which, in my experience, mostly doesn’t want to be bothered with this sort of thing at all regardless of its impact on performance or stability. Another problem that I haven’t thought much about is what are the consequences (if any) of most functions having implicit convert
calls coming at their end (like in my examples above).
These are just random musings, but I wonder if the core developers of Julia have had similar thoughts. Has there been any thought given to this in the past? I’m skeptical of this myself, because I’m always skeptical of changes that don’t add any real functionality, but it’s something that’s occurred to me a number of times in the course of my using Julia. It would be nice if someone could come up with a better specific suggestion than the one I made here.