> On Apr 15, 2016, at 2:47 PM, Joe Groff <jgr...@apple.com> wrote: >> On Apr 15, 2016, at 11:43 AM, John McCall <rjmcc...@apple.com> wrote: >>> On Apr 15, 2016, at 10:41 AM, Joe Groff <jgr...@apple.com> wrote: >>>> On Apr 15, 2016, at 8:29 AM, John McCall via swift-evolution >>>> <swift-evolution@swift.org> wrote: >>>> >>>>> On Apr 14, 2016, at 10:50 PM, Chris Lattner <clatt...@apple.com> wrote: >>>>> On Apr 14, 2016, at 10:40 PM, John McCall <rjmcc...@apple.com> wrote: >>>>>>>> To me, the unparenthesized style suggests that the input and output >>>>>>>> are peers, which feels more natural for the sort of value-to-value >>>>>>>> transform/predicate where this most commonly occurs. Parenthesizing >>>>>>>> the input feels fussier, which contributes to a sense that the >>>>>>>> argument is just one component to producing the result. >>>>>>>> The parentheses are grammatically unnecessary in most cases (by >>>>>>>> frequency of use in higher-use programming, not by feature count). >>>>>>> >>>>>>> I agree with your point that many simple higher order programming >>>>>>> examples (e.g. map, filter, etc) take a single argument. That said, I >>>>>>> don’t agree that this means that we should syntactically privilege this >>>>>>> special case. >>>>>> >>>>>> "Special case" is a loaded phrase. Why is it a special case as a >>>>>> parameter if it isn't a special case as a result? >>>>> >>>>> Because, as I tried to explain in my original post, parameters *are* a >>>>> special case. The result type of a function is just a type. The >>>>> parameter list allows things that types do not: default arguments and >>>>> variadics. >>>> >>>> Default arguments are not allowed in the type grammar. Nor are different >>>> internal vs. external labels. >>>> >>>>> As a concrete example, surely you aren’t arguing that we should support: >>>>> >>>>> let x : Int… -> Int >>>>> >>>>> are you? >>>> >>>> No, but that's because the ... is a reference to the rest of the tuple and >>>> doesn't read correctly outside of one. >>>> >>>>>>>> I guess the flip side is that call and declaration syntax both require >>>>>>>> parentheses (unless the only argument is a trailing closure), but >>>>>>>> again, we had strong justifications for that: declarations would >>>>>>>> always be ambiguous without parens, and calls would have serious >>>>>>>> problems (and the style-wars factor would be much larger, especially >>>>>>>> now with mandatory keyword arguments by default). >>>>>>> >>>>>>> Right, but regardless of *why* we always require parens on Decls and >>>>>>> ApplyExprs, we really do (and that isn’t going to change). Being >>>>>>> consistent between func decls and function types is quite important IMO. >>>>>> >>>>>> So we should require function argument labels in function types? >>>>> >>>>> Uhm, yes, we already do. In: >>>>> >>>>> let x : (a : Int) -> Float >>>>> let y : (Int) -> Float >>>>> let z : Int -> Float >>>>> >>>>> x and y have different (but compatible) types. y and z have identical >>>>> types (sugared differently). >>>> >>>> When I said "function type", I was referring to this production in the >>>> type grammar, not the type signature component of function declarations. >>>> I'm not sure how I could've been clearer on that without actually using >>>> the names of grammatical productions. >>>> >>>> My point was that allowing a function type to be written as "(Int) -> >>>> Float" is already inconsistent with function declarations, because that is >>>> not legal function declaration syntax; you would have to write "(_ : Int) >>>> -> Float". >>>> >>>> The current language composes naturally here, and your proposal feels like >>>> an odd extra rule. >>> >>> I feel like the current language no longer represents our reality, though >>> (or at least, our current ideal vision for reality). We've pretty >>> thoroughly broken the "functions have one argument" model. >> >> I don't see this syntax as an offshoot of the "functions always have one >> argument" model. I agree that that model is dead. >> >> However, I don't think users require its death to be underlined and written >> in bold; it only ever surfaced to them in bugs anyway. But many functions >> do, nonetheless, have only one argument; and because of another change to >> the model, where argument labels are becoming part of the function's name >> and not its type, that argument can be written as just a type. >> >> So to me, this question is whether we add a weird special-case rule that >> mandates the use of parentheses because they're required in a bunch of more >> complex but less common situations. >> >>> Changing the type grammar to reflect this seems good to me. I would think >>> of it as changing the function type grammar to: >>> >>> function-type ::= '(' (type (',' type)*)? ')' '->' type >>> >>> which, since the argument list can containing 0, 1, or many individual >>> arguments, makes the parens more grammatically necessary. >> >> This is tautological. > > I don't think it is just a tautology. Without encoding it in the grammar, > there's an ambiguity between tuples and multiple arguments; () -> T could > mean either "takes a single () argument" or "takes no arguments". We could > "obviously" disambiguate in favor of the latter interpretation, but then > you're introducing special cases in the other direction to keep the U -> T > syntax working.
This is a fair point, and one which would come up with (Int,Int) -> Float as well — maybe the user really does mean to pass a single value that's an (Int,Int) pair. I'm not sure this really works out to being a special case at the user level, though, since in either model the user trying to write a function that takes a single tuple-typed parameter simply has to introduce the extra parens: (()) -> Float or ((Int, Int)) -> Float. (Assuming that the type system preserves that structure in any way, of course.) John. _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution