From 7623da0643887114884f9ded976e864f8836a91e Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Thu, 29 Dec 2022 12:45:29 +0100 Subject: [PATCH] Don't deprecate splat Keep the splat function and mention in the documentation that it's the recommended way of constructing a Base.Splat object. --- NEWS.md | 5 ++- base/deprecated.jl | 2 -- base/exports.jl | 2 +- base/iterators.jl | 2 +- base/operators.jl | 37 +++++++++++++++-------- base/strings/search.jl | 4 +-- doc/src/base/base.md | 2 +- doc/src/devdocs/ast.md | 2 +- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 2 +- stdlib/LinearAlgebra/src/qr.jl | 2 +- test/broadcast.jl | 4 +-- test/compiler/inference.jl | 2 +- test/iterators.jl | 2 +- 13 files changed, 39 insertions(+), 29 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2320f5af907a55..a16e45ac65ab14 100644 --- a/NEWS.md +++ b/NEWS.md @@ -65,8 +65,6 @@ New library functions --------------------- * New function `Iterators.flatmap` ([#44792]). -* New helper `Splat(f)` which acts like `x -> f(x...)`, with pretty printing for - inspecting which function `f` was originally wrapped ([#42717]). * New `pkgversion(m::Module)` function to get the version of the package that loaded a given module, similar to `pkgdir(m::Module)` ([#45607]). * New function `stack(x)` which generalises `reduce(hcat, x::Vector{<:Vector})` to any dimensionality, @@ -95,6 +93,8 @@ Standard library changes * `@kwdef` is now exported and added to the public API ([#46273]). * An issue with order of operations in `fld1` is now fixed ([#28973]). * Sorting is now always stable by default, as `QuickSort` was stabilized ([#45222]). +* `Base.splat` is now exported. The return value is now a `Base.Splat` instead + of an anonymous function, which allows for pretty printing ([#42717]). #### Package Manager @@ -182,7 +182,6 @@ Standard library changes Deprecated or removed --------------------- -* Unexported `splat` is deprecated in favor of exported `Splat`, which has pretty printing of the wrapped function ([#42717]). External dependencies --------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index 6953cd600cacd7..79ae852ff22b12 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -318,8 +318,6 @@ const var"@_noinline_meta" = var"@noinline" # BEGIN 1.9 deprecations -@deprecate splat(x) Splat(x) false - # We'd generally like to avoid direct external access to internal fields # Core.Compiler.is_inlineable and Core.Compiler.set_inlineable! move towards this direction, # but we need to keep these around for compat diff --git a/base/exports.jl b/base/exports.jl index 266a4aa8038fb3..600b36b6c37c6f 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -816,7 +816,7 @@ export atreplinit, exit, ntuple, - Splat, + splat, # I/O and events close, diff --git a/base/iterators.jl b/base/iterators.jl index 8cf92aac8ff405..c4efce3c2b0efc 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -342,7 +342,7 @@ the `zip` iterator is a tuple of values of its subiterators. `zip()` with no arguments yields an infinite iterator of empty tuples. -See also: [`enumerate`](@ref), [`Splat`](@ref Base.Splat). +See also: [`enumerate`](@ref), [`Base.splat`](@ref). # Examples ```jldoctest diff --git a/base/operators.jl b/base/operators.jl index 81d575ec7e7a1c..99a2bbb9d3be3d 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -997,7 +997,7 @@ Represents the composition of two callable objects `outer::Outer` and `inner::In ```julia ComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...)) ``` -The preferred way to construct instance of `ComposedFunction` is to use the composition operator [`∘`](@ref): +The preferred way to construct an instance of `ComposedFunction` is to use the composition operator [`∘`](@ref): ```jldoctest julia> sin ∘ cos === ComposedFunction(sin, cos) true @@ -1212,41 +1212,54 @@ used to implement specialized methods. <(x) = Fix2(<, x) """ - Splat(f) + splat(f) Equivalent to ```julia my_splat(f) = args->f(args...) ``` i.e. given a function returns a new function that takes one argument and splats -its argument into the original function. This is useful as an adaptor to pass -a multi-argument function in a context that expects a single argument, but -passes a tuple as that single argument. Additionally has pretty printing. - -!!! compat "Julia 1.9" - This function was introduced in Julia 1.9, replacing `Base.splat(f)`. +it into the original function. This is useful as an adaptor to pass a +multi-argument function in a context that expects a single argument, but passes +a tuple as that single argument. # Example usage: ```jldoctest -julia> map(Base.Splat(+), zip(1:3,4:6)) +julia> map(splat(+), zip(1:3,4:6)) 3-element Vector{Int64}: 5 7 9 -julia> my_add = Base.Splat(+) -Splat(+) +julia> my_add = splat(+) +splat(+) julia> my_add((1,2,3)) 6 ``` """ +splat(f) = Splat(f) + +""" + Base.Splat{F} <: Function + +Represents a splatted function. That is +```julia +Base.Splat(f)(args) === f(args...) +``` +The preferred way to construct an instance of `Base.Splat` is to use the [`splat`](@ref) function. + +!!! compat "Julia 1.9" + Splat requires at least Julia 1.9. In earlier versions `splat` returns an anonymous function instead. + +See also [`splat`](@ref). +""" struct Splat{F} <: Function f::F Splat(f) = new{Core.Typeof(f)}(f) end (s::Splat)(args) = s.f(args...) -print(io::IO, s::Splat) = print(io, "Splat(", s.f, ')') +print(io::IO, s::Splat) = print(io, "splat(", s.f, ')') show(io::IO, s::Splat) = print(io, s) ## in and related operators diff --git a/base/strings/search.jl b/base/strings/search.jl index eade1fbe74158e..032aa8257b26da 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -189,7 +189,7 @@ function _searchindex(s::Union{AbstractString,ByteArray}, if i === nothing return 0 end ii = nextind(s, i)::Int a = Iterators.Stateful(trest) - matched = all(Splat(==), zip(SubString(s, ii), a)) + matched = all(splat(==), zip(SubString(s, ii), a)) (isempty(a) && matched) && return i i = ii end @@ -506,7 +506,7 @@ function _rsearchindex(s::AbstractString, a = Iterators.Stateful(trest) b = Iterators.Stateful(Iterators.reverse( pairs(SubString(s, 1, ii)))) - matched = all(Splat(==), zip(a, (x[2] for x in b))) + matched = all(splat(==), zip(a, (x[2] for x in b))) if matched && isempty(a) isempty(b) && return firstindex(s) return nextind(s, popfirst!(b)[1])::Int diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 704a0ff9fe2f11..f01dab2a5d1de4 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -258,7 +258,7 @@ new Base.:(|>) Base.:(∘) Base.ComposedFunction -Base.Splat +Base.splat Base.Fix1 Base.Fix2 ``` diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 1978cd19a9a793..9ada683b1ddb0b 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -425,7 +425,7 @@ These symbols appear in the `head` field of [`Expr`](@ref)s in lowered form. * `splatnew` Similar to `new`, except field values are passed as a single tuple. Works similarly to - `Base.Splat(new)` if `new` were a first-class function, hence the name. + `splat(new)` if `new` were a first-class function, hence the name. * `isdefined` diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 0cb6307079f64c..624cca69b84d98 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -18,7 +18,7 @@ import Base: USE_BLAS64, abs, acos, acosh, acot, acoth, acsc, acsch, adjoint, as vec, zero using Base: IndexLinear, promote_eltype, promote_op, promote_typeof, @propagate_inbounds, reduce, typed_hvcat, typed_vcat, require_one_based_indexing, - Splat + splat using Base.Broadcast: Broadcasted, broadcasted using Base.PermutedDimsArrays: CommutativeOps using OpenBLAS_jll diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 5000c3f2187a6b..1de2c2edadf993 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -159,7 +159,7 @@ function Base.hash(F::QRCompactWY, h::UInt) return hash(F.factors, foldr(hash, _triuppers_qr(F.T); init=hash(QRCompactWY, h))) end function Base.:(==)(A::QRCompactWY, B::QRCompactWY) - return A.factors == B.factors && all(Splat(==), zip(_triuppers_qr.((A.T, B.T))...)) + return A.factors == B.factors && all(splat(==), zip(_triuppers_qr.((A.T, B.T))...)) end function Base.isequal(A::QRCompactWY, B::QRCompactWY) return isequal(A.factors, B.factors) && all(zip(_triuppers_qr.((A.T, B.T))...)) do (a, b) diff --git a/test/broadcast.jl b/test/broadcast.jl index 1893acc8c11496..1333ec5f9a9a1d 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -903,13 +903,13 @@ end ys = 1:2:20 bc = Broadcast.instantiate(Broadcast.broadcasted(*, xs, ys)) @test IndexStyle(bc) == IndexLinear() - @test sum(bc) == mapreduce(Base.Splat(*), +, zip(xs, ys)) + @test sum(bc) == mapreduce(Base.splat(*), +, zip(xs, ys)) xs2 = reshape(xs, 1, :) ys2 = reshape(ys, 1, :) bc = Broadcast.instantiate(Broadcast.broadcasted(*, xs2, ys2)) @test IndexStyle(bc) == IndexCartesian() - @test sum(bc) == mapreduce(Base.Splat(*), +, zip(xs, ys)) + @test sum(bc) == mapreduce(Base.splat(*), +, zip(xs, ys)) xs = 1:5:3*5 ys = 1:4:3*4 diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 3e10d75bb2fe72..e09fa500248d00 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2892,7 +2892,7 @@ j30385(T, y) = k30385(f30385(T, y)) @test @inferred(j30385(:dummy, 1)) == "dummy" @test Base.return_types(Tuple, (NamedTuple{<:Any,Tuple{Any,Int}},)) == Any[Tuple{Any,Int}] -@test Base.return_types(Base.Splat(tuple), (typeof((a=1,)),)) == Any[Tuple{Int}] +@test Base.return_types(Base.splat(tuple), (typeof((a=1,)),)) == Any[Tuple{Int}] # test that return_type_tfunc isn't affected by max_methods differently than return_type _rttf_test(::Int8) = 0 diff --git a/test/iterators.jl b/test/iterators.jl index 9132c7b8a23a84..d8523b33a2ec1c 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -612,7 +612,7 @@ end @test length(I) == iterate_length(I) == simd_iterate_length(I) == simd_trip_count(I) @test collect(I) == iterate_elements(I) == simd_iterate_elements(I) == index_elements(I) end - @test all(Base.Splat(==), zip(Iterators.flatten(map(collect, P)), iter)) + @test all(Base.splat(==), zip(Iterators.flatten(map(collect, P)), iter)) end end @testset "empty/invalid partitions" begin