Open
Description
I had a 2D array of integers and used replace
to replace some of them using a list of pairs.
function replace_listcomp(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
result = [replace(rr, p...) for rr in r]
return result
end
With this list comprehension, Julia correctly determines the output type:
julia> @code_warntype replace_listcomp([[1,2,3]], [1 => 10])
# output cropped to relevant part
Locals
#1::var"#1#2"{Vector{Pair{Int64, Int64}}}
result::Vector{Vector{Int64}}
Body::Vector{Vector{Int64}}
I then changed the function to use broadcast syntax instead, but surprisingly, it was no longer able to determine the output type.
function replace_broadcast(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
result = replace.(r, p...)
return result
end
julia> @code_warntype replace_broadcast([[1,2,3]], [1 => 10])
# [...]
Arguments
#self#::Core.Const(replace_broadcast)
r::Vector{Vector{Int64}}
p::Vector{Pair{Int64, Int64}}
Locals
result::Any
Body::Any
1 ─ %1 = Core.tuple(Main.replace, r)::Tuple{typeof(replace), Vector{Vector{Int64}}}
│ %2 = Core._apply_iterate(Base.iterate, Base.broadcasted, %1, p)::Any
│ (result = Base.materialize(%2))
└── return result
It now says the output type is just Any
. I expected that it would say Vector{Vector{Int64}}
instead, just like the previous example.
Interestingly though, it does figure out the output type if I change the p
argument from a vector to a tuple.
function replace_broadcast_tuple(r :: Vector{Vector{Int}}, p :: Tuple{Vararg{Pair{Int, Int}}})
result = replace.(r, p...)
return result
end
julia> @code_warntype replace_broadcast_tuple([[1,2,3]], (1 => 10, 2 => 15))
# [...]
Arguments
#self#::Core.Const(replace_broadcast_tuple)
r::Vector{Vector{Int64}}
p::Tuple{Pair{Int64, Int64}, Pair{Int64, Int64}}
Locals
result::Vector{Vector{Int64}}
Body::Vector{Vector{Int64}}
1 ─ %1 = Core.tuple(Main.replace, r)::Tuple{typeof(replace), Vector{Vector{Int64}}}
│ %2 = Core._apply_iterate(Base.iterate, Base.broadcasted, %1, p)::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(replace), Tuple{Vector{Vector{Int64}}, Base.RefValue{Pair{Int64, Int64}}, Base.RefValue{Pair{Int64, Int64}}}}
│ (result = Base.materialize(%2))
└── return result
While I've already found a workaround that doesn't use replace
at all, I figured I'd post this anyway since it surprised me when I encountered it.
julia> versioninfo()
Julia Version 1.7.2
Commit bf53498635 (2022-02-06 15:21 UTC)