# Problem of eachcol in function

**URL:** <https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458>\
**Category:** General Usage\
**Tags:** function\
**Created:** [December 9, 2022, 7:35am UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458 "2022-12-09T07:35:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Xuekui\_wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xuekui_wang/32/30746_2.png) [@Xuekui\_wang](https://discourse.julialang.org/u/Xuekui_wang)\
**Post date:** [December 9, 2022, 7:35am UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/1 "2022-12-09T07:35:07Z")

</div>

When I see a program, a funciton f3 defined as follows.  
In manual: `eachcol` means: Create a generator that iterates over the second dimension of matrix A, returning the columns as AbstractVector views.  
The function returns a sum of two matrices determined by “m”，and “m” must be a BitVector.

How to understand the “m”(must be a BitVector) , and why does the function has "."and “…”?  
Thanks for your reply.

```julia
f3 = (y, ŷ) -> ((y, ŷ) -> (y[m] + ŷ[m]) ).((eachcol.((y, ŷ)))...)

```

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [December 9, 2022, 8:15am UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/2 "2022-12-09T08:15:48Z")

</div>

If I read that right:

- generally, `eachcol(x)` returns a generator over columns of `x`
- generally, `f.(x)` [broadcasts](https://docs.julialang.org/en/v1/manual/functions/#man-vectorized) `f` over elements of `x`, so `eachcol.((y, ŷ))` means broadcast `eachcol` over `(y, ŷ)`; basically equivalent to `(eachcol(y), eachcol(ŷ))`
- generally `f(x...)` means [splatting](https://docs.julialang.org/en/v1/manual/functions/#Varargs-Functions): `f((a, b)...)` means `f(a, b)`; in your case, it is used to pass `eachcol(y)` and `eachcol(ŷ)` as two arguments to the inner anonymous function (instead of a tuple `(eachcol(y), eachcol(ŷ))` as a single argument)
- the inner anonymous function is broadcasted over the corresponding columns (i.e., it is applied on each pair of corresponding columns)

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [December 9, 2022, 9:42am UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/3 "2022-12-09T09:42:13Z")

</div>

As a more general comment because you’ve asked a number of similar questions before: most of the code snippets you’ve posted are fairly unidiomatic, in my opinion borderline unreadable, Julia. In this case your function also seems to access a global variable `m`, which - apart from the general issues with using globals in funcions - is especially discouraged in Julia as it can absolutely kill performance (it is the first [Performance tip](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-tips)).

I understand that you are trying to understand someone else’s code, but if you start writing your own I’d recommend reading a few Julia tutorials and maybe packages with funcionality related to whatever you’re building to get a feel for idiomatic Julia.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [December 9, 2022, 10:25am UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/4 "2022-12-09T10:25:59Z")

</div>

Just to add to this, after staring at your function and @barucden’s exaplantion for a bit it seems you are adding a two matrices, each subsetted to only include certain rows, together and then returning a vector holding a vector for each column in the matrix after addition, is that right?

If so, a simple implementation might be:

```julia
f4(y, ŷ, m) = eachcol(y[m, :] .+ ŷ[m, :]);

```

here, m is also an input to the function so we’re not relying on global variables. The code is also supremely readable and easily understood imho - add matrices `y` and `ŷ`, restricting them to only include the rows selected by `m`. How are we doing with this?

```julia
julia> t1 = rand(100_000, 10); t2 = rand(100_000, 10); m = rand(Bool, 100_000);

julia> f3 = (y, ŷ) -> ((y, ŷ) -> (y[m] + ŷ[m]) ).((eachcol.((y, ŷ)))...);

julia> f4(y, ŷ, m) = eachcol(y[m, :] .+ ŷ[m, :]);

julia> using BenchmarkTools

julia> @btime f3($t1, $t2);
  6.704 ms (190 allocations: 11.52 MiB)

julia> @btime f4($t1, $t2, $m);
  7.678 ms (6 allocations: 11.51 MiB)

```

roughly the same performance (timings are a bit variable on my machine), but we’ve cut down allocations by a factor of of c. 30 by removing the access to global variables. We are cheating a little bit though as they functions do not return the same thing:

```julia
julia> typeof(f3(t1, t2))
Vector{Vector{Float64}} (alias for Array{Array{Float64, 1}, 1})

julia> typeof(f4(t1, t2, m))
ColumnSlices{Matrix{Float64}, Tuple{OneTo{Int64}}, SubArray{Float64, 1, Matrix{Float64}, Tuple{Slice{OneTo{Int64}}, Int64}, true}}

```

Essentially `eachcol` is just returning an iterator, which we need to `collect` to get a vector of vectors like we got from `f3`:

```julia
julia> f5(y, ŷ, m) = collect(eachcol(y[m, :] .+ ŷ[m, :]));

```

How does this fare?

```julia
julia> @btime f5($t1, $t2, $m);
  7.744 ms (7 allocations: 11.51 MiB)

```

We’ve added an allocation as we are now materializing the iterator through `collect` - you should think about whether this is necessary in your actual code, as for the most part Julia works just fine with iterators that are never materialized.

Now if you look at the total memory footprint of the allocations, you see that while there are much fewer allocations, their total size is almost unchanged (11.52MB to 11.51MB) - indicating that we are likely only saving very small allocations related to the global variable type checks. If you’ve also looked at the performance tips I linke above you’ll have come across [the section on using views for slices](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-views). In `f4` and `f5` we are doing `y[m, :]` which creates a copy of `y` by default and therefore allocates. The helpful `@views` macro can turn these copies into views, saving on allocations:

```julia
julia> f76(y, ŷ, m) = @views eachcol(y[m, :] .+ ŷ[m, :]);

```

Checking performance for this:

```julia
julia> @btime f7($t1, $t2, $m);
  1.766 ms (6 allocations: 4.60 MiB)

```

Much better - we have cut allocations by a factor of ~30 and runtime by a factor of ~4, while also making the code (in my view) much more legible and easy to understand.

---

<div class="post-metadata">

**Author:** ![Xuekui\_wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xuekui_wang/32/30746_2.png) [@Xuekui\_wang](https://discourse.julialang.org/u/Xuekui_wang)\
**Post date:** [December 9, 2022, 1:09pm UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/5 "2022-12-09T13:09:50Z")

</div>

> [@nilshg](#):
>
> I understand that you are trying to understand someone else’s code, but if you start writing your own I’d recommend reading a few Julia tutorials and maybe packages with funcionality related to whatever you’re building to get a feel for idiomatic Julia.

Thank you very much for your opinion, nilshg. Yes, I am understanding other people’s programs. I am also learning to write julia programs. I feel that this language has some special structures.  
If read a function block completely, I can’t understand the statements in it very well, so I take apart the functions written by others and understand them sentence by sentence.

---

<div class="post-metadata">

**Author:** ![Xuekui\_wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xuekui_wang/32/30746_2.png) [@Xuekui\_wang](https://discourse.julialang.org/u/Xuekui_wang)\
**Post date:** [December 9, 2022, 1:21pm UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/6 "2022-12-09T13:21:25Z")

</div>

Thank you very much for your patient explanation. I basically understand the characteristics of the Julia language, and I feel sorry for the difficulty in understanding the incomplete program. I will paste the complete readable program next time.

---

<div class="post-metadata">

**Author:** ![Xuekui\_wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xuekui_wang/32/30746_2.png) [@Xuekui\_wang](https://discourse.julialang.org/u/Xuekui_wang)\
**Post date:** [December 9, 2022, 1:58pm UTC](https://discourse.julialang.org/t/problem-of-eachcol-in-function/91458/7 "2022-12-09T13:58:57Z")

</div>

I understand what this function does, and your explain is very clear.  
Thank you very much for your help!
