It was a “bug” in your code, i.e. it not type stable (that’s not illegal so bug may be the wrong word, at least surprising), but with it giving 0.0, i.e. Float64, it seemingly wouldn’t have been. So is it a bug in Julia? I think 0 is the intended behavior:
[Though I’m not sure, why not then the largest Int, Int128, or smallest Int8, or Bool, maybe this wasn’t given a lot of thought, and Float64 would be perfectly ok, even if Rational
s in your Real array. With just Rationals, you would/will still get them for zero.]
I can see when you use concrete types, Int, Int32, Float64 etc, that you would want to get out, 0, 0, 0.0, but for abstract types, I’m not really sure, and Real is one of those (most are prefixed with Abstract, with few exceptions such as Real, because that’s what that general math concept is named).
All integers are Real
s, but in general real numbers aren’t integers, they are flaot-like, but even more generally Rational
s. What would be best in your view, 0.0, or even 0//0?
If we change your function to be type unstable in a different way, combining integers and a rational:
func(r) = (r == 0) ? 0 : r//3
julia> a = func.(0.0:1.0:5.0)
ERROR: MethodError: no method matching //(::Float64, ::Int64)
you actually get an ERROR (sooner), making a problem obvious, but in some other context you would have gotten away with and then still gotten a Int(0). Would you then have expected 0//0?
It would not be expected, too much work, to get a 0//0 in your case, if e.g. only one rational in a huge array of Real
s. So I think you would still be surprised to see it produced if using only integers and floats (or generating, as you did).
What I would like, is that the REPL would warn when you make an type-unstable function, and you could ignore when you don’t care (it’s sometimes powerful to allow, not always a problem, though always slower).
That’s very good practice to avoid non-general code, but then you must also avoid 0. You get away with it though in the check. But 0.0 would also have worked there, and elsewhere then working for Float64:
Note, the is type-unstable for e.g. Float32 passed in, because then the division doesn’t get you Float64, but 0.0 will, that could be fixed with r/3.0. I don’t believe type-stable means getting the same type out as you put in, because you can pass many in an argument list, but some might consider this not, or at least not as generic, wanting Float32 out.