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

Deprecate similar(f, …) in favor of just dispatching directly on f(…) #26733

Merged
merged 5 commits into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Deprecate similar(f, axes) to calling f directly... and implement a…
…n AbstractArray constructor
  • Loading branch information
mbauman committed Apr 6, 2018
commit 112b14996fdea642b125b32f16e8588b6e79ed8a
52 changes: 31 additions & 21 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,35 @@ convert(::Type{T}, a::T) where {T<:AbstractArray} = a
convert(::Type{AbstractArray{T}}, a::AbstractArray) where {T} = AbstractArray{T}(a)
convert(::Type{AbstractArray{T,N}}, a::AbstractArray{<:Any,N}) where {T,N} = AbstractArray{T,N}(a)

if nameof(@__MODULE__) === :Base # avoid method overwrite
# catch undefined constructors before the deprecation kicks in
# TODO: remove when deprecation is removed
function (::Type{T})(arg) where {T<:AbstractArray}
throw(MethodError(T, (arg,)))
end
to_axis(d::Integer) = OneTo(d)
to_axis(d::AbstractUnitRange) = d

# AbstractArray constructors: Gather args into a `AbstractArray{T,N}(undef, ::Tuple)` method
if nameof(@__MODULE__) === Core # avoid method overwrite with Core
# These methods and the types in these methods are shared between Core and Base
AbstractArray{T}(::UndefInitializer, dims::Vararg{Integer,N}) where {T,N} = AbstractArray{T,N}(undef, dims)
AbstractArray{T}(::UndefInitializer, dims::NTuple{N,Integer}) where {T,N} = AbstractArray{T,N}(undef, dims)

AbstractArray{T,N}(::UndefInitializer, dims::NTuple{N,Integer}) where {T,N} = Array{T,N}(undef, dims)
AbstractArray{Bool,N}(::UndefInitializer, dims::NTuple{N,Integer}) where {N} = BitArray{N}(undef, dims...)
elseif nameof(@__MODULE__) === :Base # avoid method overwrite with Core
# Add definitions supporting axes in Base alone — Core.OneTo is not shared with Base.OneTo
AbstractArray{T}(::UndefInitializer, dims::Vararg{DimOrInd,N}) where {T,N} = AbstractArray{T,N}(undef, dims)
AbstractArray{T}(::UndefInitializer, dims::NTuple{N,DimOrInd}) where {T,N} = AbstractArray{T,N}(undef, dims)
AbstractArray{T,N}(::UndefInitializer, dims::Vararg{DimOrInd,N}) where {T,N} = AbstractArray{T,N}(undef, dims)

AbstractArray{T,N}(::UndefInitializer, dims::NTuple{N,Union{Integer, OneTo}}) where {T,N} = AbstractArray{T,N}(undef, map(to_axis, dims))

AbstractArray{T,N}(::UndefInitializer, dims::NTuple{N,OneTo}) where {T,N} = Array{T,N}(undef, map(last, dims))
AbstractArray{T,0}(::UndefInitializer, ::Tuple{}) where {T} = Array{T,0}(undef)
AbstractArray{Bool,N}(::UndefInitializer, dims::NTuple{N,OneTo}) where {N} = BitArray{N}(undef, map(last, dims)...)
AbstractArray{Bool,0}(::UndefInitializer, ::Tuple{}) where {} = BitArray{0}(undef)

# catch undefined constructors before the deprecation kicks in
# TODO: remove when deprecation is removed
function (::Type{T})(arg) where {T<:AbstractArray}
throw(MethodError(T, (arg,)))
end
end

"""
Expand Down Expand Up @@ -590,14 +613,9 @@ indices of the result will match `A`.

would create a 1-dimensional logical array whose indices match those
of the columns of `A`.

similar(dims->zeros(Int, dims), axes(A))

would create an array of `Int`, initialized to zero, matching the
indices of `A`.
"""
similar(f, shape::Tuple) = f(to_shape(shape))
similar(f, dims::DimOrInd...) = similar(f, dims)
similar(::Type{T}, shape::Tuple) where {T} = T(to_shape(shape))
similar(::Type{T}, dims::DimOrInd...) where {T} = similar(T, dims)

