Is it expected that the last item errors?
a = zeros(3);
map(x -> x[1] + x[2] * 2, enumerate([1, 2, 3])); # this works
map!(x -> x * 2, a,[1, 2, 3]); # this works
map!(x -> x[1] + x[2] * 2, a,[(1,1),(1,2),(1,3)]) # this works
map!(x -> x[1] + x[2] * 2, a,enumerate([1, 2, 3])); # method error
I also tried (i,x) -> i + x*2
with the last one, but that didn't work either. collect
ing the enumeration first does work.
It looks like weirdly, map!
is not defined for arbitrary iterables.
Anyway, IMO, people should default to lazy mapping in most cases: Iterators.map(x -> x[1] + x[2] * 2, enumerate(a))
works just fine
I think that, in the general case, it's not clear how to do assignment on arbitrary iterables, which is probably why map!
is not defined for them. For example, trying to map!
from a tuple into a matrix is ambiguous unless you assume some convention for indexing the matrix by 1:n
. Probably fine in this case since Julia already has an integer indexing convention for matrices, but it may not generalize well.
In my mind fewer functions should be defined for general iterables because some of them make rather large and often incorrect assumptions about their inputs. In that light I agree
But in this particular case, it should be known how to do assignment on the destination since it's an Array?
A method which takes as source an arbitrary iterable and throws if it doesn't have a known length (which the return type of enumerate
does) seems reasonable
You could always assume an implicit mapping by iteration order, but, map
is array-aware in a way I'm not entirely sure I understand, for example
In [2]: map(identity, (1:3) .* (1:4)')
3×4 Matrix{Int64}:
1 2 3 4
2 4 6 8
3 6 9 12
If map!
is respecting the array shape of it's arguments, it would be weird if it let you combine them with iterators that dont' have a shape (or have a merely implicit flat shape).
map
is a whole different mess and a can on worms I'd rather not open
For map!
, I think Base has all the right traits to check that the source iterable has the same size/shape as the destination array before proceeding
@Brian Chen You mean in the special case of Iterators.Enumerate{UnitRange{Int64}}
or for more general iterators with potentially unknown size?
They'd need to have a known size since Arrays have a known size. Enumerating a range or an array happens to fit that criteria, yes
Last updated: Dec 28 2024 at 04:38 UTC