[swift-evolution] [pitch] Eliminate the "T1 -> T2" syntax, require "(T1) -> T2"

Joe Groff jgroff at apple.com
Fri Apr 15 12:41:41 CDT 2016


> On Apr 15, 2016, at 8:29 AM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> On Apr 14, 2016, at 10:50 PM, Chris Lattner <clattner at apple.com> wrote:
>> On Apr 14, 2016, at 10:40 PM, John McCall <rjmccall at 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. 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.

-Joe


More information about the swift-evolution mailing list