[swift-evolution] URL Literals

Rien Rien at Balancingrock.nl
Mon Dec 19 02:09:12 CST 2016


I like where this is going!
+1

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl




> On 19 Dec 2016, at 08:41, 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> 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



More information about the swift-evolution mailing list