I find that expressions like
a = f(a, ...)
a += f(...)
can be a frequent source of nasty type instabilities. Nasty especially because they can lie dormant until generic code is suddenly used with a different numerical type, etc. So I typically
guard against that with something like
a = oftype(a, f(a, ...))
But it’s tedious to write and makes the code harder to read. It might be nice to have a macro like
@typestable a = f(a, ...)
@typestable a += f(...)
that inserts the necessary oftype
in assignment-like expressions. Do we have something like this around, already?
Agree. Writing n += UInt16(1)
, n += int_T(1)
, x *= Float32(2.0)
all over the place is very annoying. Unfortunately, I don’t know a less annoying way.
If there’s no macro like this around yet, can someone suggest a fitting package to contribute this to? Or maybe we might even want something like this in Base?
You should be able to do:
function f(...)
A = typeof(a)
a::A = f(a, ...)
# now no more ::A is needed
a = g(a, ...)
....
end
See https://docs.julialang.org/en/stable/manual/types/#Type-Declarations-1
2 Likes
True - it doesn’t seem very common, though, for some reason (only a few instance in the whole of Base, also not frequent in common packages). But I agree, it’s probably the safest way. Is there some drawback to it? I just wonder why one doesn’t see it more often.
I guess the intersection where the programmer can determine the type easily, but the compiler can’t, is pretty rare.
I’m not quite sure I understand - whether I do
a = ...
...
a += typeof(a)(...)
or
x = ...
a::typeof(x) = x
...
a += ...
it’s type inference by the compiler in both cases, right?
The situation mostly occurs with variables that need to be modified within a loop (e.g. sums), of course.
Does this help?
macro keeptype(x)
y = x.args[1]
z = x.args[2]
f = z.args[1]
a = z.args[2]
b = z.args[3]
return esc(:($y = $f($a, typeof($a)($b))))
end
@keeptype a = 1 + 2.0
This only works for two valued functions like +
, but you could use splatting and mapping to make it more general.
In the second case, there is a type assertion too.
I was referring to the case where the type is stable, it is just that the compiler can’t prove it. In my experience, this is getting quite rare in v0.7
, but I tend to write short, small functions so it is possible that my style just meshes well with the compiler.