8 ms·
ECMAScript proposal: String.prototype.replaceAll
- bendiksolheim 7y agoI don’t understand the rationale behind throwing an exception if you provide a regular expression which lacks the g modifier. This seems really counter intuitive. I would expect replaceAll to replace all occurrences no matter if the regular expression is global or not.
- TAForObvReasons 7y ago> The assumption is that we made a mistake and should switch to .replace() if we really only want to replace the first occurrence. Unlike the string case, the regexp case has a way of communicating that you want to match every instance versus only the first
- bendiksolheim 7y agoThat is an interesting way of seeing it. I’m not saying I disagree with the rationale, but I find it weird that a function which promises to do something needs a specially modified version of its input _not_ throw an exception. That does not sound like a good API design at all.
- TheRealPomax 7y agoThis feels like thinking about it the wrong way round: if you want to use regular expressions, use `.replace()`, which has full regex support and always has. There is no need to ever use `replaceAll` with regular expressions. In fact, you'd just be mudding the waters by using a function that implies "all" in combination with a regex that implies "single" (if you don't specify a `g` flag, as per regex convention). However, if you just want to replace plain strings, `.replaceAll()` actually gives you a fundamentally better API: you can now use `str.replace(s,r)` for single replace, and the intuitive companion function `str.replaceAll(s,r)` for all-instances replace. No "learning/knowing regexp" required just to replace some plain text.
- bendiksolheim 7y agoIf there is no need in using replaceAll() with regexes, why would it even support it? I agree that only replacing the first occurrence is the wrong solution. That would be surprising. The only correct solution to this is in my opinion auto-g-ing the regular expression, no matter how unusual that is. There is no way you would write replaceAll() as a mistake when you actually just meant replace().
- TheRealPomax 7y agoMostly to keep the signature for replaceAll in line with replace. You _can_ call it with a regex, but then you'll have to make sure it's a regex that uses the correct syntax for "replace-all" behaviour. If you don't, now you're doing something so weird that an error is the only appropriate response. <<There is no way you would write replaceAll() as a mistake when you actually just meant replace(). >> Have you ever reviewed the daily work of colleagues or contributors who haven't used JS day in day for the last 2 years? That's exactly the kind of mistake that happens _all_ the time. And people new to JS are more than happy to reach for regex well before there's a good reason to use them.
- a13n 7y agoIs there a way to find all occurrences/matches of a regex that doesn't have the 'g' modifier? Just tried `string.match` and `regex.exec` and could only get the first match.
- zamadatix 7y agoI don't think so without modifying the string or regex each iteration. You'd have to do something like let flagified = new RegExp(original.source, original.flags + "g") or modify the regex standards as part of the proposal.
- chipperyman573 7y agoI tried to do this a while ago for a side project. There might be a really obscure way (and of course you can always write your own function), but I wasn't able to find anything built in.
- snek 7y agoIt has to do with certain behaviours of RegExp objects, such as the `lastIndex` property, as well as consistency with `matchAll`. There was a lot of discussion[1] about what should happen with a regex that doesn't have /g, and in the end the most consistent choice was to just disallow them entirely. [1]: https://github.com/tc39/proposal-string-replaceall/issues/16 https://github.com/tc39/proposal-string-replaceall/issues/16
- dmitriid 7y agoThe irony in that discussion regarding behavior of matchAll: "Once something has shipped in browser's we can't change it". Chrome: deprecating and removing Custom Elements V0 in 2020.
- explodingcamera 7y ago*V0, this has always been explicitly unstable
- vimslayer 7y agoAlso, Custom Elements is in the area of W3C, not TC39, I believe. There could be different rules and people involved. Although I'm sure they'd like to avoid breaking the web too.
- dmitriid 7y agoIndeed, and that's the point I failed to make. TC39 is rightfully concerned about not breaking the web. They are very mindful even if features that have reached stage 3 (because by this time everyone is already using them). Browser implementors though... They take a much more callous approach.
- dmitriid 7y agoAnd used by the biggest websites and projects on the Web (Google's own YouTube and AMP until very recently). How many more websites are using it because it was out, and implemented?
- happytoexplain 7y agoI too was surprised by this, but for the opposite reason: I would expect replaceAll to replace all matches for the regex, meaning if the regex only matches the first occurrence of a pattern, then only the first occurrence is replaced. The fact that we both made perfectly opposite assumptions about what is "obviously right" is strong evidence for their decision.
- chipperyman573 7y agoIsn't that how .replace works? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- happytoexplain 7y agoPerhaps - I rarely write JS. I'm speaking purely based on this function alone.
- bendiksolheim 7y agoI disagree that this makes their decision the right one. If we can come up with so many "valid" versions of this, all with their own flaws, then this is the wrong API to build. This function should not exist in its current form at all. APIs should be intuitive, preferably without reading the documentation (although I agree that this is a utopian way of seeing it).
- tmpfile 7y agoI agree. I would think replaceAll would behave like the following: /* Usage: > 'abcdefabc'.replaceAll('abc') 'def' > 'abcdefabc'.replaceAll('abc', '+') '+def+' > 'abcdefabc'.replaceAll(/abc/, '+') '+def+' > 'abcdefabc'.replaceAll(/abc/g, '+') '+def+' */ String.prototype.replaceAll = function (re_or_str, sub) { return this.split(re_or_str).join(sub||'') } On a side note, is it just me or does the linked polyfill for String.prototype.replaceAll [1] seem wildly complex??? [1] https://github.com/es-shims/String.prototype.replaceAll/blob/master/implementation.js https://github.com/es-shims/String.prototype.replaceAll/blob...
- jsjohnst 7y agoAgree, seems much more complex than it should need to be, but I’m guessing there’s edge cases (but even then it seems more complex than needed).
- vimslayer 7y agoYour implementation is missing features like capture-based substitions // Remove repeated characters 'foobar'.replace(/(.)\1+/g, '$1') "fobar" and overriding behaviour with Symbol.replace
- deleted 7y ago[deleted]
- tmpfile 7y agoYou're right, my implementation was not a drop-in replacement for replace. How about this? String.prototype.replaceAll = function (n, sub) { let t, f = "g"; if (n instanceof RegExp) { t = n.source; f = n.flags; if (!f.includes("g")) f += "g"; } else { t = RegExp.escape(n); } let r = new RegExp(t, f); return this.replace(r, sub || ""); }
- tus88 7y agoHow do you know when an entire language is ready to be thrown in the trashcan? When you are having a debate about what "all" means.
- yepthatsreality 7y agoMmmmm...syntactic sugar...
- chrisseaton 7y agoNot sure what you mean? This doesn't add or use any new syntax, let alone syntactic sugar. It's a new builtin method.
- DDR0 7y agoCould you provide an example of what this desugars to? I'm not sure I understand.
- sveingjoby 7y agoYes, you are (of course) able to replace all occurrences today. However, you either need to call replace multiple times or pollute your code with a regex. This would certainly improve the readability.
- pier25 7y agoWhy would using regex pollute your code?
- Normal_gaussian 7y ago
- robbrown451 7y agoThis would be nice, using RegEx's for such simple cases is ugly, especially if the replace string is dynamic (so can't be done with a literal). I find myself using a combination of split and join a lot to avoid that.
- deith 7y agoAnd because regexes are regexes, so one might introduce bugs by not escaping what's meant to be escaped. (I didn't read the article so maybe he mentions this already)
- 2ion 7y agoExhibit $n why ECMAScript is not a well-designed language at its core. It ought to be as simple as the Lua core language but it isn't (the object type was a good start but then stopped being one). Boltons after boltons. For things as simple as this.
- snek 7y agolua has s:gsub, which is basically the same thing... or are you saying js should've popped into existence with thousands of stdlib functions?
- mschuster91 7y agoPHP at least is sane enough to provide the C stdlib, dito for Java. JavaScript... well, remember left-pad? That's what happens when people are forced to re invent the wheels.
- krapp 7y agoleft-pad wasn't a fault of the language, but the modern javascript ecosystem and its tools. Javascript development got along fine for years when all anyone had was JQuery plugins, no one was complaining about the lack of a C style stdlib, and no single point of failure for the entire ecosystem created an internet-wide catastrophe every week.
- ben-schaaf 7y agoEveryone complained about the lack of a C style stdlib. That's why jQuery was written and everyone used it.
- krapp 7y agoPeople complained about incompatible versions of the DOM between IE and everyone else, and about how awkward AJAX and DOM manipulation was, and those are the problems JQuery solved. That's providing a common API and mostly forcing Microsoft to follow spec, not a "C style stdlib," though. I don't think many people were upset that javascript didn't natively support, say, proper integers or static types or (ugh) "classes" or what have you, at least not until people started wanting to use javascript outside of its intended purpose.
- deleted 7y ago[deleted]
- zzo38computer 7y agoI would have make the "escapeForRegExp" function built-in (it seems to me the kind of thing should be built-in), perhaps called RegExp.quote. (I would also to add support for many features of PCRE.)
- snek 7y agoYou can use String.raw: new RegExp(String.raw`\s`) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- zzo38computer 7y agoNo, that is something different.
- snek 7y agoYes, but it works quite well for this task.
- anderskaseorg 7y agoIt has nothing to do with this task. function replaceAll(str: string, pattern: string, replacement: string): string { return str.replace(new RegExp(escapeForRegExp(pattern), "g"), replacement); }
- phpnode 7y agoThere's a proposal for RegExp.escape() which was rejected by TC39 for imho quite silly reasons: https://github.com/benjamingr/RegExp.escape/issues/37 https://github.com/benjamingr/RegExp.escape/issues/37
- pjtr 7y agoI don't understand the reasons. What is the actual problem in this "even-odd problem"? How do all the other languages that have an equivalent function (Perl quotemeta, PHP preg_quote, Python re.escape, Ruby: Regexp.escape, Java Pattern.quote, C# Regex.Escape, Go QuoteMeta, Rust regex::escape) avoid or deal with this problem?
- biolurker1 7y agoSo much fuss for a small function
- happytoexplain 7y agoIt being small does not mean it's not critically important to get the details right. In fact, if there's any correlation between smallness and frequency of use, then it's actually more important to go to the full lengths of fuss resolution.
- biolurker1 7y agoReally you think in 2020 the software world should have an open discussion about a string replace function? Ok
- the_other 7y agoFor the world’s most popular language? Yes.
- tomaszs 7y agoCouldnt we just have an object called String2 with a replace method that replaces all occurances without any regex at all? Like in any other language? We could fix entire Javascript just by adding two to all object names.
- colejohnson66 7y agoThis isn’t String.replaceAll(str, match, replace), it’s str.replaceAll(match, replace). A function of the type, not a class.
- soylentgraham 7y agoThis is such a terrible idea.
- tomaszs 7y agoYou right. We should have Javascript2 language.
- herohamp 7y agohttps://xkcd.com/927/ https://xkcd.com/927/
- tomaszs 7y agoThis strip is about creating unifications based on two things that are not standarized. While the idea is to make a new JS branch that will solve issues gathered through years. So the strip does not apply here. Also, while it has some point with extreme unification efforts, there is a vast range of unification projects that actually delivered what they promised to.
- pier25 7y agoWhile this is a nice little addition to the language, personally I'd prefer to see more substantial changes like decorators, observables, class properties, optional static types, etc.
- mccraveiro 7y agoClass properties are already part of the language
- pier25 7y agoMy bad, I meant class fields which are stage 3: https://github.com/tc39/proposal-class-fields https://github.com/tc39/proposal-class-fields https://tc39.es/proposal-class-fields/ https://tc39.es/proposal-class-fields/
- rienbdj 7y agoI wish the pipeline operator were standardised so we can stop fiddling with prototypes.
- kapv89 7y agoI think JS has had enough of syntactic sugar like features. What it needs as a next step in its natural evolution is support for proper multi-threading with atomics, mutex etc.
- bobbytherobot 7y agoWhat would you do with multi-threading in JS? I/O is already non-blocking which is a big reason for using multi-threading.