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

add Returns #39794

Merged
merged 17 commits into from
Apr 1, 2021
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ New library functions
* Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]).
* `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`.
* New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971])
* New function/type `Returns(value)` that creates a function, which returns `value` for any arguments ([ #39794])
jw3126 marked this conversation as resolved.
Show resolved Hide resolved
* New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)` ([#38438])

New library features
Expand Down
8 changes: 4 additions & 4 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1604,7 +1604,7 @@ _cat_size_shape(dims, shape) = shape

_cshp(ndim::Int, ::Tuple{}, ::Tuple{}, ::Tuple{}) = ()
_cshp(ndim::Int, ::Tuple{}, ::Tuple{}, nshape) = nshape
_cshp(ndim::Int, dims, ::Tuple{}, ::Tuple{}) = ntuple(b -> 1, Val(length(dims)))
_cshp(ndim::Int, dims, ::Tuple{}, ::Tuple{}) = ntuple(Returns(1), Val(length(dims)))
@inline _cshp(ndim::Int, dims, shape, ::Tuple{}) =
(shape[1] + dims[1], _cshp(ndim + 1, tail(dims), tail(shape), ())...)
@inline _cshp(ndim::Int, dims, ::Tuple{}, nshape) =
Expand Down Expand Up @@ -1810,7 +1810,7 @@ function hvcat(nbc::Integer, as...)
mod(n,nbc) != 0 &&
throw(ArgumentError("number of arrays $n is not a multiple of the requested number of block columns $nbc"))
nbr = div(n,nbc)
hvcat(ntuple(i->nbc, nbr), as...)
hvcat(ntuple(Returns(nbc), nbr), as...)
end

"""
Expand Down Expand Up @@ -2238,9 +2238,9 @@ function mapslices(f, A::AbstractArray; dims)
end
nextra = max(0, length(dims)-ndims(r1))
if eltype(Rsize) == Int
Rsize[dims] = [size(r1)..., ntuple(d->1, nextra)...]
Rsize[dims] = [size(r1)..., ntuple(Returns(1), nextra)...]
else
Rsize[dims] = [axes(r1)..., ntuple(d->OneTo(1), nextra)...]
Rsize[dims] = [axes(r1)..., ntuple(Returns(OneTo(1)), nextra)...]
end
R = similar(r1, tuple(Rsize...,))

Expand Down
8 changes: 4 additions & 4 deletions base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ julia> selectdim(A, 2, 3)
@noinline function _selectdim(A, d, i, idxs)
d >= 1 || throw(ArgumentError("dimension must be ≥ 1, got $d"))
nd = ndims(A)
d > nd && (i == 1 || throw(BoundsError(A, (ntuple(k->Colon(),d-1)..., i))))
d > nd && (i == 1 || throw(BoundsError(A, (ntuple(Returns(Colon()),d-1)..., i))))
return view(A, idxs...)
end

Expand Down Expand Up @@ -225,7 +225,7 @@ function repeat(A::AbstractArray, counts...)
end

"""
repeat(A::AbstractArray; inner=ntuple(x->1, ndims(A)), outer=ntuple(x->1, ndims(A)))
repeat(A::AbstractArray; inner=ntuple(Returns(1), ndims(A)), outer=ntuple(Returns(1), ndims(A)))

Construct an array by repeating the entries of `A`. The i-th element of `inner` specifies
the number of times that the individual entries of the i-th dimension of `A` should be
Expand Down Expand Up @@ -491,7 +491,7 @@ julia> collect(eachslice(M, dims=2))
length(dims) == 1 || throw(ArgumentError("only single dimensions are supported"))
dim = first(dims)
dim <= ndims(A) || throw(DimensionMismatch("A doesn't have $dim dimensions"))
inds_before = ntuple(d->(:), dim-1)
inds_after = ntuple(d->(:), ndims(A)-dim)
inds_before = ntuple(Returns(:), dim-1)
inds_after = ntuple(Returns(:), ndims(A)-dim)
return (view(A, inds_before..., i, inds_after...) for i in axes(A, dim))
end
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1734,7 +1734,7 @@ function vcat(arrays::Vector{T}...) where T
return arr
end

_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(x->1, n-1)..., length(x)))
_cat(n::Integer, x::Integer...) = reshape([x...], (ntuple(Returns(1), n-1)..., length(x)))

## find ##

Expand Down
2 changes: 1 addition & 1 deletion base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ function iterate(d::ImmutableDict{K,V}, t=d) where {K, V}
!isdefined(t, :parent) && return nothing
(Pair{K,V}(t.key, t.value), t.parent)
end
length(t::ImmutableDict) = count(x->true, t)
length(t::ImmutableDict) = count(Returns(true), t)
isempty(t::ImmutableDict) = !isdefined(t, :parent)
empty(::ImmutableDict, ::Type{K}, ::Type{V}) where {K, V} = ImmutableDict{K,V}()

Expand Down
2 changes: 1 addition & 1 deletion base/env.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ variable may result in an uppercase `ENV` key.)
const ENV = EnvDict()

getindex(::EnvDict, k::AbstractString) = access_env(k->throw(KeyError(k)), k)
get(::EnvDict, k::AbstractString, def) = access_env(k->def, k)
get(::EnvDict, k::AbstractString, def) = access_env(Returns(def), k)
get(f::Callable, ::EnvDict, k::AbstractString) = access_env(k->f(), k)
in(k::AbstractString, ::KeySet{String, EnvDict}) = _hasenv(k)
pop!(::EnvDict, k::AbstractString) = (v = ENV[k]; _unsetenv(k); v)
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export
Rational,
Regex,
RegexMatch,
Returns,
RoundFromZero,
RoundDown,
RoundingMode,
Expand Down
12 changes: 6 additions & 6 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ module IteratorsMD

# zeros and ones
zero(::CartesianIndex{N}) where {N} = zero(CartesianIndex{N})
zero(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 0, Val(N)))
zero(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(Returns(0), Val(N)))
oneunit(::CartesianIndex{N}) where {N} = oneunit(CartesianIndex{N})
oneunit(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 1, Val(N)))
oneunit(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(Returns(1), Val(N)))

# arithmetic, min/max
@inline (-)(index::CartesianIndex{N}) where {N} =
Expand Down Expand Up @@ -457,7 +457,7 @@ module IteratorsMD

# Split out the first N elements of a tuple
@inline function split(t, V::Val)
ref = ntuple(d->true, V) # create a reference tuple of length N
ref = ntuple(Returns(true), V) # create a reference tuple of length N
_split1(t, ref), _splitrest(t, ref)
end
@inline _split1(t, ref) = (t[1], _split1(tail(t), tail(ref))...)
Expand Down Expand Up @@ -684,10 +684,10 @@ checkindex(::Type{Bool}, inds::Tuple, I::CartesianIndices) = all(checkindex.(Boo
# rather than returning N, it returns an NTuple{N,Bool} so the result is inferrable
@inline index_ndims(i1, I...) = (true, index_ndims(I...)...)
@inline function index_ndims(i1::CartesianIndex, I...)
(map(x->true, i1.I)..., index_ndims(I...)...)
(map(Returns(true), i1.I)..., index_ndims(I...)...)
end
@inline function index_ndims(i1::AbstractArray{CartesianIndex{N}}, I...) where N
(ntuple(x->true, Val(N))..., index_ndims(I...)...)
(ntuple(Returns(true), Val(N))..., index_ndims(I...)...)
end
index_ndims() = ()

Expand All @@ -697,7 +697,7 @@ index_ndims() = ()
@inline index_dimsum(::Colon, I...) = (true, index_dimsum(I...)...)
@inline index_dimsum(::AbstractArray{Bool}, I...) = (true, index_dimsum(I...)...)
@inline function index_dimsum(::AbstractArray{<:Any,N}, I...) where N
(ntuple(x->true, Val(N))..., index_dimsum(I...)...)
(ntuple(Returns(true), Val(N))..., index_dimsum(I...)...)
end
index_dimsum() = ()

Expand Down
36 changes: 36 additions & 0 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,42 @@ julia> [1:5;] |> x->x.^2 |> sum |> inv
"""
|>(x, f) = f(x)

"""
f = Returns(value)

Create a callable `f` such that `f(args...; kw...) === value` holds.

# Examples

```jldoctest
julia> f = Returns(42);

julia> f(1)
42

julia> f("hello", x=32)
42

julia> f.value
42
```

!!! compat "Julia 1.7"
Returns requires at least Julia 1.7.
"""
struct Returns{V} <: Function
value::V
Returns{V}(value) where {V} = new{V}(value)
Returns(value) = new{Core.Typeof(value)}(value)
end

(obj::Returns)(args...; kw...) = obj.value
function show(io::IO, obj::Returns)
show(io, typeof(obj))
print(io, "(")
show(io, obj.value)
print(io, ")")
end
# function composition

"""
Expand Down
2 changes: 1 addition & 1 deletion base/reshapedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ end
# product of trailing dims into the last element
rdims_trailing(l, inds...) = length(l) * rdims_trailing(inds...)
rdims_trailing(l) = length(l)
rdims(out::Val{N}, inds::Tuple) where {N} = rdims(ntuple(i -> OneTo(1), Val(N)), inds)
rdims(out::Val{N}, inds::Tuple) where {N} = rdims(ntuple(Returns(OneTo(1)), Val(N)), inds)
rdims(out::Tuple{}, inds::Tuple{}) = () # N == 0, M == 0
rdims(out::Tuple{}, inds::Tuple{Any}) = ()
rdims(out::Tuple{}, inds::NTuple{M,Any}) where {M} = ()
Expand Down
1 change: 1 addition & 0 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function show(io::IO, ::MIME"text/plain", f::Function)
end

show(io::IO, ::MIME"text/plain", c::ComposedFunction) = show(io, c)
show(io::IO, ::MIME"text/plain", c::Returns) = show(io, c)

function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator})
isempty(iter) && get(io, :compact, false) && return show(io, iter)
Expand Down
16 changes: 8 additions & 8 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,10 @@ function test_scalar_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where
B = T(A)
@test A == B
# Test indexing up to 5 dimensions
trailing5 = CartesianIndex(ntuple(x->1, max(ndims(B)-5, 0)))
trailing4 = CartesianIndex(ntuple(x->1, max(ndims(B)-4, 0)))
trailing3 = CartesianIndex(ntuple(x->1, max(ndims(B)-3, 0)))
trailing2 = CartesianIndex(ntuple(x->1, max(ndims(B)-2, 0)))
trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0)))
trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0)))
trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0)))
trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0)))
i=0
for i5 = 1:size(B, 5)
for i4 = 1:size(B, 4)
Expand Down Expand Up @@ -419,10 +419,10 @@ function test_vector_indexing(::Type{T}, shape, ::Type{TestAbstractArray}) where
N = prod(shape)
A = reshape(Vector(1:N), shape)
B = T(A)
trailing5 = CartesianIndex(ntuple(x->1, max(ndims(B)-5, 0)))
trailing4 = CartesianIndex(ntuple(x->1, max(ndims(B)-4, 0)))
trailing3 = CartesianIndex(ntuple(x->1, max(ndims(B)-3, 0)))
trailing2 = CartesianIndex(ntuple(x->1, max(ndims(B)-2, 0)))
trailing5 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-5, 0)))
trailing4 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-4, 0)))
trailing3 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-3, 0)))
trailing2 = CartesianIndex(ntuple(Returns(1), max(ndims(B)-2, 0)))
idxs = rand(1:N, 3, 3, 3)
@test B[idxs] == A[idxs] == idxs
@test B[vec(idxs)] == A[vec(idxs)] == vec(idxs)
Expand Down
24 changes: 12 additions & 12 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1153,17 +1153,17 @@ end
# issue #5177

c = fill(1,2,3,4)
m1 = mapslices(x-> fill(1,2,3), c, dims=[1,2])
m2 = mapslices(x-> fill(1,2,4), c, dims=[1,3])
m3 = mapslices(x-> fill(1,3,4), c, dims=[2,3])
m1 = mapslices(Returns(fill(1,2,3)), c, dims=[1,2])
m2 = mapslices(Returns(fill(1,2,4)), c, dims=[1,3])
m3 = mapslices(Returns(fill(1,3,4)), c, dims=[2,3])
@test size(m1) == size(m2) == size(m3) == size(c)

n1 = mapslices(x-> fill(1,6), c, dims=[1,2])
n2 = mapslices(x-> fill(1,6), c, dims=[1,3])
n3 = mapslices(x-> fill(1,6), c, dims=[2,3])
n1a = mapslices(x-> fill(1,1,6), c, dims=[1,2])
n2a = mapslices(x-> fill(1,1,6), c, dims=[1,3])
n3a = mapslices(x-> fill(1,1,6), c, dims=[2,3])
n1 = mapslices(Returns(fill(1,6) ), c, dims=[1,2])
n2 = mapslices(Returns(fill(1,6) ), c, dims=[1,3])
n3 = mapslices(Returns(fill(1,6) ), c, dims=[2,3])
n1a = mapslices(Returns(fill(1,1,6)), c, dims=[1,2])
n2a = mapslices(Returns(fill(1,1,6)), c, dims=[1,3])
n3a = mapslices(Returns(fill(1,1,6)), c, dims=[2,3])
jw3126 marked this conversation as resolved.
Show resolved Hide resolved
@test size(n1a) == (1,6,4) && size(n2a) == (1,3,6) && size(n3a) == (2,1,6)
@test size(n1) == (6,1,4) && size(n2) == (6,3,1) && size(n3) == (2,6,1)

Expand Down Expand Up @@ -1659,7 +1659,7 @@ end
Nmax = 3 # TODO: go up to CARTESIAN_DIMS+2 (currently this exposes problems)
for N = 1:Nmax
#indexing with (UnitRange, UnitRange, UnitRange)
args = ntuple(d->UnitRange{Int}, N)
args = ntuple(Returns(UnitRange{Int}), N)
@test Base.return_types(getindex, Tuple{Array{Float32, N}, args...}) == [Array{Float32, N}]
@test Base.return_types(getindex, Tuple{BitArray{N}, args...}) == Any[BitArray{N}]
@test Base.return_types(setindex!, Tuple{Array{Float32, N}, Array{Int, 1}, args...}) == [Array{Float32, N}]
Expand Down Expand Up @@ -1786,7 +1786,7 @@ end
@test mdsum(A) == 15
@test mdsum2(A) == 15
AA = reshape(aa, tuple(2, shp...))
B = view(AA, 1:1, ntuple(i->Colon(), i)...)
B = view(AA, 1:1, ntuple(Returns(:), i)...)
@test isa(Base.IndexStyle(B), Base.IteratorsMD.IndexCartesian)
@test mdsum(B) == 15
@test mdsum2(B) == 15
Expand All @@ -1799,7 +1799,7 @@ end
A = reshape(a, tuple(shp...))
@test mdsum(A) == 55
@test mdsum2(A) == 55
B = view(A, ntuple(i->Colon(), i)...)
B = view(A, ntuple(Returns(:), i)...)
@test mdsum(B) == 55
@test mdsum2(B) == 55
insert!(shp, 2, 1)
Expand Down
54 changes: 28 additions & 26 deletions test/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1180,8 +1180,8 @@ timesofar("datamove")

@check_bit_operation findfirst(x->x, b1) Union{Int,Nothing}
@check_bit_operation findfirst(x->!x, b1) Union{Int,Nothing}
@check_bit_operation findfirst(x->true, b1) Union{Int,Nothing}
@check_bit_operation findfirst(x->false, b1) Union{Int,Nothing}
@check_bit_operation findfirst(Returns(true ), b1) Union{Int,Nothing}
@check_bit_operation findfirst(Returns(false), b1) Union{Int,Nothing}

@check_bit_operation findall(b1) Vector{Int}
end
Expand Down Expand Up @@ -1275,49 +1275,51 @@ timesofar("find")
@test_throws BoundsError findprevnot(b2, 1001)
@test_throws BoundsError findprev(!, b2, 1001)
@test_throws BoundsError findprev(identity, b1, 1001)
@test_throws BoundsError findprev(x->false, b1, 1001)
@test_throws BoundsError findprev(x->true, b1, 1001)
@test_throws BoundsError findprev(Returns(false), b1, 1001)
@test_throws BoundsError findprev(Returns(true ), b1, 1001)
@test findprev(b1, 1000) == findprevnot(b2, 1000) == findprev(!, b2, 1000) == 777
@test findprev(b1, 777) == findprevnot(b2, 777) == findprev(!, b2, 777) == 777
@test findprev(b1, 776) == findprevnot(b2, 776) == findprev(!, b2, 776) == 77
@test findprev(b1, 77) == findprevnot(b2, 77) == findprev(!, b2, 77) == 77
@test findprev(b1, 76) == findprevnot(b2, 76) == findprev(!, b2, 76) == nothing
@test findprev(b1, -1) == findprevnot(b2, -1) == findprev(!, b2, -1) == nothing
@test findprev(identity, b1, -1) == findprev(x->false, b1, -1) == findprev(x->true, b1, -1) == nothing
@test findprev(identity, b1, -1) == nothing
@test findprev(Returns(false), b1, -1) == nothing
@test findprev(Returns(true), b1, -1) == nothing
@test_throws BoundsError findnext(b1, -1)
@test_throws BoundsError findnextnot(b2, -1)
@test_throws BoundsError findnext(!, b2, -1)
@test_throws BoundsError findnext(identity, b1, -1)
@test_throws BoundsError findnext(x->false, b1, -1)
@test_throws BoundsError findnext(x->true, b1, -1)
@test_throws BoundsError findnext(Returns(false), b1, -1)
@test_throws BoundsError findnext(Returns(true), b1, -1)
@test findnext(b1, 1) == findnextnot(b2, 1) == findnext(!, b2, 1) == 77
@test findnext(b1, 77) == findnextnot(b2, 77) == findnext(!, b2, 77) == 77
@test findnext(b1, 78) == findnextnot(b2, 78) == findnext(!, b2, 78) == 777
@test findnext(b1, 777) == findnextnot(b2, 777) == findnext(!, b2, 777) == 777
@test findnext(b1, 778) == findnextnot(b2, 778) == findnext(!, b2, 778) == nothing
@test findnext(b1, 1001) == findnextnot(b2, 1001) == findnext(!, b2, 1001) == nothing
@test findnext(identity, b1, 1001) == findnext(x->false, b1, 1001) == findnext(x->true, b1, 1001) == nothing
@test findnext(identity, b1, 1001) == findnext(Returns(false), b1, 1001) == findnext(Returns(true), b1, 1001) == nothing

@test findlast(b1) == Base.findlastnot(b2) == 777
@test findfirst(b1) == Base.findfirstnot(b2) == 77

b0 = BitVector()
@test findprev(x->true, b0, -1) == nothing
@test_throws BoundsError findprev(x->true, b0, 1)
@test_throws BoundsError findnext(x->true, b0, -1)
@test findnext(x->true, b0, 1) == nothing
@test findprev(Returns(true), b0, -1) == nothing
@test_throws BoundsError findprev(Returns(true), b0, 1)
@test_throws BoundsError findnext(Returns(true), b0, -1)
@test findnext(Returns(true), b0, 1) == nothing

b1 = falses(10)
@test findprev(x->true, b1, 5) == 5
@test findnext(x->true, b1, 5) == 5
@test findprev(x->true, b1, -1) == nothing
@test findnext(x->true, b1, 11) == nothing
@test findprev(x->false, b1, 5) == nothing
@test findnext(x->false, b1, 5) == nothing
@test findprev(x->false, b1, -1) == nothing
@test findnext(x->false, b1, 11) == nothing
@test_throws BoundsError findprev(x->true, b1, 11)
@test_throws BoundsError findnext(x->true, b1, -1)
@test findprev(Returns(true), b1, 5) == 5
@test findnext(Returns(true), b1, 5) == 5
@test findprev(Returns(true), b1, -1) == nothing
@test findnext(Returns(true), b1, 11) == nothing
@test findprev(Returns(false), b1, 5) == nothing
@test findnext(Returns(false), b1, 5) == nothing
@test findprev(Returns(false), b1, -1) == nothing
@test findnext(Returns(false), b1, 11) == nothing
@test_throws BoundsError findprev(Returns(true), b1, 11)
@test_throws BoundsError findnext(Returns(true), b1, -1)

@testset "issue 32568" for T = (UInt, BigInt)
for x = (1, 2)
Expand Down Expand Up @@ -1382,8 +1384,8 @@ timesofar("reductions")
b2 = bitrand(l)
@test map(~, b1) == map(x->~x, b1) == broadcast(~, b1)
@test map(identity, b1) == map(x->x, b1) == b1
@test map(zero, b1) == map(x->false, b1) == falses(l)
@test map(one, b1) == map(x->true, b1) == trues(l)
@test map(zero, b1) == map(Returns(false), b1) == falses(l)
@test map(one, b1) == map(Returns(true), b1) == trues(l)

@test map(&, b1, b2) == map((x,y)->x&y, b1, b2) == broadcast(&, b1, b2)
@test map(|, b1, b2) == map((x,y)->x|y, b1, b2) == broadcast(|, b1, b2)
Expand All @@ -1407,8 +1409,8 @@ timesofar("reductions")
@test map!(~, b, b1) == map!(x->~x, b, b1) == broadcast(~, b1) == b
@test map!(!, b, b1) == map!(x->!x, b, b1) == broadcast(~, b1) == b
@test map!(identity, b, b1) == map!(x->x, b, b1) == b1 == b
@test map!(zero, b, b1) == map!(x->false, b, b1) == falses(l) == b
@test map!(one, b, b1) == map!(x->true, b, b1) == trues(l) == b
@test map!(zero, b, b1) == map!(Returns(false), b, b1) == falses(l) == b
@test map!(one, b, b1) == map!(Returns(true), b, b1) == trues(l) == b

@test map!(&, b, b1, b2) == map!((x,y)->x&y, b, b1, b2) == broadcast(&, b1, b2) == b
@test map!(|, b, b1, b2) == map!((x,y)->x|y, b, b1, b2) == broadcast(|, b1, b2) == b
Expand Down
Loading