[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