Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager via the forum messaging feature. When contacting the review manager directly, please keep the proposal link at the top of the message.
Try it out
To try out this feature, you can download a toolchain for Linux or macOS.
What goes into a review?
The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:
What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available here.
I was going to say this doesn’t seem that necessary, especially if the workaround is to just add parentheses, but if it works for InlineArray then it should be made consistent.
Would this new feature enable someone (or the standard library) to add an Array.init that behaves like the motivating InlineArray.init? The examples all seem to be of trailing closures that don’t take any arguments.
This fixes a hole in the language with no adverse side effects that I'm aware of. Obvious +1.
It used to be the case that you couldn't write an extension with type sugar either:
// used to have to write this
extension Array where Element == Int { ... }
// used to be an error, now it isn't
extension [Int] { ... }
So this is just another one of those nice changes that smooth out weird rough edges in the language that shouldn't exist. If we care about having type sugar as a first-class way of writing arrays and dictionaries, then we should care about making sure you can substitute one for the other unless there's some compelling reason that should be disallowed. In this case, no such compelling reason exists—I imagine that it was just an oversight in the type checker when it tries to detect if what was parsed as a literal was actually type sugar in expression position.
As far as I'm concerned, this is really a bug fix, but it's going through Evolution because of the possibility of ever-so-minor source compatibility questions. Those seem unlikely to impact real code (let's check with the source compatibility suite to be sure).
It will support trailing closures with arguments. An Array analog of that InlineArray.init (which passes the current index to the closure) could conceivably be something like:
extension Array {
init(generate: (Int) -> Element?) {
self = []
var index = 0
while let element = generate(index) {
append(element)
index += 1
}
}
}
let powersOfTwo = [Int] { index in
guard index < 10 else { return nil }
return 1 << (index + 1)
}
To me, the @ArrayBuilder example is a stronger motivating use case, but it’s certainly reasonable and self-consistent for the language to support all of these use cases.
For initializers, this only affects sugared array and dictionary types using square brackets ([String], [String: String]).
For literals, the only possible interaction is if you can come up with a way to get a bare array literal expression followed by a callAsFunction call (with a trailing closure) to be inferred as a Set literal. I couldn’t come up an example where that works today:
extension Set {
func callAsFunction(calledAsFunction: Bool) -> Set {
print(calledAsFunction)
return self
}
func callAsFunction(_ closure: () -> Void) -> Set {
closure()
return self
}
}
// error: cannot call value of non-function type '[Int]
let value: Set<Int> = [1, 2, 3](calledAsFunction: true)
// error: cannot call value of non-function type '[Int]
let value2: Set<Int> = [1, 2, 3]({ print("test") })
// Following this proposal, this would still be an error:
// error: cannot call value of non-function type '[Int]
let value2: Set<Int> = [1, 2, 3] { print("test") }
What would you like to enable? Only Array and Dictionary have the sugared type syntax ([String], [String: String]) that is addressed in this proposal.
I think there's a bit of a misunderstanding of the goals of this specific proposal, possibly because it originated from the earlier @ArrayBuilder pitch (and uses that in some of its examples). This proposal is just a language change targeting a hole in the way type sugar/collection literals are parsed. It is only handling the following cases and making them compile with the expected behavior:
As we're getting into the second half of the review period, would be curious if any folks have additional feedback, and particularly on the (possibly only theoretical) source break that can occur in the context of result builders.