[swift-evolution] Proposal: 'T(literal)' should construct T using the appropriate literal protocol if possible

Matthew Johnson matthew at anandabits.com
Sat Jun 4 09:00:56 CDT 2016

> On Jun 3, 2016, at 9:30 PM, John McCall <rjmccall at apple.com> wrote:
>> On Jun 3, 2016, at 7:08 PM, Matthew Johnson <matthew at anandabits.com> wrote:
>>> On Jun 3, 2016, at 8:11 PM, John McCall <rjmccall at apple.com> wrote:
>>>> On Jun 3, 2016, at 5:13 PM, Matthew Johnson <matthew at anandabits.com> wrote:
>>>> On Jun 3, 2016, at 6:23 PM, John McCall <rjmccall at apple.com> wrote:
>>>>>>> On Jun 3, 2016, at 4:07 PM, David Sweeris <davesweeris at mac.com> wrote:
>>>>>>> On Jun 3, 2016, at 16:17, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
>>>>>>> Using an external parameter label in a declaration and allowing it to be omitted at the call site does not feel like the right answer to me.  I think we can find a better way to present this syntactically.
>>>>>> +eleventy gajillion
>>>>> I'm actually quite happy with the user-facing aspects of the current literal protocols and see zero reason to update them for this, so if that's the choice, I'll just leave this aside.
>>>> Are you suggesting that preserving the current syntax of the literal protocols is more important than fixing this behavior so it works like most people seem to expect?  Why not be open to other syntactic solutions? 
>>> I think fixing the behavior is good, and I stand by this proposal.  
>> I agree fixing it is good and we should do it.  I’m just trying to explore the solution space to see if there are any alternatives that might be more appealing.  Clearly you’ve thought about this a lot but it’s a new topic to consider for the rest of us.  :)
> I'm sorry if I've come across as frustrated.  It's easy for me to forget that things that I consider well-settled haven't always been covered in depth here.  The community is not intentionally re-inventing things for no purpose, it's making a genuine effort to explore the constraints on a part of the language that it isn't familiar with the rationale for.

No problem.  I know it’s not fun to revisit hard-thought decisions that you’re happy with! :)  And I can see how it feels like we’re trying to do that here.  That said, these discussions are the best way for the community to become familiar with some of the rationale for the way things currently are.  :)

>>> There is, however, nothing glaringly wrong with the literal protocols.  They do not need to redesigned simply because we found a syntactic interaction that needs to be cleaned up.
>>> There are good reasons the protocols have evolved the way they have.  The labels clearly mark the purpose of each initializer and distinguish one from another on types that support multiple literal kinds.  The labels also clearly indicate that the initializers are not intended for general use.  The argument(s) to the initializer do not always represent a single value of literal type.  Some protocols provide multiple initializers, and it is quite possible that that will become gradually more common as we explore ways to grant more flexibility to code outside of the standard library.  And we actually consider it good that you can invoke these initializers explicitly; it's only accidental use that we feel it's important to avoid, which labels provide excellent protection against.
>> If it is important that these initializers be callable directly I suppose the label is the only way to go.  I can’t think of a reason why this is necessary though.  I would consider it bad design for a type that expects to be initialized with an Int variable to require its callers to use the label, as opposed to providing an alternate initializer that doesn’t have a label with “literal” in its name.  Are there specific use cases where you think this capability is important or is it just the principle that you should be able to call any initializer you write?
> Partly that principle, but partly the ability to forward literal-initialization.  You can forward literal-initialization to, say, a BuiltinIntegerLiteralConvertible type by just appointing it your associated IntegerLiteralType, but if you're wrapping another type, that doesn't work.  For example:
>  struct MyValue : IntegerLiteralConvertible {
>    init(integerLiteral literal: JSONValue.IntegerLiteralType) {
>      json = JSONValue(integerLiteral: literal)
>    }
>    ...
>  }

What is the advantage of calling the literal JSONValue initializer here rather than a non-literal initializer that accepts JSONValue.IntegerLiteralType?  Is there something in the implementation that makes this more efficient?

If forwarding is the intended use for explicit calls, wouldn’t the `@literal` attribute attached to the type be an alternative way to address the forwarding use case?

Are there any non-forwarding use cases for explicit calls?

If forwarding is the only intended use case of explicit calls and `@literal` could cover that use case then the question (in my mind) is which principle do we hold more sacred?  The ability to call any initializer we write or the syntactic consistency that external argument labels are always required at the call site?  I admit this is partly an aesthetic concern…


> John.

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

More information about the swift-evolution mailing list