> On May 27, 2016, at 2:26 PM, Austin Zheng <[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. -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
