Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declare that f is applied iteratively in map! #47012

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3225,7 +3225,7 @@ mapany(f, itr) = Any[f(x) for x in itr]
map(f, c...) -> collection

Transform collection `c` by applying `f` to each element. For multiple collection arguments,
apply `f` elementwise, and stop when when any of them is exhausted.
apply `f` elementwise, and stop when any of them is exhausted.

See also [`map!`](@ref), [`foreach`](@ref), [`mapreduce`](@ref), [`mapslices`](@ref), [`zip`](@ref), [`Iterators.map`](@ref).

Expand Down Expand Up @@ -3279,10 +3279,15 @@ function map_n!(f::F, dest::AbstractArray, As) where F
end

"""
map!(function, destination, collection...)
map!(f, destination, collection...)

Like [`map`](@ref), but stores the result in `destination` rather than a new
collection. `destination` must be at least as large as the smallest collection.
Iteratively apply `f` to `collection`s. At each iteration, store the return value of `f` at
the corresponding location in `destination`. For multiple collection arguments, apply `f`
elementwise, and stop when any of them is exhausted. `destination` must be at least as
large as the smallest collection.

If `destination` is aliased with any of the input collections, then the result of `map!`
might be different from the result of `map`.

See also: [`map`](@ref), [`foreach`](@ref), [`zip`](@ref), [`copyto!`](@ref).

Expand All @@ -3305,6 +3310,22 @@ julia> map!(+, zeros(Int, 5), 100:999, 1:3)
105
0
0

julia> b = [1, 2, 3, 4];

julia> v = @view b[end:-1:begin]
4-element view(::Vector{Int64}, 4:-1:1) with eltype Int64:
4
3
2
1

julia> map!(x -> x + 1, b, v)
4-element Vector{Int64}:
5
4
5
6
```
"""
function map!(f::F, dest::AbstractArray, As::AbstractArray...) where {F}
Expand Down
29 changes: 29 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,35 @@ include("generic_map_tests.jl")
generic_map_tests(map, map!)
@test_throws ArgumentError map!(-, [1])

@testset "iterative application of f in map!" begin
# Issue #46352.
# These tests are outside of the generic_map_tests() function, because the
# "iteratively apply f" interface does not apply to aysncmap!.

# Ensure that f is applied iteratively to the source collections, and at each
# iteration the return value is stored at the corresponding location in the
# destination collection. (These tests should verify that SIMD is not happening.)
for T in (Int32, Int64, Float32, Float64)
a = T[1:8...]
v = view(a, 8:-1:1)
@test map!(x -> x + 1, a, v) == [9, 8, 7, 6, 7, 8, 9, 10]

a = T[1:8...]
v = view(a, 8:-1:1)
@test map!(+, a, T[1:8...], v) == [9, 9, 9, 9, 14, 15, 16, 17]

a = T[1:8...]
v = view(a, 8:-1:1)
@test map!(+, a, T[1:8...], ones(T, 8), v) == [10, 10, 10, 10, 16, 17, 18, 19]
end

# If you give map! a view of a BitVector, then the AbstractArray method is called
# rather than the BitArray method.
a = BitVector((true, true))
v = view(a, 2:-1:1)
@test map!(!, a, v) == BitVector((false, true))
end

test_UInt_indexing(TestAbstractArray)
test_13315(TestAbstractArray)
test_checksquare()
Expand Down