Skip to content

Commit 4913c25

Browse files
authored
Merge pull request #17266 from JuliaLang/teh/mapslices_copy
RFC: prevent mapslices from mutating the original array
2 parents b25739d + d9ce339 commit 4913c25

File tree

4 files changed

+15
-5
lines changed

4 files changed

+15
-5
lines changed

NEWS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ Breaking changes
9393
If a reshaped copy is needed, use `copy(reshape(a))` or `copy!` to a new array of
9494
the desired shape ([#4211]).
9595

96-
* `mapslices` will always pass a view, so passing mutating functions will mutate the underlying array ([#16260])
96+
* `mapslices` now re-uses temporary storage. Recipient functions
97+
that expect input slices to be persistent should copy data to
98+
other storage ([#17266]).
9799

98100
* Local variables and arguments are represented in lowered code as numbered `Slot`
99101
objects instead of as symbols ([#15609]).
@@ -294,3 +296,4 @@ Deprecated or removed
294296
[#16645]: https://github.com/JuliaLang/julia/issues/16645
295297
[#16731]: https://github.com/JuliaLang/julia/issues/16731
296298
[#16972]: https://github.com/JuliaLang/julia/issues/16972
299+
[#17266]: https://github.com/JuliaLang/julia/issues/17266

base/abstractarray.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,8 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector)
14171417
idx[d] = Colon()
14181418
end
14191419

1420-
r1 = f(view(A, idx...))
1420+
Aslice = A[idx...]
1421+
r1 = f(Aslice)
14211422

14221423
# determine result size and allocate
14231424
Rsize = copy(dimsA)
@@ -1449,7 +1450,8 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector)
14491450
for i in 1:nidx
14501451
idx[otherdims[i]] = ridx[otherdims[i]] = I.I[i]
14511452
end
1452-
R[ridx...] = f(view(A, idx...))
1453+
_unsafe_getindex!(Aslice, A, idx...)
1454+
R[ridx...] = f(Aslice)
14531455
end
14541456
end
14551457

base/statistics.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,7 @@ end
492492
median!{T}(v::AbstractArray{T}) = median!(vec(v))
493493
median{T}(v::AbstractArray{T}) = median!(copy!(Array(T, length(v)), v))
494494

495-
median!{T}(v::AbstractArray{T}, region) = mapslices(median!, v, region)
496-
median{T}(v::AbstractArray{T}, region) = median!(copy(v), region)
495+
median{T}(v::AbstractArray{T}, region) = mapslices(median!, v, region)
497496

498497
# for now, use the R/S definition of quantile; may want variants later
499498
# see ?quantile in R -- this is type 7

test/arrayops.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,12 @@ let
843843
n3a = mapslices(x-> ones(1,6), c, [2,3])
844844
@test size(n1a) == (1,6,4) && size(n2a) == (1,3,6) && size(n3a) == (2,1,6)
845845
@test size(n1) == (6,1,4) && size(n2) == (6,3,1) && size(n3) == (2,6,1)
846+
847+
# mutating functions
848+
o = ones(3, 4)
849+
m = mapslices(x->fill!(x, 0), o, 2)
850+
@test m == zeros(3, 4)
851+
@test o == ones(3, 4)
846852
end
847853

848854

0 commit comments

Comments
 (0)