Quite a lot of work has been done to implement recently accepted Swift Evolution proposals, as well as improving their diagnostics and error messages. Interestingly, some of this work has been done by first-time contributors, which is amazing to see!
Interested in sponsoring Swift Weekly Brief? Learn more here.
Episode 9: String Manifesto
This week JP Simard and Jesse Squires discuss the String Manifesto!
Commits and pull requests
Robert Widmann has redone exhaustiveness checking, fixing a lot of SR-bugs in the process.
The proposal is accepted, including the revision to change the method name from
swapAt(_:_)that came out of the Core Team meeting.
The consensus on
swift-evolutionwas to add the method, with division mostly on the naming of the method. The Core Team reviewed the proposed options as well as consulted the API design guidelines to resolve the issue.
Two important points from the guidelines serve to us well here:
“Omit all labels when arguments can’t be usefully distinguished”
“When the first argument forms part of a prepositional phrase, give it an argument label… An exception arises when the first two arguments represent parts of a single abstraction. In such cases, begin the argument label after the preposition, to keep the abstraction clear.”
The combination of these rules leads to the method name
swapAt(_:_:), which the Core Team believes was most in line with the guidelines.
In Swift 3, it is possible to modify a variable while it’s being used or modified by another part of the program. This can lead to unexpected and confusing results. It also forces a great deal of conservatism onto the implementation of the compiler and the standard libraries, which must generally ensure the basic soundness of the program (no crashes or undefined behavior) even in unusual circumstances.
We propose that Swift should instead enforce a general rule that potential modifications of variables must be exclusive with any other access to that variable.
Proposals in review
This proposal changes the
Sequenceto return an associated type, and adds a default implementation to
RangeReplaceableCollectionto return the same type as the filtered collection.
The recently accepted SE-0165 introduced a version of
Dictionarythat returned a
Dictionary. This had both performance and usability benefits: in most cases, a
Dictionaryis what the user wanted from the filter, and creating one directly from the filter operation is much more efficient than first creating an array then creating a
However, this does result in some inconsistencies. Users may be surprised that this one specific collection returns
Self, while other collections that would benefit from the same change still return
[Element]. And some collections, such as
String, might also benefit from usability and performance win similar to
Dictionary. Additionally, these wins will be lost in generic code – if you pass a
Dictionaryinto an algorithm that takes a
Sequence, then when you filter it, you will still get an
This proposal makes the package manager’s dependency resolution behavior clearer and more intuitive. It removes the pinning commands (
swift package pin&
swift package unpin), replaces the
swift package fetchcommand with a new
swift package resolvecommand with improved behavior, and replaces the optional
Package.pinsfile with a
Package.resolvedfile which is always created during dependency resolution.
There has once again been some discussion around
throws and the
Result type. Although we probably won’t see changes here in the near future, it’s interesting to see this keeps resurfacing and the ideas maturing.
Doug Gregor writes:
[..] the current error-handling system will not be going away, for the reasons Jaden has stated above.
Maybe we will grow typed throws at some point; maybe
Resultwill get added to the standard library with some nice affordances to map between
Result-producing types; but we’re well beyond the point where we can rip out major features that have been generally well-received.
In the earlier discussion on revamping
throws, John McCall writes:
We’ve definitely considered including a
Resulttype, but our sense was that in an ideal world almost no code would be using it. It’s hard to imagine an ordinary API that ought to be returning a
throwing, and once you’ve defined that away, the major remaining use case is just to shift computation around, like with a completion handler. That explicit computation-shifting pattern is something we’re hoping to largely define away with something like
await, which would leave
Resultas mostly just an implementation detail of such APIs. We didn’t want to spend a great deal of time designing a type that would end up being so marginal, especially if the changing role would lead us into different directions on the design itself. We also didn’t want to design a type that would become an obstacle to potential future language changes like, say, typed
The downside, of course, is that as long as we lack that
awaitdesign, computation-shifting isn’t real great.
And finally — Xcode might not be as genius as you think. 🤔