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

make replace with count=0 a no-op #22325

Merged
merged 13 commits into from
Jul 4, 2017
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
Prev Previous commit
Next Next commit
deprecate when count < 0 and add NEWS.md entry
  • Loading branch information
rfourquet committed Jul 4, 2017
commit bd0079a9ef15d90d4e11761626e70fc3b70dc221
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ Deprecated or removed
Ternaries must now include some amount of whitespace, e.g. `x ? a : b` rather than
`x? a : b` ([#22523]).

* The method `replace(s::AbstractString, pat, r, count)` with `count <= 0` is deprecated
in favor of `replace(s::AbstractString, pat, r, typemax(Int))` ([#22325]).


Julia v0.6.0 Release Notes
==========================
Expand Down
11 changes: 11 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,17 @@ function bkfact!(A::StridedMatrix, uplo::Symbol, symmetric::Bool = issymmetric(A
return bkfact!(symmetric ? Symmetric(A, uplo) : Hermitian(A, uplo), rook)
end

function replace(s::AbstractString, pat, f, n::Integer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add a comment explaining that replace_new needs to be renamed to replace when removing this deprecation (and make sure tests will fail if that's not the case).

if n <= 0
depwarn(string("`replace(s, pat, r, count)` with `count <= 0` is deprecated, use ",
"`replace(s, pat, r, typemax(Int))` or replace(s, pat, r)` instead"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing opening backtick.

:replace)
Base.replace(s, pat, f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base. not needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok removed.

else
Base.replace_new(String(s), pat, f, Int(n))
end
end

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
16 changes: 8 additions & 8 deletions base/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,10 @@ _replace(io, repl, str, r, pattern) = print(io, repl)
_replace(io, repl::Function, str, r, pattern) =
print(io, repl(SubString(str, first(r), last(r))))

function replace(str::String, pattern, repl, limit::Int)
limit == 0 && return str
limit < 0 && throw(DomainError())
function replace_new(str::String, pattern, repl, count::Int)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why restrict this to Int?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's what's done in other contexts too: accept Integer at the API level, but convert to Int in the method which does the work, a readons could be to limit the number of compiled functions. But I can see that there is no reason to error out if e.g. a very big BigInt is passed. I could use clamp(n, 0, typemax(Int) instead of Int(n) in the caller (which is in deprecated now), assuming it's never necessary to replace more than typemax(Int) times.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that once the deprecation is removed, the "API level" will be this function, and only Int will be accepted... So if you want this you need to add another layer which will remain. But really I'm not sure it's worth it, e.g. search doesn't use that trick.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. But this replace_new also only accepts a String, not an AbstractString, so this is the replace(s::AbstractString, pat, f) = replace_new(String(s), pat, f, typemax(Int)) (still in strings/util.jl, below replace_new) which will have to be modified to
replace(s::AbstractString, pat, f, count::Integer=typemax(Int)) = replace(String(s), pat, f, clamp(count, typemin(Int), typemax(Int)) % Int).

# rename to `replace` when `replace` is removed from deprecated.jl
count == 0 && return str
count < 0 && throw(DomainError())
n = 1
e = endof(str)
i = a = start(str)
Expand All @@ -386,26 +387,25 @@ function replace(str::String, pattern, repl, limit::Int)
end
r = search(str,pattern,k)
j, k = first(r), last(r)
n == limit && break
n == count && break
n += 1
end
write(out, SubString(str,i))
String(take!(out))
end

"""
replace(string::AbstractString, pat, r, [count::Integer])
replace(s::AbstractString, pat, r, [count::Integer])

Search for the given pattern `pat`, and replace each occurrence with `r`.
Search for the given pattern `pat` in `s`, and replace each occurrence with `r`.
If `count` is provided, replace at most `count` occurrences.
As with search, the second argument may be a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

search would be good as a cross reference

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

single character, a vector or a set of characters, a string, or a regular expression. If `r`
is a function, each occurrence is replaced with `r(s)` where `s` is the matched substring.
If `pat` is a regular expression and `r` is a `SubstitutionString`, then capture group
references in `r` are replaced with the corresponding matched text.
"""
replace(s::AbstractString, pat, f, n::Integer=typemax(Int)) =
replace(String(s), pat, f, Int(n))
replace(s::AbstractString, pat, f) = replace_new(String(s), pat, f, typemax(Int))

# hex <-> bytes conversion

Expand Down
3 changes: 2 additions & 1 deletion test/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,12 @@ end
@test replace("abc", 'b', 2.1) == "a2.1c"

# test replace with a count, check that replace is a no-op if count==0
@test replace("aaa", 'a', 'z', 0) == "aaa"
# @test replace("aaa", 'a', 'z', 0) == "aaa" # re-enable when undeprecated
@test replace("aaa", 'a', 'z', 1) == "zaa"
@test replace("aaa", 'a', 'z', 2) == "zza"
@test replace("aaa", 'a', 'z', 3) == "zzz"
@test replace("aaa", 'a', 'z', 4) == "zzz"
@test replace("aaa", 'a', 'z', typemax(Int)) == "zzz"

# chomp/chop
@test chomp("foo\n") == "foo"
Expand Down