diff --git a/NEWS.md b/NEWS.md index 0d440d9c8e893..a3366ca1d1c6f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,15 +36,15 @@ New library functions * `readdir` output is now guaranteed to be sorted. The `sort` keyword allows opting out of sorting to get names in OS-native order ([#33542]). * The new `only(x)` function returns the one-and-only element of a collection `x`, and throws an `ArgumentError` if `x` contains zero or multiple elements. ([#33129]) * `takewhile` and `dropwhile` have been added to the Iterators submodule ([#33437]). +* `filter` can now act on a `Tuple` ([#32968]). * There is a now an `evalpoly` (generated) function meant to take the role of the `@evalpoly` macro. The function is just as efficient as the macro while giving added flexibility, so it should be preferred over `@evalpoly`. `evalpoly` takes a list of coefficients as a tuple, so where one might write `@evalpoly(x, p1, p2, p3)` one would instead write `evalpoly(x, (p1, p2, p3))`. + Standard library changes ------------------------ * The methods of `mktemp` and `mktempdir` which take a function body to pass temporary paths to no longer throw errors if the path is already deleted when the function body returns ([#33091]). - * `div` now accepts a rounding mode as the third argument, consistent with the corresponding argument to `rem`. Support for rounding division, by passing one of the RoundNearest modes to this function, was added. For future compatibility, library authors should now extend this function, rather than extending the two-argument `fld`/`cld`/`div` directly. ([#33040]) - * Verbose `display` of `Char` (`text/plain` output) now shows the codepoint value in standard-conforming `"U+XXXX"` format ([#33291]). * `Iterators.partition` now uses views (or smartly re-computed ranges) for partitions of all `AbstractArray`s ([#33533]). diff --git a/base/tuple.jl b/base/tuple.jl index a9bfe7b10120d..e18620fd62f3a 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -270,6 +270,13 @@ _totuple(::Type{Tuple}, itr, s...) = (collect(Iterators.rest(itr,s...))...,) end +## filter ## + +filter(f, xs::Tuple) = afoldl((ys, x) -> f(x) ? (ys..., x) : ys, (), xs...) + +# use Array for long tuples +filter(f, t::Any16) = Tuple(filter(f, collect(t))) + ## comparison ## isequal(t1::Tuple, t2::Tuple) = (length(t1) == length(t2)) && _isequal(t1, t2) diff --git a/test/tuple.jl b/test/tuple.jl index 0b017b18f5752..2d1e525302a4d 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -254,6 +254,16 @@ end @test_throws ArgumentError mapfoldl(abs, =>, ()) end +@testset "filter" begin + @test filter(isodd, (1,2,3)) == (1, 3) + @test filter(isequal(2), (true, 2.0, 3)) === (2.0,) + @test filter(i -> true, ()) == () + @test filter(identity, (true,)) === (true,) + longtuple = ntuple(identity, 20) + @test filter(iseven, longtuple) == ntuple(i->2i, 10) + @test filter(x -> x<2, (longtuple..., 1.5)) === (1, 1.5) +end + @testset "comparison and hash" begin @test isequal((), ()) @test isequal((1,2,3), (1,2,3))