> For clarity's sake, there's really two syntactic issues that I think would be 
> good to address. The first, which I think is the far bigger problem, which is 
> that right now a list of params with closures is very hard to read. For 
> example, this requires mental effort to decode whether this is returning an 
> Int, or a closure returning an Int:
> 
> func makeIncrementer(forIncrement amount: Int) -> () -> Int {
> }
I look at currying like a right-associative operator (like the ternary 
operator, or assignments in languages like C). There is a function that takes 
no arguments and returns an int, that you get from a function that takes an int 
argument.

Changing this to say
> func makeIncrementer(forIncrement amount: Int) -> func () -> Int {
feels like it is changing the behavior to that of a non-associative operator. 

One interesting result would be if by removing the ternary operator as it 
stands today and changing how currying heppens, swift wound up having no right 
associative operators left in core.
> And the second being that stylistically, having the params on the inside of 
> the closure is breaking precedent of params outside of the block of code 
> without gaining much. 
> Perhaps we could adopt the Obj-C ^ as a closure indicator. I think with 
> existing Swift syntax, a lot of the confusion that caused 
> www.fuckingblocksyntax.com <http://www.fuckingblocksyntax.com/> would be 
> avoided.
<snip>
> makeIncrementer(forIncrement: ^(number: Int) {
>    if (number == 3) { return true }
> })
Why does the block now have to be declared within the function parameters?
Why do I have to declare the type of number now?
Why do I *not* have to declare the return type as being a boolean?
Would this syntax still support single expression implicit returns, e.g. 
current Swift

> [1,2,3].map() { number in number == 3 }
$R0: [Bool] = 3 values {
  [0] = false
  [1] = false
  [2] = true
}
> By having ^ mark an upcoming closure, I think it's a lot easier to follow 
> what's going on with declarations because as you read left to right, you're 
> prepped that a closure syntax is coming up as you read left to right. It also 
> allows you to keep the params outside of the closure, which I think is a win. 
> Closure params would also have the same syntax everywhere, and be extremely 
> similar to normal method calls which would be easier for new Swift users. 
There are three pieces at play here IMHO:
1. How functions (global and on types) are declared and implemented
2. How function specifications are indicated as types
3. How anonymous functions are declared and implemented

When I declare a global or type-specific function, I can specify its name and 
arguments, assign external names to them (as well as internal names), and 
declare my return value. The types, even if generic, must be known for the 
function implementation to pass semantic checks.

The syntax for functions as types are really just a list of input and output 
types. There are not (for instance) named parameter requirements on the 
implementing functions. But the input and return types must be known to declare 
a new function type.

Anonymous functions assume a great deal of type information from the context in 
which they are used. This is why you can get away with not declaring input 
types or even input names (using $0, $1, etc), the return type or even if a 
value is returned. The code is mapped into the context it is needed, then 
semantic evaluation is done.

You are attempting to change #2 and #3 at the same time, when really they have 
quite different needs. I assume the reason anonymous functions (aka closures in 
Swift) have their argument names on the inside of the block is because the 
argument names have no external bearing whatsoever. Considering I may or may 
not declare type information or even give all the parameters names, this makes 
a certain kind of sense. If you were to move the argument names outside the 
block, you would need a syntax specifically for that. There are enough options 
that reusing the same base syntax between 1 and 3 or 2 and 3 would likely just 
_feel_ wrong.

There are enough rules about escape analysis to possibly make sense to have 
function blocks, do blocks, repeat blocks, switch blocks, for…in blocks, etc 
all be considered ‘kinds’ of blocks, and for closure blocks to be on that list. 
It possibly makes sense for them to have a keyword just like all the other 
blocks to simplify compiler and human visual parsing. But I don’t envy the 
effort of redesigning and redecorating that particular bike shed :-)

-DW
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to