[swift-evolution] URL Literals

Micah Hainline micah.hainline at gmail.com
Wed Dec 28 13:29:35 CST 2016


> SE-0039 says that resourceName should be a static-string-literal

It compiles just fine for me in my project. My next question was going
to be do we actually need a change in the language spec, or can we
call fixing that a bug, I think you're answering my question for me
before I even had to ask it!

On Wed, Dec 28, 2016 at 1:20 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Wed, Dec 28, 2016 at 2:08 PM, Micah Hainline via swift-evolution
> <swift-evolution at swift.org> wrote:
>>
>> As an aide to learning I've been playing around with implementation of
>> some of these concepts in the compiler and a few things popped up that
>> I'm not happy with.
>>
>> First, regarding the way #fileLiteral works, it necessitates the
>> addition of URL.init(fileReferenceLiteralResourceName:) which takes a
>> string but does not return an optional value. Fine, except that I
>> don't have to call #fileLiteral in my code to use that constructor, I
>> can also use it directly. While I could get compile-time checking on
>> the #fileLiteral, I can't on the direct constructor. Additionally, I
>> could use the direct constructor with any String, not just literals.
>> Internally that will call ```self = Bundle.main.url(forResource: name,
>> withExtension: nil)!``` and crash at runtime if it's not found.
>> Clearly we do not intend that init to be called directly, but that
>> isn't clear to new Swift user Jude Doe, who discovers the API as xe
>> autocompletes from Xcode.
>
>
> That could be fixed with documentation. This API design was reviewed and
> approved as part of SE-0039:
> https://github.com/apple/swift-evolution/blob/master/proposals/0039-playgroundliterals.md
>
>>
>> The second problem comes from String Interpolation. It's a basic
>> problem I think with anything that extends the concept of the
>> string_literal with additional requirements that need to be checked at
>> compile-time. Right now I can put in something like
>> ```#fileLiteral(resourceName: "\(myString)")```.
>
>
> Can you? SE-0039 says that resourceName should be a static-string-literal,
> which (unless I'm mistaken) should forbid interpolation.
>
>>
>> While at one level it
>> might seem nice to be able to construct this sort of thing, it's not
>> at all nice from a validation perspective.
>>
>> I think this has to be solved at a higher level, in the Lexer, making
>> a url literal a concept at that level, and fundamentally NOT a string
>> literal underneath, even if they shared some similar constructs.
>>
>> The Lexer would be able to see #url("https://\(host)") and say
>> "Invalid escape sequence in literal, \( is not understood as a url".
>> In fact, the URL literal should probably not need ANY escape sequences
>> or even the concept of escape sequences, since a double-quote is not a
>> legal character in a URL.
>>
>> I definitely think we should take this opportunity to identify that we
>> do NOT want to use string literal as it currently stands as a base
>> construct for other literal types. Quite possibly there's another,
>> more restricted concept that we can draw out of string literal that
>> would make a good base construct, but certainly not a string literal
>> with interpolation.
>>
>>
>>
>>
>> On Wed, Dec 28, 2016 at 8:01 AM, Jonathan Hull via swift-evolution
>> <swift-evolution at swift.org> wrote:
>> >
>> > On Dec 27, 2016, at 11:46 AM, David Sweeris <davesweeris at mac.com> wrote:
>> >
>> >
>> > On Dec 22, 2016, at 11:39 PM, Jonathan Hull <jhull at gbis.com> wrote:
>> >
>> >
>> > On Dec 20, 2016, at 12:29 PM, David Sweeris <davesweeris at mac.com> wrote:
>> >
>> >
>> > On Dec 20, 2016, at 2:11 AM, Jonathan Hull via swift-evolution
>> > <swift-evolution at swift.org> wrote:
>> >
>> > Yes, I agree.  I am excited to see what happens in phase 2.
>> >
>> > What I am suggesting here is slightly different. Basically being able to
>> > use
>> > RegEx (with capture groups) as a shorthand for a type composed of base
>> > literals. For example: (StringLiteral, [IntegerLiteral]). Named capture
>> > groups could even map to a dictionary literal.  I am using “RegEx goes
>> > Here”
>> > to represent RegEx in the examples below, but hopefully it will get it’s
>> > own
>> > literal type in Xcode (Imagine that replacing it here).
>> >
>> > func foo( _ param: “RegExGoesHere”) {…} //Definition uses a RegEx where
>> > the
>> > type would normally be
>> > foo(“my parseable string") //Calling with a string literal
>> >
>> > In this case, ‘param’ takes a string literal when called but the
>> > compiler
>> > converts it to a tuple of literals based on the regEx supplied and
>> > passes
>> > that tuple the function. The type/structure of the tuple is defined by
>> > the
>> > capture groups in the RegEx
>> >
>> > The parameter above would only allow string literals to be passed in,
>> > and
>> > would give a compiler error if you tried to pass a variable or if the
>> > string
>> > didn’t conform to the supplied RegEx.  To allow passing String variables
>> > you
>> > would have to add either ‘?’ or ‘!’ after the RegEx definition to handle
>> > the
>> > case where the value doesn’t conform.
>> >
>> > func foo( _ param: “RegExGoesHere”?) {…} //‘param' is nil if RegEx fails
>> > foo(myStringVar) //Calling
>> >
>> > func bar( _ param: “RegExGoesHere”!) {…} //fatal error if RegEx fails
>> >
>> > When a variable is passed, the RegEx is performed at runtime instead of
>> > compile time.
>> >
>> > Once you have this, the syntax to add new literal types/initializers
>> > falls
>> > out virtually for free.
>> >
>> >
>> > Is “RegExGoesHere” where the regex pattern goes, or where the string
>> > you’re
>> > trying to match goes? If it’s the latter, where does the pattern go? If
>> > it’s
>> > the former, where does the string you’re trying to match go?
>> >
>> >
>> > “RegExGoesHere” is where the pattern goes (instead of the type).  The
>> > string
>> > you are trying to match gets passed in as the parameter (e.g. “my
>> > parseable
>> > string”).
>> >
>> > Ah, ok, I think I understand what you’re saying now... You’re suggesting
>> > that instead of defining a custom type that conforms to “RegExLiteral”
>> > (or
>> > some other mechanism) and using that as the parameter’s type, you put
>> > your
>> > regex pattern as the type directly?
>> >
>> >
>> > Yes.  It is admittedly an advanced feature, but I think it would be a
>> > useful
>> > one.
>> >
>> > Thanks,
>> > Jon
>> >
>> >
>> >
>> > _______________________________________________
>> > swift-evolution mailing list
>> > swift-evolution at swift.org
>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>> >
>> _______________________________________________
>> 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