[swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

Austin Zheng austinzheng at gmail.com
Fri May 27 14:26:30 CDT 2016


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). But I would like to address a few
final points.

(inline)

On Fri, May 27, 2016 at 12:06 PM, Matthew Johnson <matthew at anandabits.com>
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.


>
>
> 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.


> 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 <matthew at anandabits.com>
> wrote:
>
>
>
> Sent from my iPad
>
> On May 27, 2016, at 11:18 AM, Austin Zheng <austinzheng at gmail.com> 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 <
> swift-evolution at swift.org> wrote:
>
>
> Am 27.05.2016 um 16:54 schrieb Matthew Johnson <matthew at anandabits.com>:
>
>
> On May 27, 2016, at 8:18 AM, Thorsten Seitz via swift-evolution <
> swift-evolution at swift.org> 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 <svabox at gmail.com>:
>
> 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
> <swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>>:
>
> 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
> >),
> 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
> (swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>) 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 <
> swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>> wrote:
> >>
> >>
> >>> on Thu May 26 2016, Adrian Zubarev <swift-evolution at swift.org <
> mailto:swift-evolution at swift.org <swift-evolution at swift.org>>> 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
> >> swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>
> >> https://lists.swift.org/mailman/listinfo/swift-evolution
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <swift-evolution at swift.org>>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org
> <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
>
>
> _______________________________________________
> 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
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160527/cb23f759/attachment.html>


More information about the swift-evolution mailing list