Add fill method accepting constructor function

Initialising array of arrays fill([], 2) would end up in an error, as all arrays will be actually the same array.

I suggest provide additional method for fill function, accepting constructor function fill(() -> [], 2).

It’s possible to use for loop comprehension. But adding additional method to fill would make fill complement.

1 Like

So how would you go about filling an array with a function then? You can do map(i -> [], 1:2), however. Or the kinda cryptic 0 .|> fill(i -> [], 2).

2 Likes

I imagine that a function specifically for this, eg named fillwith or similar, would be a useful addition to Base. I thought I saw some discussion about this an issue, but I cannot find it.

Maybe https://github.com/JuliaLang/julia/pull/16769 ?

1 Like

Yes, it is related somewhat, but it is my impression that the focus of that is on modfying existing arrays.

I am not sure if adding this to Base is worth it though, the general case is

f.(CartesianIndices((1:3, 1:4)))

which already compiles to very neat code when f is _ -> stuff.

2 Likes

Nice trick!

Ah you are right.

I have never used the resize! function directly but the idea of a copy keyword would make a lot of sense for fill. I.e. fill([], 2, copy=true) could make an array with distinct empty arrays.

Beside already mentioned problem with defining an array of functions (which is somewhat contrived, as functions defined via function or -> have singleton types), there is a worse one: what if someone makes a callable struct subtyping Function? E.g.:

struct Id{T} <: Function
    value::T
end

(x::Id)() = x.value

Why should fill(Id(0), k) return an array of zeros and not an array of Ids?

Not necessarily. Try

many_functions(n) = [x -> x + i for i in 1:n]
v = many_functions(10) # has homogeneous element types

This is essentially equivalent to making a struct with i, and defining it to be callable.

Ah, my bad, only looked at functions with no captured variables.

Then, I’d better say “an idea of array of functions may seem contrived, but in Julia it’s not uncommon to create entities that may be viewed as both function and data objects”.

Yep. And of course this power can be abused in creative ways:

julia> (i::Int)(x) = i + x

julia> (2).([3,5])
2-element Array{Int64,1}:
 5
 7
1 Like