Search code examples
juliavectorization

How can I use map! in julia?


How can I use map! with a function using vector variables in julia?

Codes below did not work.

Perhaps, there might be a simple solution of below codes,

but I want to use map! in this problem.

 a1 = ones(100, 2)
 a2 = ones(100, 2)
 a3 = ones(100, 2)

 function expe1(v1,v2,v3)
  v1 + v2 + v3
 end

 dest = [zeros(100) for i in 1:2]

 map!(expe1, dest, eachcol(a1), eachcol(a2), eachcol(a3))

Error:

ERROR: MethodError: no method matching map!(::typeof(expe1), ::Vector{Vector{Float64}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}})
Closest candidates are:
  map!(::F, ::AbstractArray, ::AbstractArray) where F at abstractarray.jl:2924
  map!(::F, ::AbstractArray, ::AbstractArray, ::AbstractArray) where F at abstractarray.jl:2967
  map!(::F, ::AbstractArray, ::AbstractArray...) where F at abstractarray.jl:3024
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

Solution

  • There is no method of map! for non-array iterables, because it insists on all arguments being AbstractArrays having the same shape.

    To write the result into a destination array without intermediate allocation, you could broadcast-assign it a generator:

    julia> dest .= Base.Generator(expe1, eachcol(a1), eachcol(a2), eachcol(a3))
    2-element Vector{Vector{Float64}}:
     [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
     [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
    

    Something like this should also work:

    function my_map!(f::F, dest::AbstractArray, As...) where F
        for (i, a...) in zip(eachindex(dest), As...)
            val = f(a...)
            @inbounds dest[i] = val
        end
        return dest
    end