<div dir="ltr">URLs are unlikely to be something that can be validated by regex. See, for instance, this discussion: <<a href="https://webkit.org/blog/7086/url-parsing-in-webkit/">https://webkit.org/blog/7086/url-parsing-in-webkit/</a>>. The full spec is here: <<a href="https://url.spec.whatwg.org">https://url.spec.whatwg.org</a>>. If Swift were to implement parsing of URLs at the level of the compiler or core library, I'd expect it to be the full spec, as we do with Unicode.<div><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 19, 2016 at 2:26 AM, Benjamin Spratling via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">Howdy,<div><span class="gmail-m_-1448418347467680467Apple-tab-span" style="white-space:pre-wrap">        </span>Yes, I was also intrigued by the “Regex” validation mentioned in another post. It could offer a convenient way to get some literals support in without the headaches associated with the constexpr C++ approach.</div><div><span class="gmail-m_-1448418347467680467Apple-tab-span" style="white-space:pre-wrap">        </span>I’m curious, though, how many types can we image in can be validated by this method? If it really is just URL’s, then I’d actually lean towards making this a compiler magic feature.</div><div><br></div><div><span class="gmail-m_-1448418347467680467Apple-tab-span" style="white-space:pre-wrap">        </span>Someone else mentioned fetching the URL’s for a preview. Given that we might be coding “deletes” in URL’s (yes, I recently met a backend developer who coded a delete as a GET), I really highly suggest we not ping people’s API’s artificially. At least we shouldn’t for non-file-scheme URLs. IMHO, verifying that a service is active isn’t really the Swift compiler’s job. It might happen as part of coordinated run-time tests, which sometimes have to be balanced to keep test data correct, something the IDE wouldn’t know how to enforce correctly.</div><div>-Ben</div><div><br><div><blockquote type="cite"><div><div class="gmail-h5"><div>On Dec 19, 2016, at 1:41 AM, David Sweeris via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_-1448418347467680467Apple-interchange-newline"></div></div><div><div><div class="gmail-h5"><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Dec 17, 2016, at 1:12 PM, Micah Hainline via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_-1448418347467680467Apple-interchange-newline"><div><div dir="auto"><div></div><div>I'd love a fleshed out elegant example for URL that shows what a complete implementation of that special init method would look like. </div></div></div></blockquote><br></div><div>Sorry this took so long… the weekend kinda got away from me.</div><div><br></div><div>Anyway, I was thinking something like this (which has been very simplified on account of my regexing being sub-sketchy, and me not knowing exactly what’s valid in an URL anyway):</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;line-height:normal"><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures"><font color="#bb2ca2">#literalpatterns</font> += (</span><font face="Menlo">name: </font><span style="color:rgb(209,47,27);font-family:menlo">“URLLiteralType</span><font color="#d12f1b" face="Menlo">”</font><font face="Menlo">, components</font><font face="Menlo">: (name: url, type: </font><span style="color:rgb(112,61,170);font-family:menlo">StringLiteralType</span><font face="Menlo">, </font><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">patte<wbr>rn: </span><font color="#d12f1b" face="Menlo">“(http|https)://</font><font color="#d12f1b" face="Menlo">(www.)?[a-z|A-<wbr>Z|0-9]+</font><font color="#d12f1b" face="Menlo">.(com|org|net)(/</font><span style="color:rgb(209,47,27);font-family:menlo">[a-z|A-<wbr>Z|0-9]+)*(/</span><span style="color:rgb(209,47,27);font-family:menlo">[a-z|A-Z|0-9]+.</span><span style="color:rgb(209,47,27);font-family:menlo">[a-<wbr>z|A-Z|0-9]+)?</span><font face="Menlo"><font color="#d12f1b">”</font>), </font><font face="Menlo">protocol: </font><span style="color:rgb(79,129,135);font-family:menlo">ExpressibleByURLLite<wbr>ral</span><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">)</span></div></div></blockquote><div><div><div style="margin:0px;line-height:normal">This would let the compiler know pretty much everything it needs to know… that the “new” type is called “URLLiteralType", that it starts out life as young StringLiteralType with a bright future in the computer industry, that in order to succeed it has to match a given pattern, and what protocol a type has to conform to in order to use an URLLiteral. In practice, the compiler would synthesize a struct containing the specified members and validate the literal with the specified pattern before making an “instance” of it (since we’re talking about literals and compile-time code here, I’m pretty sure that “instance" the wrong terminology… pardon my ignorance)</div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">struct</span><span style="font-variant-ligatures:no-common-ligatures"> URLLiteralType: {</span></div></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo;color:rgb(112,61,170)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> url: </span><span style="font-variant-ligatures:no-common-ligatures">StringLiteralType</span></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div></div></div></blockquote><div><div style="margin:0px;line-height:normal"><div><span style="font-variant-ligatures:no-common-ligatures">A tuple would be better, IMHO, but according to the playground, single-element tuples can’t have element labels. </span>As for the implementation of the init function:</div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">init</span><span style="font-variant-ligatures:no-common-ligatures">(urlLiteral value: <span style="color:rgb(79,129,135)">URLLiteralType</span>) {</span></div><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> urlString = value.url</span></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal"><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures"> </span><font color="#008400" face="Menlo">//Do whatever URL is doing now, except there’s no need to check for errors since the compiler pre-validated it for us</font></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div></div></div></blockquote><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal"><br></div></div><div>If it’d be more useful, the pattern could be split into multiple pieces:</div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;line-height:normal"><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures"><font color="#bb2ca2">#literalpatterns</font> += (</span><font face="Menlo">name: </font><span style="color:rgb(209,47,27);font-family:menlo">“URLLiteralType</span><font color="#d12f1b" face="Menlo">”</font><font face="Menlo">,</font></div><div style="margin:0px;line-height:normal"><font face="Menlo"> components: (</font><font face="Menlo">(name: </font><font color="#d12f1b" face="Menlo">“`protocol`"</font><font face="Menlo">, type: </font><span style="color:rgb(112,61,170);font-family:menlo">StringLiteralType</span><font face="Menlo">, </font><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">patte<wbr>rn: </span><font color="#d12f1b" face="Menlo">“(http|https)”</font><font face="Menlo">),</font></div><div style="margin:0px;line-height:normal"><font face="Menlo"> (name: </font><span style="color:rgb(187,44,162);font-family:menlo">_</span><font face="Menlo">, type: </font><span style="color:rgb(112,61,170);font-family:menlo">StringLiteralType</span><font face="Menlo">, </font><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">patt<wbr>ern: </span><font color="#d12f1b" face="Menlo">“://”</font><font face="Menlo">),</font></div><div style="margin:0px;line-height:normal"><font face="Menlo"> (name: </font><span style="color:rgb(209,47,27);font-family:menlo">“domain"</span><font face="Menlo">, </font><font face="Menlo">type: </font><span style="color:rgb(112,61,170);font-family:menlo">StringLiteralType</span><font face="Menlo">, </font><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">pat<wbr>tern: </span><font color="#d12f1b" face="Menlo">“(www.)?[a-z|A-Z|0-9]+</font><font color="#d12f1b" face="Menlo">.(<wbr>com|org|net)</font><font face="Menlo"><font color="#d12f1b">”</font>),</font></div><div style="margin:0px;line-height:normal"><font face="Menlo"> (name: </font><font color="#d12f1b" face="Menlo">“path”</font><font face="Menlo">, </font><font face="Menlo">type: </font><span style="color:rgb(112,61,170);font-family:menlo">StringLiteralType</span><font face="Menlo">, </font><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">pat<wbr>tern: </span><font color="#d12f1b" face="Menlo">"(/</font><span style="color:rgb(209,47,27);font-family:menlo">[a-z|A-Z|0-9]+)*(/</span><span style="color:rgb(209,47,27);font-family:menlo">[a-z|A-Z|<wbr>0-9]+.</span><span style="color:rgb(209,47,27);font-family:menlo">[a-z|A-Z|0-9]+)?</span><font face="Menlo"><font color="#d12f1b">”</font>))</font></div><div style="margin:0px;line-height:normal"><font face="Menlo"> protocol: </font><span style="color:rgb(79,129,135);font-family:menlo">ExpressibleByURLLit<wbr>eral</span><span style="font-family:menlo;font-variant-ligatures:no-common-ligatures">)</span></div></div></blockquote><div><div style="margin:0px;line-height:normal">This would result in URLLiteralType looking like this:</div><div style="margin:0px;line-height:normal"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">struct</span><span style="font-variant-ligatures:no-common-ligatures"> URLLiteralType: {</span></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo;color:rgb(112,61,170)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> `protocol`: </span><span style="font-variant-ligatures:no-common-ligatures">StringLitera<wbr>lType</span></div><div style="margin:0px;line-height:normal;font-family:menlo;color:rgb(112,61,170)"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> domain: </span><span style="font-variant-ligatures:no-common-ligatures">StringLiteralTyp<wbr>e</span></div><div style="margin:0px;line-height:normal;font-family:menlo;color:rgb(112,61,170)"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)"> let</span><span style="font-variant-ligatures:no-common-ligatures"> path: </span><span style="font-variant-ligatures:no-common-ligatures">StringLiteralType</span></span></div><div style="margin:0px;line-height:normal;font-family:menlo;color:rgb(112,61,170)">}</div></div></div></blockquote>And in the init would start out like this:</div><div style="margin:0px;line-height:normal"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">init</span><span style="font-variant-ligatures:no-common-ligatures">(urlLiteral value: <span style="color:rgb(79,129,135)">URLLiteralType</span>) {</span></div><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> protocolType = value.</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(79,129,135)">protocol</span></div><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> domain = value.</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(79,129,135)">domain</span></div><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(79,129,135)"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(187,44,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> path = value.</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(79,129,135)">path</span></div><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures"> </span><font color="#008400" face="Menlo">//Do whatever with the components</font></div></div></div><div><div style="margin:0px;line-height:normal"><div style="margin:0px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div></div></div></blockquote></div></div><div><div style="margin:0px;line-height:normal"><div><div style="margin:0px;line-height:normal"><div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div><div><span style="font-variant-ligatures:no-common-ligatures">The “base” types of literals like Int or String that don’t refine pre-existing literal types would still need a bit of compiler magic (or at least a different mechanism for becoming actual types), but </span>as long as a type doesn’t take advantage of reference semantics in its stored properties or something, I *think* pretty much any data type could become “literalizeable” with something like this. Oh, and there’s nothing particularly magical about regular expressions as far as this idea is concerned; they’re just usually the first thing that comes to mind when I think of pattern matching in a string. </div><div><br></div><div>I know this looks like a lot of code, but the scary-looking parts with the regex stuff only has to be written once for each “type” of literal… types that want to be expressible by such a literal just have to write an init function.</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>While I was writing this up, it occurred to me that another solution would be to have a set of "ExpressibleByValidated*<wbr>Literal” protocols, where the init is failable and has to be @pure/@constexpr/@<wbr>whateverthecompilerneedstoruni<wbr>tatcompiletime. That way the literal can be validated simply by calling the init and checking if it returns nil. Make `URL` conform to `<wbr>ExpressibleByValidatedStringLi<wbr>teral`, and you'll get the complie-time validation functionality just by copying whatever’s in the current `URL.init?(string: String)` function.</div><div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div><div>- Dave Sweeris</div></div></div></div></div><div><div style="margin:0px;line-height:normal"><div><div style="margin:0px;line-height:normal"></div></div></div></div></div></div></div><span class="gmail-">______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></span></div></blockquote></div><br></div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div></div></div>