I use lots of Int32
s in my code because I have some large arrays of those. But for some x::Int32
we have typeof(x+1) == Int64
since numeric literals are Int64
by default (I have to use 64bit Julia to handle my arrays). The problem is, if I have some function f(x::Int32)
then f(x+1)
will method error. I don't want to implement a f(x::Int64) = f(convert(Int32, x))
for almost every function and want to use concrete types for type stability. Currently, I simply have expressions like x + Int32(1)
all over my code which looks really cluttered. For other types we have shorthands, i.e., 1.f0
gives me a Float32
and big"1"
a BigInt
. Is there something similar for Int32
?
Asked
Active
Viewed 246 times
4

Corylus
- 736
- 5
- 16
-
1Can't you just do your scalar arithmetic in `Int64`, and let them be auto-converted to `Int32` when you write them to your arrays? Also, you can define `f` as `f(x::Integer)`, it does not harm performance at all. – DNF Feb 11 '23 at 12:13
-
Fair. That would be possible. But I also like that something like `update!(somecollection, index::Int64, value::Int32)` (simplified example) helps against confusing the parameters. – Corylus Feb 11 '23 at 12:47
3 Answers
5
Since you explicitly mention the big_str
macro (big""
) you can easily define a similar macro for Int32 (the same way the uint128_str and int128_str is defined):
macro i32_str(s)
parse(Int32, s)
end
julia> typeof(i32"1")
Int32
this might still clutter your code too much so alternatively you could exploit that a number followed by a name is multiplication:
struct i32 end
(*)(n, ::Type{i32}) = Int32(n)
julia> typeof(1i32)
Int32

ahnlabb
- 2,017
- 1
- 6
- 16
4
You can make a macro to replace every literal integer with an Int32
, a bit like what ChangePrecision.jl does for floats. A very quick first attempt is:
julia> macro literal32(ex)
esc(literal32(ex))
end;
julia> literal32(ex::Expr) = Expr(ex.head, literal32.(ex.args)...);
julia> literal32(i::Int) = Int32(i);
julia> literal32(z) = z; # ignore Symbol, literal floats, etc.
julia> @literal32 [1,2] .+ 3
2-element Vector{Int32}:
4
5
julia> @literal32 function fun(x::AbstractVector)
x[1] + 2 # both 1 and 2 are changed
end
fun (generic function with 1 method)
julia> fun(Int32[3,4]) |> typeof
Int32
One place this may have unexpected consequences is literal type parameters:
julia> @literal32([1,2,3]) isa Array{Int32,1}
true
julia> @literal32 [1,2,3] isa Array{Int32,1}
false
Another is that x^2
will not use Base.literal_pow
, e.g. @literal32 Meta.@lower pi^2
.

mcabbott
- 2,329
- 1
- 4
- 8
1
What if you say:
# Or, a::Int32 = 1
julia> a = Int32(1)
1
julia> b::Int32 = a+2
3
julia> typeof(b)
Int32
julia> f(b)
...

Shayan
- 5,165
- 4
- 16
- 45
-
1Or e.g. `const i1 = Int32(1)` and the same pattern for any other constant value you would want to use like `i2` etc.. In this way you need only to type one extra `i` and also it is visually explicit that you are using `Int32` values. – Bogumił Kamiński Feb 11 '23 at 11:46
-
Oh, I absolutely haven't thought about defining a global constant! Since `1` is the by far most frequent literal, this would actually work very well. – Corylus Feb 11 '23 at 12:50