Issue #158 23 Apr 2020
Written by: Bas Broek
It still feels strange to me that every time I start writing this introduction, I think about the two weeks that have just flown by. It makes me appreciate how valuable time can be, and makes it feel worth it to provide all of you with an overview of what’s been happening in the “world of Swift”.
I also want to give another massive thank you to Kristaps, whose contributions are what make it possible for me to continue writing these issues.
I’d like to encourage you to stand still and reach out to or thank someone that has been helping you — speaking from my experience, it really makes a difference.
Interested in sponsoring Swift Weekly Brief? Learn more here.
- SR-12648 [Standard Library]
filteruses an intermediate array
- SR-12605 [Compiler]
#sourceLocationdoesn’t allow underscores in line numbers
- SR-12585 [Project Infrastructure]
Teach update-checkout to
News and community
Mattt announced DocTest,
an experimental tool for testing Swift example code in documentation. During
my brief foray in the land of Python, this is something I loved a lot about the
language. Mattt indicates Python’s
doctest indeed inspired this work, too.
Xcode 11.4.1 was released, including a fix for a compiler crash and removed an incorrectly emitted error for Swift packages.
The feedback was generally positive and the proposal has been accepted with one minor revision: the
main()signature will be throwing.
Proposals in review
This proposal adds a limited set of low-level atomic operations to the Standard Library, including native spellings for C++-style memory orderings. Our goal is to enable intrepid library authors to start building synchronization constructs directly in Swift.
In Swift today, application developers use dispatch queues and Foundation’s
NSLockingprotocol to synchronize access to mutable state across concurrent threads of execution.
However, for Swift to be successful as a systems programming language, it needs to also provide low-level primitives that can be used to implement such synchronization constructs (and many more!) directly within Swift.
This is the second review, with a modified proposal. The core team has considered the feedback from the first review and believes that:
- the underlying motivation for the proposal does merit a change to the language to better accommodate multiple trailing closures;
- the concerns around the original proposed syntax warranted a rethink of the proposed solution.
The proposal authors have a revised proposal that aims to address some of those concerns.
[..] one thing that occurred to me is that it might not be very clear to the community what are concrete examples of things kinds of enhancement proposals that are good candidates.
Also, while I barely contribute to SwiftPM anymore, we make very heavy use of SwiftPM in the work our team currently does, so I have a lot of opinions from managing large & complex graphs of SwiftPM projects.
With that in mind, here is my own personal “wishlist” of SwiftPM enhancements that are also unblocked from my perspective, in the sense that if someone wanted to show up with a proposal and an implementation, the project would be eager to work towards accepting them.
See the full post for a list of “proposal proposals”.
There have been a fair number of proposals for making multiple closure arguments to a function look nicer and be more readable—most recently SE-279. These have all come up against ergonomic issues and lack of community consensus because they assume something close to the trailing closure syntax is what’s needed. I’d like to propose a very different approach, inspired directly by a hitherto unique feature of the language Ceylon, and which counterintuitively makes a complicated call site easier to read by increasing its length and verbosity (but also its expressiveness and formattability). I call these Declaration-Like Argument Blocks, and the intuitive idea is to make a complicated call site look a lot like a class or struct declaration.
SR-12524 describes a problem we’ve had since the earliest days of Swift. For years there has been talk of solving it with language features, and in fact we got one of the necessary features in coroutine accessors. I think I can now demonstrate it’s the only feature we needed, and I’ll propose we incorporate this capability into the standard library.
- Variadics and array literals both default to allocating Arrays, which usually means a heap allocation.
- The compiler can already stack-promote Arrays if it can prove that there are no outstanding references to the Array instance.
- But it’s hard to do that through a non-inlinable function call.
- We can sidestep that problem today by using
- When move-only types come along, we’re close to being able to make a safe
BorrowedBuffertype. (Which we’ll very likely want anyway, for other purposes.)
- If we then come up with a syntax to allow types other than
Arrayto be used for variadic parameters, we get safe stack-allocated variadics out of it. (I don’t much care what the syntax is at the moment.)
A review of the standard library should be undertaken on all high-order functions to determine whether their argument label is important, and if so, recommend adding a second method with the argument label hoisted into the basename. This would be source breaking, but justified under the “active harm” exception, since the readability of methods such as
drop(while:)is currently severely impaired by dropping the argument label. The original method should be deprecated over time (probably when we next introduce a new language variant).
Note, not all argument labels are necessary for readability, and would have been better left out altogether. These should be left alone rather than changed for consistency, since the bar for source breakage is high.
The original key path proposal expressly limited key paths to be able to reference only properties and subscripts:
\Person.name // KeyPath<Person, String> \Person.pets // KeyPath<Person, Pet>
This proposal adds the ability for key paths to reference instance methods, optionally specifying argument names:
\Person.sing // KeyPath<Person, () -> Sound> \Person.sing(melody:lyrics:) // KeyPath<Person, (Melody, String) -> Sound>
Note that these key paths do not provide argument values; they reference unapplied methods, and the value they give is a function, not the the value that results from calling the method.
Adding this capability not only removes an inconsistency in Swift, but also solves practical problems involving
filteroperations, proxying with key path member lookup, and passing weak method references that do not retain their receiver.
Joe Groff never fails to a maïs 🌽