<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Michael,</div><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Thanks for sending this through. It’s an interesting read. One section gave me pause however. I feel Swift should resist the siren call of combining Swift Syntax with Regex syntax as it falls on the wrong side of Occam's razor. ISO Regex syntax is plenty complex enough without trying to incorporate named capture, desirable as it may be. Also, if I was to go down that route, I’d move away from / as the delimiter which is a carry over from Perl to something like e”I am a regex” to give the lexer more to go on which could represent say, a cached instance of NSRegularExpression.</div><div class=""><br class=""></div>And now for something completely different...<br class=""><div class=""><br class=""></div><div class="">Common usage patterns for a regex fall into 4 categories: deconstruction, replacement, iteration and switch/case. Ideally the representation of a regex match would the same for all four of these categories and I’d like to argue a set of expressive regex primitives can be created without building them into the language.</div><div class=""><br class=""></div><div class="">I’ve talked before about a regex match being coded as a string/regex subscripting into a string and I’ve been able to move this forward since last year. While this seems like an arbitrary operator to use it has some semantic sense in that you are addressing a sub-part of the string with pattern as you might use an index or a key. Subscripts also have some very interesting properties in Swift compared to other operators or functions: You don’t have to worry about precedence, they can be assigned to, used as an interator, and I've learned since my last email on this topic that the <i class="">Swift type checker will disambiguate multiple subscript overloads on the basis of the type of the variable is being assigned to</i>.</div><div class=""><br class=""></div><div class="">An extension to String can now realise the common use cases by judicious use of types:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">var</span><span style="color: #000000" class=""> input = </span>"Now is the time for all good men to come to the aid of the party"</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">if</span><span style="color: #000000" class=""> </span><span style="color: #4f8187" class="">input</span><span style="color: #000000" class="">[</span>"\\w+"<span style="color: #000000" class="">] {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #000000" class=""> </span><span style="color: #3e1e81" class="">print</span><span style="color: #000000" class="">(</span>"match"<span style="color: #000000" class="">)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0); background-color: rgb(255, 255, 255);" class="">// receiving type controls data you get</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">if</span> <span style="color: #ba2da2" class="">let</span> firstMatch: <span style="color: #703daa" class="">Substring</span> = <span style="color: #4f8187" class="">input</span>[<span style="color: #d12f1b" class="">"\\w+"</span>] {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #3e1e81" class="">print</span>(<span style="color: #d12f1b" class="">"match: </span>\<span style="color: #d12f1b" class="">(</span>firstMatch<span style="color: #d12f1b" class="">)"</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="color: rgb(186, 45, 162);" class="">if</span> <span style="color: rgb(186, 45, 162);" class="">let</span> groupsOfFirstMatch: [<span style="color: rgb(112, 61, 170);" class="">Substring</span>?] = <span style="color: rgb(79, 129, 135);" class="">input</span>[<span style="color: rgb(209, 47, 27);" class="">"(all) (\\w+)"</span>] {</div></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #3e1e81" class="">print</span>(<span style="color: #d12f1b" class="">"groups: </span>\<span style="color: #d12f1b" class="">(</span>groupsOfFirstMatch<span style="color: #d12f1b" class="">)"</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0); background-color: rgb(255, 255, 255);" class="">// "splat" out up to N groups of first match</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="color: rgb(186, 45, 162);" class="">if</span> <span style="color: rgb(186, 45, 162);" class="">let</span> (group1, group2): (<span style="color: rgb(112, 61, 170);" class="">String</span>, <span style="color: rgb(112, 61, 170);" class="">String</span>) = <span style="color: rgb(79, 129, 135);" class="">input</span>[<span style="color: rgb(209, 47, 27);" class="">"(all) (\\w+)"</span>] {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #000000" class=""> </span><span style="color: #3e1e81" class="">print</span><span style="color: #000000" class="">(</span>"group1: <span style="color: #000000" class="">\</span>(<span style="color: #000000" class="">group1</span>), group2: <span style="color: #000000" class="">\</span>(<span style="color: #000000" class="">group2</span>)"<span style="color: #000000" class="">)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">if</span> <span style="color: #ba2da2" class="">let</span> allGroupsOfAllMatches: [[<span style="color: #703daa" class="">Substring</span>?]] = <span style="color: #4f8187" class="">input</span>[<span style="color: #d12f1b" class="">"(\\w)(\\w*)"</span>] {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #3e1e81" class="">print</span>(<span style="color: #d12f1b" class="">"allGroups: </span>\<span style="color: #d12f1b" class="">(</span>allGroupsOfAllMatches<span style="color: #d12f1b" class="">)"</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div></div><div class=""><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class="">// regex replace by assignment</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27);" class=""><span style="color: rgb(79, 129, 135);" class="">input</span><span style="color: rgb(0, 0, 0);" class="">[</span>"men"<span style="color: rgb(0, 0, 0);" class="">] = </span>"folk"</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(62, 30, 129);" class="">print<span style="color: rgb(0, 0, 0);" class="">(</span><span style="color: rgb(79, 129, 135);" class="">input</span><span style="color: rgb(0, 0, 0);" class="">)</span></div></div><div class=""><br class=""></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0); background-color: rgb(255, 255, 255);" class="">// parsing a properties file using regex as iterator</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">let</span> props = <span style="color: #d12f1b" class="">"""</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> name1 = value1</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> name2 = value2</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> """</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">var</span> params = [<span style="color: #703daa" class="">String</span>: <span style="color: #703daa" class="">String</span>]()</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">for</span><span style="color: #000000" class=""> groups </span><span style="color: #ba2da2" class="">in</span><span style="color: #000000" class=""> </span><span style="color: #4f8187" class="">props</span><span style="color: #000000" class="">[</span>"(\\w+)\\s*=\\s*(.*)"<span style="color: #000000" class="">] {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #4f8187" class="">params</span>[<span style="color: #703daa" class="">String</span>(groups[<span style="color: #272ad8" class="">1</span>]!)] = <span style="color: #703daa" class="">String</span>(groups[<span style="color: #272ad8" class="">2</span>]!)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""><span style="color: #3e1e81" class="">print</span><span style="color: #000000" class="">(</span>params<span style="color: #000000" class="">)</span></div></div><div class=""><span style="color: #000000" class=""><br class=""></span></div><div class="">The case for switches is slightly more opaque in order to avoid executing the match twice but viable.</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0); background-color: rgb(255, 255, 255);" class=""><span style="color: rgb(186, 45, 162);" class="">let</span> match = <span style="color: rgb(79, 129, 135);" class="">RegexMatch</span>()</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(186, 45, 162); background-color: rgb(255, 255, 255);" class="">switch<span style="color: #000000" class=""> </span><span style="color: #4f8187" class="">input</span><span style="color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">case</span><span style="color: #000000" class=""> </span>RegexPattern<span style="color: #000000" class="">(</span><span style="color: #d12f1b" class="">"(\\w)(\\w*)"</span><span style="color: #000000" class="">, capture: </span>match<span style="color: #000000" class="">):</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #ba2da2" class="">let</span> (first, rest) = <span style="color: #4f8187" class="">input</span>[<span style="color: #4f8187" class="">match</span>]</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""> <span style="color: #3e1e81" class="">print</span>(<span style="color: #d12f1b" class="">"</span>\<span style="color: #d12f1b" class="">(</span>first<span style="color: #d12f1b" class="">) </span>\<span style="color: #d12f1b" class="">(</span>rest<span style="color: #d12f1b" class="">)"</span>)</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(186, 45, 162); background-color: rgb(255, 255, 255);" class="">default<span style="color: #000000" class="">:</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(186, 45, 162); background-color: rgb(255, 255, 255);" class=""><span style="color: #000000" class=""> </span>break</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">}</div></div><div class=""><br class=""></div><div class="">This is explored in the attached playground (repo: <a href="https://github.com/johnno1962/SwiftRegex4" class="">https://github.com/johnno1962/SwiftRegex4</a>)</div><div class=""></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></body></html>