"""
empty(v::AbstractVector, [eltype])
Expand Down Expand Up @@ -886,14 +904,6 @@ isempty(a::AbstractArray) = (_length(a) == 0)
# keys with an IndexStyle
keys(s::IndexStyle, A::AbstractArray, B::AbstractArray...) = eachindex(s, A, B...)

"""
of_indices(x, y)

Represents the array `y` as an array having the same indices type as `x`.
"""
of_indices(x, y) = similar(dims->y, oftype(axes(x), axes(y)))


## range conversions ##

map(::Type{T}, r::StepRange) where {T<:Real} = T(r.start):T(r.step):T(last(r))
Expand Down
15 changes: 9 additions & 6 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,11 @@ julia> fill(1.0, (5,5))
If `x` is an object reference, all elements will refer to the same object. `fill(Foo(),
dims)` will return an array filled with the result of evaluating `Foo()` once.
"""
fill(v, dims::Dims) = fill!(Array{typeof(v)}(undef, dims), v)
fill(v, dims::Integer...) = fill!(Array{typeof(v)}(undef, dims...), v)
fill(v, dims::NTuple{N, Integer}) where {N} = fill!(Array{typeof(v), N}(undef, dims), v)
fill(v, dims::NTuple{N, OneTo}) where {N} = fill!(Array{typeof(v), N}(undef, map(last, dims)), v)
fill(v, dims::NTuple{N, Union{Integer, OneTo}}) where {N} = fill!(Array{typeof(v), N}(undef, map(to_axis, dims)), v)
fill(v, dims::Tuple{}) = fill!(Array{typeof(v), 0}(undef), v)
fill(v, dims::DimOrInd...) = fill(v, dims)

"""
zeros([T=Float64,] dims...)
Expand Down Expand Up @@ -392,10 +395,10 @@ function ones end

for (fname, felt) in ((:zeros, :zero), (:ones, :one))
@eval begin
$fname(::Type{T}, dims::NTuple{N, Any}) where {T, N} = fill!(Array{T,N}(undef, convert(Dims, dims)::Dims), $felt(T))
$fname(dims::Tuple) = ($fname)(Float64, dims)
$fname(::Type{T}, dims...) where {T} = $fname(T, dims)
$fname(dims...) = $fname(dims)
$fname(::Type{T}, dims::NTuple{N,DimOrInd}) where {T,N} = fill!(AbstractArray{T,N}(undef, dims), $felt(T))
$fname(dims::Tuple{Vararg{DimOrInd}}) = $fname(Float64, dims)
$fname(::Type{T}, dims::DimOrInd...) where {T} = $fname(T, dims)
$fname(dims::DimOrInd...) = $fname(dims)
end
end

Expand Down
8 changes: 4 additions & 4 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ julia> falses(2,3)
false false false
```
"""
falses(dims::Dims) = fill!(BitArray(undef, dims), false)
falses(dims::Integer...) = falses(map(Int,dims))
falses(dims::Tuple{Vararg{DimOrInd}}) = fill!(AbstractArray{Bool}(undef, dims), false)
falses(dims::DimOrInd...) = falses(dims)

"""
trues(dims)
Expand All @@ -382,8 +382,8 @@ julia> trues(2,3)
true true true
```
"""
trues(dims::Dims) = fill!(BitArray(undef, dims), true)
trues(dims::Integer...) = trues(map(Int,dims))
trues(dims::Tuple{Vararg{DimOrInd}}) = fill!(AbstractArray{Bool}(undef, dims), true)
trues(dims::DimOrInd...) = trues(dims)

function one(x::BitMatrix)
m, n = size(x)
Expand Down
10 changes: 10 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,16 @@ end
@deprecate Crand Libc.rand false
@deprecate Csrand Libc.srand false

# Deprecate `similar(f, axes)`
@noinline function similar(f, shape::Tuple)
depwarn("using similar(f, shape) to call `f` with axes `shape` is deprecated; call `f` directly and/or add methods such that it supports axes", :similar)
f(to_shape(shape))
end
@noinline function similar(f, dims::DimOrInd...)
depwarn("using similar(f, shape...) to call `f` with axes `shape` is deprecated; call `f` directly and/or add methods such that it supports axes", :similar)
f(to_shape(dims))
end

