From ee98578dbdaf55c397cb40c07bad0377fb46da20 Mon Sep 17 00:00:00 2001 From: Carsten Bauer Date: Mon, 9 Mar 2020 17:10:29 +0100 Subject: [PATCH 1/3] curried versions of endswith and startswith --- base/strings/util.jl | 22 ++++++++++++++++++++ test/strings/basic.jl | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/base/strings/util.jl b/base/strings/util.jl index c84cbf1cb82c3..5475057e2a63d 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -70,6 +70,28 @@ function endswith(a::Union{String, SubString{String}}, end end +""" + endswith(suffix) + +Create a function that checks whether its argument ends with `suffix`, i.e. +a function equivalent to `y -> endswith(y, suffix)`. + +The returned function is of type `Base.Fix2{typeof(endswith)}`, which can be +used to implement specialized methods. +""" +endswith(s) = Base.Fix2(endswith, s) + +""" + startswith(prefix) + +Create a function that checks whether its argument starts with `prefix`, i.e. +a function equivalent to `y -> startswith(y, prefix)`. + +The returned function is of type `Base.Fix2{typeof(startswith)}`, which can be +used to implement specialized methods. +""" +startswith(s) = Base.Fix2(startswith, s) + """ chop(s::AbstractString; head::Integer = 0, tail::Integer = 1) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index d2be061b52d70..753c939f795ee 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -51,71 +51,119 @@ end @testset "{starts,ends}with" begin @test startswith("abcd", 'a') + @test startswith('a')("abcd") @test startswith("abcd", "a") + @test startswith("a")("abcd") @test startswith("abcd", "ab") + @test startswith("ab")("abcd") @test !startswith("ab", "abcd") + @test !startswith("abcd")("ab") @test !startswith("abcd", "bc") + @test !startswith("bc")("abcd") @test endswith("abcd", 'd') + @test endswith('d')("abcd") @test endswith("abcd", "d") + @test endswith("d")("abcd") @test endswith("abcd", "cd") + @test endswith("cd")("abcd") @test !endswith("abcd", "dc") + @test !endswith("dc")("abcd") @test !endswith("cd", "abcd") + @test !endswith("abcd")("cd") @test startswith("ab\0cd", "ab\0c") + @test startswith("ab\0c")("ab\0cd") @test !startswith("ab\0cd", "ab\0d") + @test !startswith("ab\0d")("ab\0cd") x = "∀" y = String(codeunits(x)[1:2]) z = String(codeunits(x)[1:1]) @test !startswith(x, y) + @test !startswith(y)(x) @test !startswith(x, z) + @test !startswith(z)(x) @test !startswith(y, z) + @test !startswith(z)(y) @test startswith(x, x) + @test startswith(x)(x) @test startswith(y, y) + @test startswith(y)(y) @test startswith(z, z) + @test startswith(z)(z) x = SubString(x) y = SubString(y) z = SubString(z) @test !startswith(x, y) + @test !startswith(y)(x) @test !startswith(x, z) + @test !startswith(z)(x) @test !startswith(y, z) + @test !startswith(z)(y) @test startswith(x, x) + @test startswith(x)(x) @test startswith(y, y) + @test startswith(y)(y) @test startswith(z, z) + @test startswith(z)(z) x = "x∀y" y = SubString("x\xe2\x88y", 1, 2) z = SubString("x\xe2y", 1, 2) @test !startswith(x, y) + @test !startswith(y)(x) @test !startswith(x, z) + @test !startswith(z)(x) @test !startswith(y, z) + @test !startswith(z)(y) @test startswith(x, x) + @test startswith(x)(x) @test startswith(y, y) + @test startswith(y)(y) @test startswith(z, z) + @test startswith(z)(z) x = "∀" y = String(codeunits(x)[2:3]) z = String(codeunits(x)[3:3]) @test !endswith(x, y) + @test !endswith(y)(x) @test !endswith(x, z) + @test !endswith(z)(x) @test endswith(y, z) + @test endswith(z)(y) @test endswith(x, x) + @test endswith(x)(x) @test endswith(y, y) + @test endswith(y)(y) @test endswith(z, z) + @test endswith(z)(z) x = SubString(x) y = SubString(y) z = SubString(z) @test !endswith(x, y) + @test !endswith(y)(x) @test !endswith(x, z) + @test !endswith(z)(x) @test endswith(y, z) + @test endswith(z)(y) @test endswith(x, x) + @test endswith(x)(x) @test endswith(y, y) + @test endswith(y)(y) @test endswith(z, z) + @test endswith(z)(z) x = "x∀y" y = SubString("x\x88\x80y", 2, 4) z = SubString("x\x80y", 2, 3) @test !endswith(x, y) + @test !endswith(y)(x) @test !endswith(x, z) + @test !endswith(z)(x) @test endswith(y, z) + @test endswith(z)(y) @test endswith(x, x) + @test endswith(x)(x) @test endswith(y, y) + @test endswith(y)(y) @test endswith(z, z) + @test endswith(z)(z) end @testset "filter specialization on String issue #32460" begin From d1f3d4532d0323d38948f6fab8ad92584ff2ed73 Mon Sep 17 00:00:00 2001 From: Carsten Bauer Date: Wed, 11 Mar 2020 15:20:09 +0100 Subject: [PATCH 2/3] News.md entry --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 60df17954b41d..e53098430ad71 100644 --- a/NEWS.md +++ b/NEWS.md @@ -61,6 +61,7 @@ New library functions expressions before they are evaluated ([#34595]). * New function `bitreverse` for reversing the order of bits in a fixed-width integer ([#34791]). * New function `bitrotate(x, k)` for rotating the bits in a fixed-width integer ([#33937]). +* One argument methods `startswith(x)` and `endswith(x)` have been added, returning partially-applied versions of the functions, similar to existing methods like `isequal(x)` ([#33193]). New library features -------------------- From 2b35cf2f41652a7d1e549ff16f40a7cabe2abb45 Mon Sep 17 00:00:00 2001 From: Carsten Bauer Date: Wed, 11 Mar 2020 15:25:37 +0100 Subject: [PATCH 3/3] compat entries --- base/strings/util.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base/strings/util.jl b/base/strings/util.jl index 5475057e2a63d..22dee5ebd024a 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -78,6 +78,10 @@ a function equivalent to `y -> endswith(y, suffix)`. The returned function is of type `Base.Fix2{typeof(endswith)}`, which can be used to implement specialized methods. + +!!! compat "Julia 1.5" + The single argument `endswith(suffix)` requires at least Julia 1.5. + """ endswith(s) = Base.Fix2(endswith, s) @@ -89,6 +93,10 @@ a function equivalent to `y -> startswith(y, prefix)`. The returned function is of type `Base.Fix2{typeof(startswith)}`, which can be used to implement specialized methods. + +!!! compat "Julia 1.5" + The single argument `startswith(prefix)` requires at least Julia 1.5. + """ startswith(s) = Base.Fix2(startswith, s)