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 a "SubstitutionFunction" for replace #36293

Open
tlienart opened this issue Jun 15, 2020 · 3 comments · May be fixed by #41051
Open

Add a "SubstitutionFunction" for replace #36293

tlienart opened this issue Jun 15, 2020 · 3 comments · May be fixed by #41051

Comments

@tlienart
Copy link
Contributor

context: https://discourse.julialang.org/t/using-replace-with-a-function-of-the-match/41264 ; the suggestion below was made by @simeonschaub; in short the idea would be to allow:

foo(m::RegexMatch) = uppercase(m.captures[1])
rx = r"b([a-z])r"
replace("foobar", rx => SubstitutionFunction(foo))
# fooA 

i.e. introduce a new SubstitutionFunction type that would wrap a function which would get passed the regex match and allow for that regex match to be processed specifically before doing the replacement.

At the moment, in order to achieve this, one has to do a double match (at least as far as I'm aware):

foo(m::RegexMatch) = uppercase(m.captures[1])
rx = r"b([a-z])r"
replace("foobar", rx => s -> foo(match(rx, s)))

which seems a bit dumb.

I'm interested in trying a PR for this but would like to collect feedback first as to whether people think it's a good idea? (also advice as to where to put the code whether close to replace or close to SubstitutionString or somewhere else, would be welcome)

@JeffreySarnoff
Copy link
Contributor

a new SubstitutionFunction type that would wrap a function f ...

rx = r"b([a-z])r"
foo(m::RegexMatch) = uppercase(m.captures[1])
result = replace("foobar", rx => SubstitutionFunction(foo))
  • Absent the SubstitutionFunction, the result is obtained by replacing the captured portion of "foobar" with the result of a string mapping transformation of that captured portion (here, uppercase).
  • With the SubstitutionFunction, the result is obtained by replacing the captured portion of "foobar" with the result of applying the SubstitutionFunction to that string mapping transformation.

The function applied to the string mapping transformation is not a function substituted for some other. What is a more apt name?

@tlienart
Copy link
Contributor Author

MatchTransformer?

@epithet
Copy link
Contributor

epithet commented May 31, 2021

I'm also really interested in being able to do this, and I proposed a different solution in #24598 before I found this issue.

This solution with the function wrapper would

  • be more consistent with the existing API
  • be less surprising because there wouldn't be two methods that take a function (only in different places), but with different semantics

Advantages of my solution:

  • no need for a wrapper type, and therefore more concise and more convenient
  • it would solve both issues at the same time, i.e. we would be able to use do-blocks

My main argument would be that the previous API is good for simple one-liners, and a do-block would enable more complicated things, which fits well with the intended purpose of do-blocks:

replace("The quick foxes run quickly.", r"fox(es)?" => s"bus\1")
# The quick buses run quickly.
replace("The quick foxes run quickly.", r"quick|slow" => uppercase)
# The QUICK foxes run QUICKly.
replace("The quick foxes run quickly.", r"fox(es)") do match
    "bus" * uppercase(match[1])
end
# The quick busES run quickly.

I'm completely happy with either solution, or even both, as long as I'm able to do this kind of thing. In any case, both are non-breaking, which I'm a big fan of in general.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants