> Am 27.05.2016 um 21:41 schrieb Matthew Johnson <[email protected]>:
>
>
>> On May 27, 2016, at 2:26 PM, Austin Zheng <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> Thanks for all your thoughtful replies.
>>
>> I'm not really invested in arguing this much further, as it's mainly a
>> stylistic thing that I could live with and also probably a hopeless battle
>> (given how everyone else disagrees).
>
> I’ve been in the same place with some of the other stylistic battles. :-)
>
>> But I would like to address a few final points.
>>
>> (inline)
>>
>> On Fri, May 27, 2016 at 12:06 PM, Matthew Johnson <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>
>> Turning it around, we don’t have to put parentheses around function types
>> and nobody complains about it being problematic even for higher-order
>> functions with several steps before the final result.
>>
>> Function types have a very regular syntax, especially now that 0066 was
>> accepted (which, I admit, was very controversal itself):
>>
>> ( <one or more types> ) -> (tuple)
>> or
>> ( <one or more types> ) -> SingleTypeWithNoSpaces
>> or
>> ( <one or more types> ) -> GenericType<All, Spaces, Are, Inside, The,
>> Brackets>
>>
>> A function type is very easy to visually parse: combine the argument parens,
>> arrow thing, and the single type that it returns. That being said, complex
>> function types are probably the most difficult types to read in a function
>> declaration today, even with this regular structure.
>>
>> The proposed syntax, which allows arbitrary whitespace outside the context
>> of a delimiter, would require the user to scan the string comprising the
>> existential type expression for a very common sigil in order to locate the
>> endpoint: '=' for variable declarations (which admittedly isn't that bad) or
>> ',' for functions (which is a lot worse). Not to mention the point Joe Groff
>> brought up about a generic function with a generic where clause returning an
>> existential and having everything devolve into a undifferentiated soup of
>> identifiers.
>>
>>
>> Does anyone know if users of Ceylon or other languages with the
>> unparenthesized syntax find it problematic? How would they feel about being
>> required to use parentheses?
>>
>>>
>>> We're trying to establish a syntax that will hopefully be used for things
>>> significantly more complicated than tuple definitions, which are just a
>>> list of types. I think readability is a major concern. Typealiases should
>>> be supported, but they shouldn't be required to make the feature useable.
>>
>> I agree, but I don’t think they would be required to make the feature
>> useable just because parentheses are not required. If a developer or team
>> thinks they are required for clarity / readability, etc they are free to use
>> them. This is a style issue that should be addressed by a linter, not the
>> formal syntax of the language.
>>
>> It is a style issue, but so is (Int) -> T versus Int -> T and a lot of other
>> language details like trailing commas in argument lists, of which the core
>> team seems to feel pretty strongly about.
>
> Fair enough! :-)
>
>>
>>
>>>
>>> Finally, wouldn't we need some delimiter for nested existential definitions
>>> anyways? Now you have the confusing situation where the outside definition
>>> has no delimiters, but the inside ones do:
>>>
>>> // Why does the inner existential look fundamentally different than the
>>> outer one?
>>> // Not to mention, visually parsing the boundaries of this type when you
>>> look at it in a function signature
>>> let x : Protocol1, Protocol2, (Protocol 3 where .Foo == Int) where
>>> Protocol2.Bar : Baz
>>
>> Nested existentials are supported not because it would ever be a good idea
>> to actually write them. They are supported to allow composition of
>> existentials:
>>
>>
>> Perhaps then we should only allow existentials to be nested if a typealias
>> is used. Swift is, after all, an opinionated language. If a feature is in
>> the language, it should either be usable directly in an ergonomic way, or it
>> shouldn't be there at all. Having a self-admittedly "bad" way to nest
>> literal existential expressions just for consistency when typealiases are
>> the preferred use case is very unlike Swift.
>
> I think self-admittedly “bad” is a bit of a stretch. I do *think* the
> conventional style would be to match the rest of Swift. But I’m not
> *certain* of that. I could see the style Thorsten posted being conventional
> and useful in some cases:
>
> let x : Protocol1 & (Protocol2 where .Bar : Baz) & (Protocol 3 where .Foo ==
> Int)
>
> I think direct `&` syntax will be most useful when combining two (or maybe
> three) protocols with no associated types: `Protocol1 & Protocol2` (whether
> or not we require parens).
>
> Generally I hope we will use type aliases for existentials that are this
> complex just as we usually bind names to parts of expressions rather than
> writing large one-liners.
>
> One issue I’m not sure we have addressed is the case of an existential for a
> single protocol with an associated type constraint `Protocol where .Foo =
> Int`. Before we settle on a syntax we should be sure that this doesn’t
> introduce any ambiguity.
Austin raised the point (or reminded of Joe’s raising the point) of possible
problems when returning constrained existentials from generic functions:
func foo<P, Q>(p: P, q: Q) -> any<Collection where .Element == P> where P:
Equatable { … }
would require parentheses when using `&` instead of any<>
func foo<P, Q>(p: P, q: Q) -> (Collection where .Element == P) where P:
Equatable { … }
This would even be the case if there was no constraint on P:
func foo<P, Q>(p: P, q: Q) -> (Collection where .Element == P) { … }
An alternative would be to use `with` for existentials instead of `where`:
func foo<P, Q>(p: P, q: Q) -> Collection with .Element == P where P: Equatable
{ … }
But even then this would be more readable either with parentheses (now just as
a matter of style) or a line break:
func foo<P, Q>(p: P, q: Q) -> Collection with .Element == P
where P: Equatable { … }
-Thorsten
>
> -Matthew
>
>>
>> typealias P3Int = Protocol 3 where .Foo == Int
>> let x : Protocol1, Protocol2, P3Int where Protocol2.Bar : Baz
>>
>> If you are writing the entire type in a single location I expect the
>> conventional style to be like this:
>>
>> let x : Protocol1, Protocol2, Protocol 3 where Protocol2.Bar : Baz,
>> Protocol3.Foo == Int
>>
>> With all associated types constraints in a single `where` clause as we other
>> places they are written in Swift.
>>
>> Maybe I am wrong about that and a different conventional style would emerge
>> (for example, where clauses clustered with the related protocol).
>>
>> But *requiring* parentheses is really orthogonal to the style issue of where
>> and when it is considered *advisable* to use them.
>>
>> -Matthew
>>
>>>
>>> I hope that explains my reasoning.
>>>
>>> Best,
>>> Austin
>>>
>>>
>>>> On May 27, 2016, at 9:28 AM, Matthew Johnson <[email protected]
>>>> <mailto:[email protected]>> wrote:
>>>>
>>>>
>>>>
>>>> Sent from my iPad
>>>>
>>>> On May 27, 2016, at 11:18 AM, Austin Zheng <[email protected]
>>>> <mailto:[email protected]>> wrote:
>>>>
>>>>> Here's a strawman idea.
>>>>>
>>>>> What if we go with '&' and 'where', but we enclose the whole thing in
>>>>> parentheses?
>>>>>
>>>>> (class & Protocol1 & Protocol2 where .Foo == Int, .Bar : Baz)
>>>>>
>>>>> There are a couple of reasons I propose this syntax:
>>>>>
>>>>> - It makes it very clear where the definition of the type begins and
>>>>> ends. I understand people really despise angle brackets, but I really
>>>>> want some way to visually delineate the boundaries of the type. Plus, I
>>>>> imagine it makes syntax a little easier to parse and preemptively forbids
>>>>> some ambiguities.
>>>>>
>>>>> - It's a structural, not nominal, type, like a tuple, so it uses parens
>>>>> as well. This reserves "<" and ">" for generic types.
>>>>>
>>>>> - The '&' is easily understood - "Protocol1" *and* "Protocol2". It's also
>>>>> a signal that order doesn't matter - just like how order matters with
>>>>> things that use commas, like argument lists, tuples, and array members,
>>>>> order doesn't generally matter with bitwise or logical 'and' operators.
>>>>>
>>>>> - If we ever decide to have union types, we have a very elegant third
>>>>> form of nominal type syntax that naturally falls out: (MyClass1 |
>>>>> MyClass2 | MyClass3).
>>>>>
>>>>> Thoughts?
>>>>
>>>> Generally in favor. But I would not require the parentheses. I believe
>>>> they would be allowed optionally automatically, just as (Int) is the same
>>>> as Int (because single element tuples don't exist and the underlying type
>>>> is used directly instead). It seems better to leave parentheses up to a
>>>> matter of style.
>>>>
>>>>
>>>>>
>>>>> Austin
>>>>>
>>>>>
>>>>>> On May 27, 2016, at 9:07 AM, Thorsten Seitz via swift-evolution
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>
>>>>>>
>>>>>>> Am 27.05.2016 um 16:54 schrieb Matthew Johnson <[email protected]
>>>>>>> <mailto:[email protected]>>:
>>>>>>>
>>>>>>>>
>>>>>>>> On May 27, 2016, at 8:18 AM, Thorsten Seitz via swift-evolution
>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>
>>>>>>>> Personally I think `&` is more lightweight (and it is established in
>>>>>>>> other languages like Ceylon and Typescript) and `where` is more
>>>>>>>> expressive (and established in Swift for introducing constraints), so
>>>>>>>> I would stay with these.
>>>>>>>
>>>>>>> I agree. If we can make `&` with `where` work syntactically it would
>>>>>>> be nice to go in this lighter weight direction. If we decide to do
>>>>>>> that the question then becomes what to do with `protocol`. Would it be
>>>>>>> feasible to replace it with `&` in Swift 3 if we decide on that
>>>>>>> direction?
>>>>>>
>>>>>> Yep. `protocol` should be replaced with `&` in that case.
>>>>>>
>>>>>> -Thorsten
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> -Thorsten
>>>>>>>>
>>>>>>>>
>>>>>>>>> Am 27.05.2016 um 14:34 schrieb Vladimir.S <[email protected]
>>>>>>>>> <mailto:[email protected]>>:
>>>>>>>>>
>>>>>>>>> Btw, in case we have `where` keyword in syntax related to
>>>>>>>>> types/protocols (when defining constrains. and not some symbol like
>>>>>>>>> '>>'.. don't know, for example), why we can't have 'and' keyword also
>>>>>>>>> when discuss the syntax of type/protocol conjunction?
>>>>>>>>> I.e.
>>>>>>>>>
>>>>>>>>> let x: P and Q
>>>>>>>>> let x: P and Q where P.T == Q.T
>>>>>>>>> let x: P and Q and R
>>>>>>>>>
>>>>>>>>> or, for consistency, as I understand it, we should have
>>>>>>>>> let x: P & Q >> P.T == Q.T
>>>>>>>>>
>>>>>>>>> On 27.05.2016 11:55, Thorsten Seitz via swift-evolution wrote:
>>>>>>>>>> We could just write
>>>>>>>>>>
>>>>>>>>>> let x: P & Q
>>>>>>>>>> instead of
>>>>>>>>>> let x: Any<P, Q>
>>>>>>>>>>
>>>>>>>>>> let x: Collection where .Element: P
>>>>>>>>>> instead of
>>>>>>>>>> let x: Any<Collection where .Element: P>
>>>>>>>>>>
>>>>>>>>>> let x: P & Q where P.T == Q.T
>>>>>>>>>> instead of
>>>>>>>>>> let x: Any<P, Q where P.T == Q.T>
>>>>>>>>>>
>>>>>>>>>> let x: P & Q & R
>>>>>>>>>> instead of
>>>>>>>>>> let x: Any<P, Q, R>
>>>>>>>>>>
>>>>>>>>>> let x: Collection
>>>>>>>>>> instead of
>>>>>>>>>> let x: Any<Collection>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> This would avoid the confusion of Any<T1, T2> being something
>>>>>>>>>> completely
>>>>>>>>>> different than a generic type (i.e. order of T1, T2 does not matter
>>>>>>>>>> whereas
>>>>>>>>>> for generic types it is essential).
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -Thorsten
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Am 26.05.2016 um 20:11 schrieb Adrian Zubarev via swift-evolution
>>>>>>>>>>> <[email protected] <mailto:[email protected]>
>>>>>>>>>>> <mailto:[email protected]
>>>>>>>>>>> <mailto:[email protected]>>>:
>>>>>>>>>>>
>>>>>>>>>>> Something like |type<…>| was considered at the very start of the
>>>>>>>>>>> whole
>>>>>>>>>>> discussion (in this thread
>>>>>>>>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016523.html
>>>>>>>>>>>
>>>>>>>>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016523.html>>),
>>>>>>>>>>> but it does not solve the meaning of an existential type and also
>>>>>>>>>>> might
>>>>>>>>>>> lead to even more confusion.
>>>>>>>>>>>
>>>>>>>>>>> From my perspective I wouldn’t use parentheses here because it
>>>>>>>>>>> looks more
>>>>>>>>>>> like an init without any label |Type.init(…)| or |Type(…)|. I could
>>>>>>>>>>> live
>>>>>>>>>>> with |Any[…]| but this doesn’t look shiny and Swifty to me. Thats
>>>>>>>>>>> only my
>>>>>>>>>>> personal view. ;)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Adrian Zubarev
>>>>>>>>>>> Sent with Airmail
>>>>>>>>>>>
>>>>>>>>>>> Am 26. Mai 2016 bei 19:48:04, Vladimir.S via swift-evolution
>>>>>>>>>>> ([email protected] <mailto:[email protected]>
>>>>>>>>>>> <mailto:[email protected]
>>>>>>>>>>> <mailto:[email protected]>>) schrieb:
>>>>>>>>>>>
>>>>>>>>>>>> Don't think {} is better here, as they also have "established
>>>>>>>>>>>> meaning in
>>>>>>>>>>>> Swift today".
>>>>>>>>>>>>
>>>>>>>>>>>> How about just Type(P1 & P2 | P3) - as IMO we can think of such
>>>>>>>>>>>> construction as "creation" of new type and `P1 & P2 | P3` could be
>>>>>>>>>>>> treated
>>>>>>>>>>>> as parameters to initializer.
>>>>>>>>>>>>
>>>>>>>>>>>> func f(t: Type(P1 & P2 | P3)) {..}
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 26.05.2016 20:32, L. Mihalkovic via swift-evolution wrote:
>>>>>>>>>>>> > How about something like Type{P1 & P2 | P3} the point being that
>>>>>>>>>>>> > "<...>" has an established meaning in Swift today which is not
>>>>>>>>>>>> > what is expressed in the "<P1,P2,P3>" contained inside Any<P1,
>>>>>>>>>>>> > P2,P3>.
>>>>>>>>>>>> >
>>>>>>>>>>>> >> On May 26, 2016, at 7:11 PM, Dave Abrahams via swift-evolution
>>>>>>>>>>>> >> <[email protected] <mailto:[email protected]>
>>>>>>>>>>>> >> <mailto:[email protected]
>>>>>>>>>>>> >> <mailto:[email protected]>>> wrote:
>>>>>>>>>>>> >>
>>>>>>>>>>>> >>
>>>>>>>>>>>> >>> on Thu May 26 2016, Adrian Zubarev <[email protected]
>>>>>>>>>>>> >>> <mailto:[email protected]>
>>>>>>>>>>>> >>> <mailto:[email protected]
>>>>>>>>>>>> >>> <mailto:[email protected]>>> wrote:
>>>>>>>>>>>> >>>
>>>>>>>>>>>> >>> There is great feedback going on here. I'd like to consider a
>>>>>>>>>>>> >>> few things here:
>>>>>>>>>>>> >>>
>>>>>>>>>>>> >>> * What if we name the whole thing `Existential<>` to sort out
>>>>>>>>>>>> >>> all
>>>>>>>>>>>> >>> confusion?
>>>>>>>>>>>> >>
>>>>>>>>>>>> >> Some of us believe that “existential” is way too theoretical a
>>>>>>>>>>>> >> word to
>>>>>>>>>>>> >> force into the official lexicon of Swift. I think “Any<...>” is
>>>>>>>>>>>> >> much
>>>>>>>>>>>> >> more conceptually accessible.
>>>>>>>>>>>> >>
>>>>>>>>>>>> >>>
>>>>>>>>>>>> >>> This would allow `typealias Any = Existential<>`. * Should
>>>>>>>>>>>> >>> `protocol A: Any<class>` replace `protocol A: class`? Or at
>>>>>>>>>>>> >>> least
>>>>>>>>>>>> >>> deprecate it. * Do we need `typealias AnyClass = Any<class>`
>>>>>>>>>>>> >>> or do we
>>>>>>>>>>>> >>> want to use any class requirement existential directly? If
>>>>>>>>>>>> >>> second, we
>>>>>>>>>>>> >>> will need to allow direct existential usage on protocols
>>>>>>>>>>>> >>> (right now we
>>>>>>>>>>>> >>> only can use typealiases as a worksround).
>>>>>>>>>>>> >>
>>>>>>>>>>>> >> --
>>>>>>>>>>>> >> Dave
>>>>>>>>>>>> >>
>>>>>>>>>>>> >> _______________________________________________
>>>>>>>>>>>> >> swift-evolution mailing list
>>>>>>>>>>>> >> [email protected] <mailto:[email protected]>
>>>>>>>>>>>> >> <mailto:[email protected]
>>>>>>>>>>>> >> <mailto:[email protected]>>
>>>>>>>>>>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>>> > _______________________________________________
>>>>>>>>>>>> > swift-evolution mailing list
>>>>>>>>>>>> > [email protected] <mailto:[email protected]>
>>>>>>>>>>>> > <mailto:[email protected]
>>>>>>>>>>>> > <mailto:[email protected]>>
>>>>>>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>>> >
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>>>>> <mailto:[email protected]
>>>>>>>>>>>> <mailto:[email protected]>>
>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>>>> <mailto:[email protected]
>>>>>>>>>>> <mailto:[email protected]>>
>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>> _______________________________________________
>>>>>>>> swift-evolution mailing list
>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>
>>
>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution