# Calling `similar()` with all the three input arguments

I am trying to understand the full usage of `similar()`. The manual shows an example

``````similar(falses(10), Float64, 2, 4)
``````

and states that

Since `BitArray` s can only store elements of type `Bool` , however, if you request a different element type it will create a regular `Array` instead

Since the type and the dimension of the matrix (or array in general) to be created are specified, I am wondering what is the point in using the above code and not writing just

``````Matrix{Float64}(undef, 2, 4)
``````

instead.

Maybe it it is just plurality of ways to express the same thing, but I would be grateful for clarification. Namely does the full usage of `similar`, that is, specifying all the three input parameters (array, type, size), give any advantage over the latter way of creating an unitialized matrix of a given type and size?

The point is that `similar` allows the â€śreferenceâ€ť array to have some sort of say in what it returns. The example is perhaps overly simplistic â€” the power of `similar` comes when you donâ€™t immediately know one of the arguments and need to allocate a scratch or result array that is kinda-sorta like the reference one. For example, a simple `map` could be written as:

``````function map(f, A)
v1 = f(first(A))
result = similar(A, typeof(v1))
for i in eachindex(A)
result[i] = f(A[i])
end
return result
end
``````

This is overly simplistic (it evaluates `f` twice for the first element, doesnâ€™t support widening if the types change, etc, etc), but I hope you can see how it will allow the original array to have some sort of say in what a good array might be for `result`. For example, if `A` is a `BitArray`, it will either be a `BitArray` (if `f` also returns `Bool`s) or a `Array` otherwise. Or if `A` is a static array, itâ€™ll return an array that preserves its knowledge of the array size. Or if `A` is an immutable array (like `1:10`) then itâ€™ll always give you an `Array` since ranges canâ€™t be modified at all.

The same applies if you give it all three arguments â€” one or more of them might not be known to you ahead of time but by passing them all to `similar`, you can write generic code that does something reasonable through the power of multiple dispatch.

2 Likes

Another way of putting this is that if you know you want a `Matrix{Float64}` of the given size, then using the `Matrix{Float64}(undef, 2, 4)` constructor is the right thing to do. You might want to use `similar()` when you donâ€™t know exactly what kind of array-like thing you want, and you want the type of the arguments passed to `similar` to have some effect on what the resulting type is.

2 Likes

If you know all the inputs to `similar` beforehand, then itâ€™s not much point in using it.

But I think it would be awkward to disallow specifying all of them while allowing every-which-but-one. It would be surprising and seem inconsistent to the user, I think, and potentially awkward to implement (maybe one could just throw an error if fully specifiedâ€”but why!?).

1 Like