{"id":609,"date":"2015-09-19T15:10:06","date_gmt":"2015-09-19T22:10:06","guid":{"rendered":"http:\/\/kagan.mactane.org\/blog\/?p=609"},"modified":"2015-12-07T19:58:54","modified_gmt":"2015-12-08T03:58:54","slug":"skipping-regexes-in-es6-is-nothing-compared-to-skipping-boolean-comparison-warts","status":"publish","type":"post","link":"https:\/\/kagan.mactane.org\/blog\/2015\/09\/19\/skipping-regexes-in-es6-is-nothing-compared-to-skipping-boolean-comparison-warts\/","title":{"rendered":"Skipping Regexes in ES6 is Nothing Compared to Skipping Boolean-Comparison Warts"},"content":{"rendered":"<p>Yesterday, <a href=\"https:\/\/twitter.com\/wesbos\/status\/644897369000030209\">Wes Bos tweeted about<\/a> ES6&#8217;s <code>startsWith()<\/code>, <code>endsWith()<\/code>, and <code>includes()<\/code> methods. He said it was &#8220;[t]hree less JavaScript Regexes you&#8217;ll have to&nbsp;write&#8221;.<\/p>\n<p>Which is true, but I feel it misses the point. I mean, the regexes for initial match and final match are really not that hard, and the regex for plain inclusion is, well, basically the bare form of any regex: put slashes around it, and you&#8217;re&nbsp;done.<\/p>\n<p>The coolest thing about these new methods isn&#8217;t the ability to change <code>\/^foo\/<\/code>, <code>\/foo$\/<\/code>, or <code>\/foo\/<\/code> into just plain <code>foo<\/code>. That&#8217;s a savings of at most three keystrokes, and fairly little cognitive load. No, the coolest thing about these is <strong>not having to add <code class=\"nowrap\">!= -1<\/code> at the end of&nbsp;them!<\/strong><\/p>\n<p>I think looking at it as &#8220;not having to write regexes&#8221; is really missing the point. In fact, I&#8217;m going to dust off something I wrote on a private Livejournal, back in&nbsp;2007:<\/p>\n<div class=\"separator\"> <\/div>\n<p>When doing regex matches on strings, I&#8217;m sick and tired of writing things&nbsp;like:<\/p>\n<div class=\"code\">if (some_string.search(\/some_regex\/) <strong>!= -1<\/strong>) {<\/div>\n<p>In particular, it&#8217;s the bold part I object to. And for what it&#8217;s worth, there&#8217;s a similar wart in PHP, where searching for a substring requires the construct:<\/p>\n<div class=\"code\">if (<strong>false ===<\/strong> strpos($haystack, $needle)) {<\/div>\n<p>In both of these languages, the problem is that the function or method that&#8217;s doing the searching isn&#8217;t returning a strict Boolean, but it <em>is<\/em> being evaluated in a Boolean context. PHP&#8217;s <code>strpos()<\/code> returns the position at which the needle starts in the haystack string (which may be zero if the needle is right at the beginning of the haystack), or FALSE if the needle isn&#8217;t there. JavaScript&#8217;s <code>string.search()<\/code> method similarly returns the position at which the matched text starts (which, again, may be zero), or -1 on&nbsp;failure.<\/p>\n<p>And both of these languages evaluate zero as false in a Boolean context, so that you can find the text you&#8217;re looking for (right at the beginning of your string) and have the <code>if<\/code> statement claim it&#8217;s not&nbsp;there.<\/p>\n<p>Perl avoids this entire problem by simply making a binding to a pattern match return Boolean, and not bother giving you the position. (To be honest, you hardly ever need the actual position.) And maybe I&#8217;ve been spoiled by years of writing things&nbsp;like:<\/p>\n<div class=\"code\">if ($some_string =~ \/some_regex\/) {<\/div>\n<p>&#8230;but, honestly, I think Perl is getting it right and the other two are getting it&nbsp;wrong.<\/p>\n<div class=\"separator\"> <\/div>\n<p>So that&#8217;s what I wrote back in 2007. At that time, of course, PHP and Perl were both more significant; I wouldn&#8217;t mention them nearly as much today. Which is a bit of a shame, because the analysis of how <em>too much information makes life harder<\/em> is still apropos, and Perl still gets it right in a way that various other languages don&#8217;t.<\/p>\n<p>The ES6 methods help fix that, because they <strong>just return Boolean<\/strong>, instead of getting all fancy-pants and giving you the position where the match was found. (In fact, back in 2007, when everyone was using Prototype.js and the idea of messing with built-in objects&#8217; prototypes wasn&#8217;t as unfashionable as it is now, I pondered adding a function called &#8220;contains&#8221; to the String prototype in my company&#8217;s standard JavaScript library. And check it out; Firefox and Chrome <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/String\/includes\">have a <code>String.includes()<\/code> method<\/a>, which used to be named <code>contains()<\/code> at least in&nbsp;Firefox.<\/p>\n<p>But they still only take a case-sensitive string to search for, not a regex. Which makes me&nbsp;sad.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yesterday, Wes Bos tweeted about ES6&#8217;s startsWith(), endsWith(), and includes() methods. He said it was &#8220;[t]hree less JavaScript Regexes you&#8217;ll have to&nbsp;write&#8221;. Which is true, but I feel it misses the point. I mean, the regexes for initial match and final match are really not that hard, and the regex for plain inclusion is, well, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[7,146,83,70,60,33,71],"_links":{"self":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/609"}],"collection":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/comments?post=609"}],"version-history":[{"count":3,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/609\/revisions"}],"predecessor-version":[{"id":659,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/posts\/609\/revisions\/659"}],"wp:attachment":[{"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/media?parent=609"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/categories?post=609"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kagan.mactane.org\/blog\/wp-json\/wp\/v2\/tags?post=609"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}