[swift-evolution] URL Literals

Benjamin Spratling bspratling at mac.com
Mon Dec 19 02:26:45 CST 2016


Howdy,
	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.
	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.

	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.
-Ben

> On Dec 19, 2016, at 1:41 AM, David Sweeris via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Dec 17, 2016, at 1:12 PM, Micah Hainline via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> I'd love a fleshed out elegant example for URL that shows what a complete implementation of that special init method would look like. 
> 
> Sorry this took so long… the weekend kinda got away from me.
> 
> 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):
> #literalpatterns += (name: “URLLiteralType”, components: (name: url, type: StringLiteralType, pattern: “(http|https)://(www.)?[a-z|A-Z|0-9]+.(com|org|net)(/[a-z|A-Z|0-9]+)*(/[a-z|A-Z|0-9]+.[a-z|A-Z|0-9]+)?”), protocol: ExpressibleByURLLiteral)
> 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)
> struct URLLiteralType: {
>     let url: StringLiteralType
> }
> A tuple would be better, IMHO, but according to the playground, single-element tuples can’t have element labels. As for the implementation of the init function:
> init(urlLiteral value: URLLiteralType) {
>     let urlString = value.url
>     //Do whatever URL is doing now, except there’s no need to check for errors since the compiler pre-validated it for us
> }
> 
> If it’d be more useful, the pattern could be split into multiple pieces:
> #literalpatterns += (name: “URLLiteralType”,
>                      components: ((name: “`protocol`", type: StringLiteralType, pattern: “(http|https)”),
>                                   (name: _,            type: StringLiteralType, pattern: “://”),
>                                   (name: “domain",     type: StringLiteralType, pattern: “(www.)?[a-z|A-Z|0-9]+.(com|org|net)”),
>                                   (name: “path”,       type: StringLiteralType, pattern: "(/[a-z|A-Z|0-9]+)*(/[a-z|A-Z|0-9]+.[a-z|A-Z|0-9]+)?”))
>                      protocol: ExpressibleByURLLiteral)
> This would result in URLLiteralType looking like this:
> struct URLLiteralType: {
>     let `protocol`: StringLiteralType
>     let domain: StringLiteralType
>     let path: StringLiteralType
> }
> And in the init would start out like this:
> init(urlLiteral value: URLLiteralType) {
>     let protocolType = value.protocol
>     let domain = value.domain
>     let path = value.path
>     //Do whatever with the components
> }
> 
> 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 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. 
> 
> 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.
> 
> 
> 
> 
> 
> While I was writing this up, it occurred to me that another solution would be to have a set of "ExpressibleByValidated*Literal” protocols, where the init is failable and has to be @pure/@constexpr/@whateverthecompilerneedstorunitatcompiletime. That way the literal can be validated simply by calling the init and checking if it returns nil. Make `URL` conform to `ExpressibleByValidatedStringLiteral`, and you'll get the complie-time validation functionality just by copying whatever’s in the current `URL.init?(string: String)` function.
> 
> - Dave Sweeris
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161219/9c957ae3/attachment.html>


More information about the swift-evolution mailing list