# \`Replace\` function defaulting to type Any when using broadcasting, but not with a for-loop

**URL:** <https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030>\
**Category:** General Usage\
**Tags:** question\
**Created:** [December 13, 2021, 4:32pm UTC](https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030 "2021-12-13T16:32:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![numberMX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/numbermx/32/31874_2.png) [@numberMX](https://discourse.julialang.org/u/numberMX)\
**Post date:** [December 13, 2021, 4:32pm UTC](https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030/1 "2021-12-13T16:32:52Z")

</div>

I had a situation the other day where I had a 2D vector of integers, and I wanted to use the `replace` function with a list of replacement pairs, on the integers in the inner vectors.

If I use a for-loop list comprehension, Julia can correctly determine the type of the output:

```julia
function replace_listcomp(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
    result = [replace(rr, p...) for rr in r]
    return result
end

julia> @code_warntype replace_listcomp([Int[]], Pair{Int, Int}[])
# the output is long, but the relevant bit is:
  result::Vector{Vector{Int64}}
Body::Vector{Vector{Int64}}

```

However, if I try to do the same thing using broadcasting instead … suddenly, Julia can’t determine the output type, and defaults to `Any`:

```julia
function replace_broadcast(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
    result = replace.(r, p...)
    return result
end

julia> @code_warntype replace_broadcast([Int[]], Pair{Int, Int}[])
# the relevant part again:
Locals
  result::Any
Body::Any #(these show up in red in the terminal)

```

Why is this happening? It seems like it should be able to determine the output type, but can’t for some reason. Is this a bug in Julia?

(PS: I already have an alternate solution for my situation that avoids the `replace` function entirely, but I figured I’d ask anyway because I’m curious about what’s happening here.)

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [December 13, 2021, 7:53pm UTC](https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030/2 "2021-12-13T19:53:52Z")

</div>

Your code (without `@code_warntype`) does not run:

Is that intentional?

```julia
julia> function replace_listcomp(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
           result = [replace(rr, p...) for rr in r]
           return result
       end
replace_listcomp (generic function with 1 method)

julia> replace_listcomp([Int[]], Pair{Int, Int}[])
ERROR: MethodError: no method matching promote_valuetype()
Closest candidates are:
  promote_valuetype(::Pair{K, V}) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:580
  promote_valuetype(::Pair{K, V}, ::Pair...) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:581
Stacktrace:
 [1] replace(::Vector{Int64}; count::Nothing)
   @ Base ./set.jl:570
 [2] replace(::Vector{Int64})
   @ Base ./set.jl:570
 [3] #3
   @ ./array.jl:0 [inlined]
 [4] iterate
   @ ./generator.jl:47 [inlined]
 [5] collect(itr::Base.Generator{Vector{Vector{Int64}}, var"#3#4"{Vector{Pair{Int64, Int64}}}})
   @ Base ./array.jl:724
 [6] replace_listcomp(r::Vector{Vector{Int64}}, p::Vector{Pair{Int64, Int64}})
   @ Main ./REPL[7]:2
 [7] top-level scope
   @ REPL[8]:1

julia> function replace_broadcast(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
           result = replace.(r, p...)
           return result
       end
replace_broadcast (generic function with 1 method)

julia> 

julia> replace_broadcast([Int[]], Pair{Int, Int}[])
ERROR: MethodError: no method matching promote_valuetype()
Closest candidates are:
  promote_valuetype(::Pair{K, V}) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:580
  promote_valuetype(::Pair{K, V}, ::Pair...) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:581
Stacktrace:
 [1] replace(::Vector{Int64}; count::Nothing)
   @ Base ./set.jl:570
 [2] replace(::Vector{Int64})
   @ Base ./set.jl:570
 [3] _broadcast_getindex_evalf
   @ ./broadcast.jl:670 [inlined]
 [4] _broadcast_getindex
   @ ./broadcast.jl:643 [inlined]
 [5] getindex
   @ ./broadcast.jl:597 [inlined]
 [6] copy
   @ ./broadcast.jl:899 [inlined]
 [7] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(replace), Tuple{Vector{Vector{Int64}}}})
   @ Base.Broadcast ./broadcast.jl:860
 [8] replace_broadcast(r::Vector{Vector{Int64}}, p::Vector{Pair{Int64, Int64}})
   @ Main ./REPL[9]:2
 [9] top-level scope
   @ REPL[10]:1
julia> function replace_listcomp(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
           result = [replace(rr, p...) for rr in r]
           return result
       end
replace_listcomp (generic function with 1 method)

julia> replace_listcomp([Int[]], Pair{Int, Int}[])
ERROR: MethodError: no method matching promote_valuetype()
Closest candidates are:
  promote_valuetype(::Pair{K, V}) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:580
  promote_valuetype(::Pair{K, V}, ::Pair...) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:581
Stacktrace:
 [1] replace(::Vector{Int64}; count::Nothing)
   @ Base ./set.jl:570
 [2] replace(::Vector{Int64})
   @ Base ./set.jl:570
 [3] #3
   @ ./array.jl:0 [inlined]
 [4] iterate
   @ ./generator.jl:47 [inlined]
 [5] collect(itr::Base.Generator{Vector{Vector{Int64}}, var"#3#4"{Vector{Pair{Int64, Int64}}}})
   @ Base ./array.jl:724
 [6] replace_listcomp(r::Vector{Vector{Int64}}, p::Vector{Pair{Int64, Int64}})
   @ Main ./REPL[7]:2
 [7] top-level scope
   @ REPL[8]:1

julia> function replace_broadcast(r :: Vector{Vector{Int}}, p :: Vector{Pair{Int, Int}})
           result = replace.(r, p...)
           return result
       end
replace_broadcast (generic function with 1 method)

julia> 

julia> replace_broadcast([Int[]], Pair{Int, Int}[])
ERROR: MethodError: no method matching promote_valuetype()
Closest candidates are:
  promote_valuetype(::Pair{K, V}) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:580
  promote_valuetype(::Pair{K, V}, ::Pair...) where {K, V} at ~/Programme/julia-1.7.0/share/julia/base/set.jl:581
Stacktrace:
 [1] replace(::Vector{Int64}; count::Nothing)
   @ Base ./set.jl:570
 [2] replace(::Vector{Int64})
   @ Base ./set.jl:570
 [3] _broadcast_getindex_evalf
   @ ./broadcast.jl:670 [inlined]
 [4] _broadcast_getindex
   @ ./broadcast.jl:643 [inlined]
 [5] getindex
   @ ./broadcast.jl:597 [inlined]
 [6] copy
   @ ./broadcast.jl:899 [inlined]
 [7] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(replace), Tuple{Vector{Vector{Int64}}}})
   @ Base.Broadcast ./broadcast.jl:860
 [8] replace_broadcast(r::Vector{Vector{Int64}}, p::Vector{Pair{Int64, Int64}})
   @ Main ./REPL[9]:2
 [9] top-level scope
   @ REPL[10]:1

```

This seems to run but produces the same red line with `@code_warntype`.  
EDIT:

```julia
julia> replace_broadcast([Int[1]], Pair{Int, Int}[1 => 1])
1-element Vector{Vector{Int64}}:
 [1]

julia> replace_listcomp([Int[1]], Pair{Int, Int}[1 => 1])
1-element Vector{Vector{Int64}}:
 [1]

```

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [December 13, 2021, 9:19pm UTC](https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030/3 "2021-12-13T21:19:47Z")

</div>

I was playing around, and replacing your vector `p` with a tuple seems to fix the instability.

```julia
function replace_listcomp(r :: Vector{Vector{Int}}, p)
    result = [replace(rr, p...) for rr in r]
    return result
end

function replace_broadcast(r :: Vector{Vector{Int}}, p)
    result = replace.(r, p...)
    return result
end

function main()
    r = [[1], [2]]
    p = (2 => 20, 1 => 10) 
    @show replace_listcomp(r, p)
    @show replace_broadcast(r, p)
        
    return nothing
end

# REPL
julia> main()
replace_listcomp(r, p) = [[10], [20]]
replace_broadcast(r, p) = [[10], [20]]

julia> @code_warntype replace_broadcast([Int[1], Int[2]], (1=>12, 2=>22))
MethodInstance for replace_broadcast(::Vector{Vector{Int64}}, ::Tuple{Pair{Int64, Int64}, Pair{Int64, Int64}})
  from replace_broadcast(r::Vector{Vector{Int64}}, p) in Main at /home/fxw/lel.jl:6
Arguments
  #self#::Core.Const(replace_broadcast)
  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

```

---

<div class="post-metadata">

**Author:** ![numberMX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/numbermx/32/31874_2.png) [@numberMX](https://discourse.julialang.org/u/numberMX)\
**Post date:** [December 14, 2021, 4:34am UTC](https://discourse.julialang.org/t/replace-function-defaulting-to-type-any-when-using-broadcasting-but-not-with-a-for-loop/73030/4 "2021-12-14T04:34:15Z")

</div>

Yeah, `@code_warntype` only looks for the types of the values, not the values themselves, when you call it - which is why I simply put empty vectors that match the types.

To actually use it you’d have to put values into those vectors (which I see you did in your edit). Since `@code_warntype` looks at the types only, it will produce the same output.
