[swift-evolution] [swift-evolution-announce] [Review] SE-0105: Removing Where Clauses from For-In Loops
Ryan Lovelett
swift-dev at ryan.lovelett.me
Thu Jun 23 08:42:46 CDT 2016
> What is your evaluation of the proposal?
Negative.
The “Motivation” logic seems incongruent possibly even contradictory.
The where syntax is cited as “… rarely used, [and] hard to discover ….”
while simultaneously a source of confusion to new developers. Taking
both statements together this proposal seems to be aimed at a sub-set of
a sub-set of developers. That alone would tell me this is a problem that
is not significant enough to warrant a change to Swift.
Unfortunately the statistics provided in the proposal heavily weigh
open-source Swift code and discount code written in closed-source
applications. My intuition, based on the volume of feedback provided on
the swift-evolution mailing list, tells me there is likely to be some
practical Swift code written in closed-source and enterprise
applications that is not being equally counted by the proposal
statistics. While the intent of the argument, that the syntax is not
widely used, is warranted I question these statistics and methods.
Additionally in the “confusion of use” example the `while` loop would
seem to be a moot point. It is my understanding that SE-0099 has already
removed the inconsistent `while` condition. Assuming that is true, it is
hard to believe that future new developers are going to be confused by a
syntax that they are unable to experience or use. If this assumption is
incorrect than I'd argue the correct course of action is to remove the
`while` loop behavior rather than for-in behavior.
Moving to more concrete code based examples. The introduction
effectively states that the proposal means to enforce a coding style or
convention by removal of another. This seems like something that should
be enforced by a linting tool, not the Swift compiler. To put a point on
this, I looked at one snippet of code cited in the “Frequency of Use”
section as a concrete example of what code would look like before and
after accepting the proposal [1].
Before:
/// Returns the greatest argument passed.
///
/// If there are multiple equal greatest arguments, returns the last
one.
public func max<T : Comparable>(_ x: T, _ y: T, _ z: T, _ rest: T...) ->
T {
var maxValue = max(max(x, y), z)
// In case `value == maxValue`, we pick `value`. See min(_:_:).
for value in rest where value >= maxValue {
maxValue = value
}
return maxValue
}
After:
/// Returns the greatest argument passed.
///
/// If there are multiple equal greatest arguments, returns the last
one.
public func max<T : Comparable>(_ x: T, _ y: T, _ z: T, _ rest: T...) ->
T {
var maxValue = max(max(x, y), z)
// In case `value == maxValue`, we pick `value`. See min(_:_:).
for value in rest {
guard value >= maxValue else { continue }
maxValue = value
}
return maxValue
}
It is not obvious to me how removing the `where` and adding the `guard`
“reduce[d] cognitive burden when interpreting intent”. Frankly in my
estimation it increased it. Now the for-in loop declaration has to be
read along with the trailing `guard` to interpret the intent of the
loop. I concede it is possible I just do not understand what is meant by
cognitive burden when interpreting intent. But I cannot shake the
feeling the argument is specious.
At this point I would like to draw attention to the fact that both the
“Before” and “After” syntax are fully supported in Swift right now. If
one is preferred by a developer as clearer both options are available.
And as I pointed out earlier could be enforced by a linting tool.
The motivation provided for the removal of the feature would seem to be
applicable to any number of existing Swift features. Not least of which
is the pattern matching for-in loop.
enum Thing { case One; case Two; case Three; case Four }
let foo: [Thing] = [.One, .Two, .One, .Three, .Four, .One]
for case .One in foo { print("Found a .One") }
I feel confident that most (all?) of the motivations applied by this
proposal would be equally applicable to the example pattern matching
for-in loop above. Especially the strongest of those arguments,
specifically that it elevates one style, the `continue` on condition,
above other related styles.
[1]
https://github.com/apple/swift/blob/a51aa91032ff7ba13bdc883122f4e8868aee6413/stdlib/public/core/Algorithm.swift#L47-54
> Is the problem being addressed significant enough to warrant a change to Swift?
No. In fact, I think that even the proposal itself says as much. The
proposal indicates it means to deprecate an available coding style. It
seems to me, as much as is practicable, style changes should be enforced
by something other than the Swift compiler.
The proposed `guard` syntax is complete today and is available as a
“work-around” for any of the conditions not elevated by this existing
Swift syntactic sugar feature.
Of course, other alternatives could be considered, such as expanding
this behavior to include `while`, `unless` and `until`. Though that
change seems pre-mature. A more pragmatic approach, since the change
would be additive, would be to defer until after Swift 3.
> Does this proposal fit well with the feel and direction of Swift?
No. Swift.org [1] lists as one of the “additional” features of the
language “Fast and concise iteration over a range or collection”.
Removing this feature does little to positively augment that feature.
Swift is opinionated. This is a good thing. It should have strong
opinions about safe, fast and expressive code. I do not believe the
existing for-in where clause syntax violates any of those features.
Furthermore it does nothing to increase the joy of writing Swift code
(an explicitly stated goal of Swift [1]).
[1] https://swift.org/about/
> If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I’ve never experienced this syntax in other languages. Though, coming
from C, it is a welcome improvement over that language’s syntax and
provides a lot of practical value.
> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
A fairly in-depth study. I looked at code that I have access to inside
of my work environment (as well as refactoring some for-in loops). I
also actively participated in the discussion on the swift-evolution
mailing lists.
Additionally, I discussed with co-workers and spouse. These discussions
were especially illuminating to me. Because many of my co-workers, as
well as my spouse, while being professional software developers, have
never worked with Swift. Not a single person I was able to discuss the
topic with was confused by the existing syntax regardless of their
experience level with Swift. Most shared confusion as to why the
proposed `guard` syntax was considered better at all. Most found `guard`
in and of itself to be more confusing than `where` combined with for-in.
Though it does strongly color my opinion of these changes it is, of
course, purely anecdotal.
More information about the swift-evolution
mailing list