@deprecate showcompact(x) show(IOContext(stdout, :compact => true), x)
@deprecate showcompact(io, x) show(IOContext(io, :compact => true), x)
@deprecate sprint(::typeof(showcompact), args...) sprint(show, args...; context=:compact => true)
Expand Down
5 changes: 2 additions & 3 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1763,10 +1763,9 @@ julia> unique(A, 3)
```
"""
@generated function unique(A::AbstractArray{T,N}, dim::Int) where {T,N}
inds = inds -> zeros(UInt, inds)
quote
1 <= dim <= $N || return copy(A)
hashes = similar($inds, axes(A, dim))
hashes = zeros(UInt, axes(A, dim))

# Compute hash for each row
k = 0
Expand All @@ -1783,7 +1782,7 @@ julia> unique(A, 3)
uniquerows = collect(values(firstrow))

# Check for collisions
collided = similar(falses, axes(A, dim))
collided = falses(axes(A, dim))
@inbounds begin
@nloops $N i A d->(if d == dim
k = i_d
Expand Down
8 changes: 4 additions & 4 deletions base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,10 @@ function _findmin(A, region)
if prod(map(length, reduced_indices(A, region))) != 0
throw(ArgumentError("collection slices must be non-empty"))
end
(similar(A, ri), similar(dims->zeros(eltype(keys(A)), dims), ri))
(similar(A, ri), zeros(eltype(keys(A)), ri))
else
findminmax!(isless, fill!(similar(A, ri), first(A)),
similar(dims->zeros(eltype(keys(A)), dims), ri), A)
zeros(eltype(keys(A)), ri), A)
end
end

Expand Down Expand Up @@ -795,10 +795,10 @@ function _findmax(A, region)
if prod(map(length, reduced_indices(A, region))) != 0
throw(ArgumentError("collection slices must be non-empty"))
end
similar(A, ri), similar(dims->zeros(eltype(keys(A)), dims), ri)
similar(A, ri), zeros(eltype(keys(A)), ri)
else
findminmax!(isgreater, fill!(similar(A, ri), first(A)),
similar(dims->zeros(eltype(keys(A)), dims), ri), A)
zeros(eltype(keys(A)), ri), A)
end
end

Expand Down
34 changes: 17 additions & 17 deletions base/stat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -282,23 +282,23 @@ operm(st::StatStruct) = UInt8((filemode(st) ) & 0x7)
# mode predicate methods for file names

for f in Symbol[
:ispath
:isfifo
:ischardev
:isdir
:isblockdev
:isfile
:issocket
:issetuid
:issetgid
:issticky
:uperm
:gperm
:operm
:filemode
:filesize
:mtime
:ctime
:ispath,
:isfifo,
:ischardev,
:isdir,
:isblockdev,
:isfile,
:issocket,
:issetuid,
:issetgid,
:issticky,
:uperm,
:gperm,
:operm,
:filemode,
:filesize,
:mtime,
:ctime,
]
@eval ($f)(path...) = ($f)(stat(path...))
end
Expand Down
4 changes: 4 additions & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ include("reinterpretarray.jl")
# type and dimensionality specified, accepting dims as series of Integers
Vector{T}(::UndefInitializer, m::Integer) where {T} = Vector{T}(undef, Int(m))
Matrix{T}(::UndefInitializer, m::Integer, n::Integer) where {T} = Matrix{T}(undef, Int(m), Int(n))
Array{T,N}(::UndefInitializer, d::Vararg{Integer,N}) where {T,N} = Array{T,N}(undef, convert(Tuple{Vararg{Int}}, d))
# type but not dimensionality specified, accepting dims as series of Integers
Array{T}(::UndefInitializer, m::Integer) where {T} = Array{T,1}(undef, Int(m))
Array{T}(::UndefInitializer, m::Integer, n::Integer) where {T} = Array{T,2}(undef, Int(m), Int(n))
Expand All @@ -163,6 +164,9 @@ Array{T}(::UndefInitializer, d::Integer...) where {T} = Array{T}(undef, convert(
# dimensionality but not type specified, accepting dims as series of Integers
Vector(::UndefInitializer, m::Integer) = Vector{Any}(undef, Int(m))
Matrix(::UndefInitializer, m::Integer, n::Integer) = Matrix{Any}(undef, Int(m), Int(n))
# Dimensions as a single tuple
Array{T}(::UndefInitializer, d::NTuple{N,Integer}) where {T,N} = Array{T,N}(undef, convert(Tuple{Vararg{Int}}, d))
Array{T,N}(::UndefInitializer, d::NTuple{N,Integer}) where {T,N} = Array{T,N}(undef, convert(Tuple{Vararg{Int}}, d))
# empty vector constructor
Vector() = Vector{Any}(undef, 0)

Expand Down
6 changes: 3 additions & 3 deletions stdlib/SparseArrays/src/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1607,9 +1607,9 @@ end
# and computing reductions along columns into SparseMatrixCSC is
# non-trivial, so use Arrays for output
Base.reducedim_initarray(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} =
fill!(similar(dims->Array{R}(undef, dims), Base.reduced_indices(A,region)), v0)
fill(v0, Base.reduced_indices(A,region))
Base.reducedim_initarray0(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} =
fill!(similar(dims->Array{R}(undef, dims), Base.reduced_indices0(A,region)), v0)
fill(v0, Base.reduced_indices0(A,region))

# General mapreduce
function _mapreducezeros(f, op, ::Type{T}, nzeros::Int, v0) where T
Expand Down Expand Up @@ -1823,7 +1823,7 @@ function _findr(op, A, region, Tv)
throw(ArgumentError("array slices must be non-empty"))
else
ri = Base.reduced_indices0(A, region)
return (similar(A, ri), similar(dims->zeros(Ti, dims), ri))
return (similar(A, ri), zeros(Ti, ri))
end
end

Expand Down
9 changes: 7 additions & 2 deletions test/TestHelpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,20 @@ function Base.similar(A::AbstractArray, T::Type, inds::Tuple{UnitRange,Vararg{Un
OffsetArray(B, map(indsoffset, inds))
end

Base.similar(f::Union{Function,Type}, shape::Tuple{UnitRange,Vararg{UnitRange}}) =
OffsetArray(f(map(length, shape)), map(indsoffset, shape))
Base.similar(::Type{T}, shape::Tuple{UnitRange,Vararg{UnitRange}}) where {T<:Array} =
OffsetArray(T(undef, map(length, shape)), map(indsoffset, shape))
Base.similar(::Type{T}, shape::Tuple{UnitRange,Vararg{UnitRange}}) where {T<:BitArray} =
OffsetArray(T(undef, map(length, shape)), map(indsoffset, shape))

Base.reshape(A::AbstractArray, inds::Tuple{UnitRange,Vararg{UnitRange}}) = OffsetArray(reshape(A, map(length, inds)), map(indsoffset, inds))

Base.fill(v, inds::NTuple{N, AbstractUnitRange}) where{N} =
fill!(OffsetArray(Array{typeof(v), N}(undef, map(length, inds)), map(indsoffset, inds)), v)
Base.AbstractArray{T}(::UndefInitializer, inds::NTuple{N,AbstractUnitRange}) where {T,N} =
OffsetArray(Array{T, N}(undef, map(length, inds)), map(indsoffset, inds))
Base.AbstractArray{T,N}(::UndefInitializer, inds::NTuple{N,AbstractUnitRange}) where {T,N} =
OffsetArray(Array{T, N}(undef, map(length, inds)), map(indsoffset, inds))

@inline function Base.getindex(A::OffsetArray{T,N}, I::Vararg{Int,N}) where {T,N}
checkbounds(A, I...)
@inbounds ret = parent(A)[offset(A.offsets, I)...]
Expand Down
2 changes: 1 addition & 1 deletion test/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bitcheck(x) = true
function check_bitop_call(ret_type, func, args...; kwargs...)
r1 = func(args...; kwargs...)
r2 = func(map(x->(isa(x, BitArray) ? Array(x) : x), args)...; kwargs...)
ret_type ≢ nothing && !isa(r1, ret_type) && @show ret_type, r1
ret_type ≢ nothing && !isa(r1, ret_type) && @show ret_type, typeof(r1)
ret_type ≢ nothing && @test isa(r1, ret_type)
@test tc(r1, r2)
@test isequal(r1, ret_type ≡ nothing ? r2 : r2)
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ end

# issue #5575
f5575() = zeros(Type[Float64][1], 1)
@test Base.return_types(f5575, ())[1] == Vector
@test Base.return_types(f5575, ())[1] == Union{Vector, BitVector}

# make sure Tuple{unknown} handles the possibility that `unknown` is a Vararg
function maybe_vararg_tuple_1()
Expand Down