[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