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
regexp: add S.replaceWith and S.replaceBy #686
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I like this one better than the other one. We lose the special replacement syntax from the other PR but I didn't even know that's a thing and I can't think of any case where I would want that over just using replaceBy
. Removing that capability removes a gotcha, if they want that functionality String.replace
isn't going anywhere.
I did like that with the other PR both functions began with the regexp, but with these names the parameter order you have makes perfect sense and reads well. I also like these names better than the other ones.
It is convenient for // replace__ :: RegExp -> (Array String -> String) -> String -> String
//
// Variant of proposed function `S.replace_` (sanctuary-js/sanctuary#685)
// for patterns without optional capturing groups.
const replace__ = S.flip (S.compose (S.flip (S.replace_)) (S.contramap (S.justs))); // replaceBy_ :: (Array String -> String) -> RegExp -> String -> String
//
// Variant of proposed function `S.replaceBy` (sanctuary-js/sanctuary#686)
// for patterns without optional capturing groups.
const replaceBy_ = S.compose (S.replaceBy) (S.contramap (S.justs)); I am aware of two other reasons to take the pattern second:
|
function replaceWith(replacement) { | ||
return function(pattern) { | ||
return function(text) { | ||
return text.replace (pattern, function() { return replacement; }); | ||
}; | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we consider B (replaceBy) (K)
as the implementation of replaceWith
?
//. > S.replaceBy (S.show) (/(foo)(bar)?/) ('<foobar>') | ||
//. '<[Just ("foo"), Just ("bar")]>' | ||
//. ``` | ||
function replaceBy(substitute) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered naming it just replace
? What moved you to replaceBy
?
- I would confuse
replaceWith
andreplaceBy
all the time, and would have an easier time remembering howreplace
andreplaceWith
are different. - It makes sense for me that
replaceWith
is a specialisation ofreplace
. - The name
replace
is closer to its name in Native JavaScript. - It's shorter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent points. I completely agree. :)
In fact, I suggest we only provide this function (as S.replace
). As you noted, one can easily ignore the array of captured values (using S.K
, say). sanctuary-js/sanctuary-site#90 demonstrates this streamlined approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how I feel about the exclusion of replaceWith
altogether. I totally understand the reasoning, but since it's such a common use-case of replace
, it might not be comfortable for users to have to make this little jump to use K
with it every time. Then again, I would probably just define replaceWith
in my own projects and be happy either way, so I don't feel particularly strongly about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest we try replace
for a few months to see how it feels. We can easily add replaceWith
in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me.
Superseded by #693 |
Competes with #685
This pull request adds the following two functions:
Design decisions:
Both functions take
pattern :: RegExp
, so there is no straightforward equivalent ofs1.replace (s2, s3)
for stringss1
,s2
, ands3
. One could useS.replaceWith (s3) (S.regex ('') (S.regexEscape (s2))) (s1)
, but it would be simpler and clearer to useString#replace
directly in such cases.Using
pattern :: RegExp
exclusively provides two benefits:Simplicity. Supporting both
RegExp
andString
would require splittingreplaceWith
into two functions (which would pose a naming challenge) or usingEither RegExp String
(which would not be ergonomic).Clarity. It's unclear whether
R.replace ('o') ('x') ('foo')
should evaluate to'fxo'
or to'fxx'
, whereas the presence of theg
flag in/o/g
indicates that all occurrences ofo
should be replaced, and the absence of theg
flag in/o/
indicates that only the first occurrence ofo
should be replaced.Unlike
replace
,S.replaceWith
does not support special replacement patterns. We are not obligated to expose every feature of the underlying API, and withS.replaceBy
it is possible to reference values matched by capturing groups (the primary use case for special replacement patterns).Like
replace'
,S.replaceBy
ignores the “offset
” and “string
” arguments provided byString#replace
(when given a function). These are rarely useful.Unlike
replace'
,S.replaceBy
ignores the “groups
” argument provided byString#replace
(when given a function) if the pattern contains any named capturing groups. I included a fix for this deficiency in purescript/purescript-strings#126.Unlike
replace'
,S.replaceBy
ignores the “match
” argument provided byString#replace
(when given a function). This simplifies the function's type, and saves one from usingS.K (...)
when only the captured groups are important (as is commonly the case). If one does require access to the matched substring as a whole, one can use/(...)/
to capture it. Admittedly, this approach is impractical if the RegExp object is defined in another module, but in such exceptional cases one can of course useString#replace
directly.Unlike
replace'
,S.replaceBy
acknowledges the existence of optional capturing groups:Evaluating the equivalent PureScript expression results in an exception being thrown:
I have proposed the use of
Array (Maybe String)
in place ofArray String
in purescript/purescript-strings#126.I have opened sanctuary-js/sanctuary-site#88 to provide several examples of
replaceWith
andreplaceBy
in use.@sanctuary-js/owners, what do you think of the proposed additions to the library?