Archive for February, 2016

Non-Apple contributors being granted Swift commit access

As of today, Apple is now offering commit access to third parties with a proven contribution track record. The updated policy is as follows:

“If you would like commit access, please send an email to the code owners list with a list of 5 non-trivial pull requests that we accepted without modifications.”

If you want to start contributing to Swift, the team has a set of “starter bugs” you can work on, building up to non-trivial contributions. To learn more about contributing code, visit swift.org’s page that details the process.

Getting ready for Swift to stop breaking code

When you talk about code breaking, it can mean one of two things.

  1. The language semantics change. You need to refactor the way you perform key tasks. This happened when Swift moved away from (..., &NSError) -> Result? patterns to using thrown errors.
  2. The language syntax changes. You apply a migrator and boom, everything more or less gets fixed (minus some epsilon of incorrect tweaks).

The latter is an inconvenience. The former is disruptive. If I’m reading the tea leaves correctly, Swift 3 aims to be the last source-breaking change for a while. Swift 4 should be adding more new features instead of redesigning existing ones.

Chris Lattner writes,

Agreed – source breaking changes in Swift 3 are already a given, so we’re going to provide a really great migrator to help move people forward.  Beyond Swift 3, the Swift community will be a much more diverse place with multiple platforms supported and more diverse tools/ide’s used.

As such, source breaking changes will be much more difficult to justify after Swift 3 is out the door, we’re prefer to roll them into Swift 3 where ever possible.

further:

While Swift 4 will probably break *some* code, we really want to reduce cases that happens.

In terms of time frames,

This is why we need to stay focused on making Swift 3 great within the schedule constraints we have, even if it means pushing off a lot of interesting work…

I don’t think there is any point in discussing features beyond Swift 3 now, and I think it would be harmful to do so. There isn’t enough bandwidth from the core team to participate in these discussions, and we’d like to keep the rest of the community and contributors focused on what is important to make Swift 3 great.

What happens in Swift 3 will inform what happens in Swift 4. While there are some things that we can predict (e.g. concurrency being a feature) there are many completely different design directions that may prove out to be the best. It is extremely unlikely that a discussion right now would shed any light on the tradeoffs involved that would select the best approach, but it is very likely that a lot of discussion time would be wasted.

I know it requires patience and restraint, but it really is best for everyone involved to wait until the right time to have these discussions. This Fall (for the northern hemisphere) is not that far away and there is a ton of important work to do now.

Getting Swift 3 design goals solidified and into a timetable has been a challenge, especially since the language has been open sourced.

Predicting what will end up in Swift 3 (e.g., “will we achieve our goals?”) is inherently fraught with peril and cannot be done perfectly.  There are a ton of unknowns in design and implementation of any feature (e.g., how do you know how long it will take to implement behaviors when we don’t have a concrete design?), and new work gets added all of the time as we find new problems to solve and the community identifies new problems.  It is also impossible to predict what open source contributors will provide.

Part of the reason we have to say “no” to good ideas is that we are incredibly design and implementation bound.  We have high goals for Swift 3 as it is, but we aren’t 100% certain we’ll be able to achieve them (that’s why they are “goals”, not “certainty”).  I think that we’ve had a consistent approach with Swift 3, where we’re focused on fixing core deficiencies in the base language, fixing implementation issues and designing resilience features that affect ABI stability, while taking on small scope extensions to the language.  This has come at a cost of having to defer discussion on “large” extensions to the language that do not affect the core model (e.g. the memberwise init revamp) but I’m hoping that we will still get some of those for Swift 3.

Overall, this comes back to a higher order philosophy about what Swift 3 is really about: it is about driving the next wave of adoption of Swift by even more people. This will hopefully come from new audiences coming on-board as Corelibs + Swift on Linux (and other platforms) become real, SwiftPM being great and growing into its own, and the Swift language/stdlib maturing even more.

What does this mean looking forward?  Well, Swift 2 to Swift 3 is going to be an unavoidably disruptive change for code since Cocoa renamification is going to land, and we’re going to be building impressive migration technology again.  As such, we should try to get the “rearrange all the deckchairs” changes into Swift 3 if possible, to make Swift 3 to 4 as smooth as possible.  While our community has generally been very kind and understanding about Swift evolving under their feet, we cannot keep doing this for long.  While I don’t think we’ll want to guarantee 100% source compatibility from Swift 3 to Swift 4, I’m hopefully that it will be much simpler than the upgrade to Swift 2 was or Swift 3 will be.

As a final note, watch out for that Cocoa renamification. It’s going to be a doozy.

Non-linear loops

Yesterday, someone was asking me about how to do loops for non-linear sequences. Normally, you just do stuff like:

for i in 1...5 {print(i)} // 1, 2, 3, 4, 5

And stuff like:

for i in 1.0.stride(through: 2.01, by: 0.1) {
    print(i) // 1.0, 1.1, ... 1.9, 2.0
}

for floating point. The 2.01 ensures you get that last value. You had to add some kind of epsilon when working with C-style for loops too because reasons and floating point math.

Screen Shot 2016-02-26 at 10.50.11 AM

Ditto stride:

Screen Shot 2016-02-26 at 10.53.28 AM

Leaving floating point aside, the question of the day had to do with non-linear sequences, for example, how do you do a loop for 1^-2 through 12^-2? Using map applies a function across each value, offering a simple non-linear value sequence:

Screen Shot 2016-02-26 at 10.55.37 AM

Doing math inside the for-in statement itself can quickly become ugly. It’s much nicer to map a named function across an integer sequence than implement the transformation directly in the for loop declaration.

Screen Shot 2016-02-26 at 10.57.16 AM

Of course, once you separate out the function like this, you can throw in any function at all in place. Just swap out inverseSquare with whatever function you’d prefer.

If your functionality depends on the count of iterations, for example doing some kind of trig across every 15°, then you’d want to pull out the count calculation, so it could be used both in the loop and the applied function, like this:

Screen Shot 2016-02-26 at 10.59.59 AM

Update: Joe Groff writes, “1.0.stride(through: 2.01, by: 0.1) will accrue error as you repeatedly add 0.1000….02. You can avoid the ugly epsilon by iterating exact values and scaling down, say by 10.0.stride(through: 20.0, by: 1.0).lazy.map { $0 * 0.1 }, which will produce more accurate tenths.” If I were going to go that way, I think I’d prefer just using integer math and converting from there. Both solutions shown in the following screenshot.

Screen Shot 2016-02-26 at 11.26.58 AM

Three rejected Swift proposals

The Swift team has rejected three Swift proposals:

SE-0010 “Add StaticString.UnicodeScalarView would have added a way to index into a static string and return a static string. The team writes,

While the addition of StaticString.UnicodeScalarView is a useful feature by itself, the core team felt that it would be inconsistent just to add this narrow set of APIs for Unicode scalars. StaticString itself is a bit odd: it’s UTF-8 API works differently from String, there is no provision for UTF-16/32, etc. If StaticString is to gain Unicode support, it should be done comprehensively, not piecemeal. Moreover, with the aforementioned String re-evaluation underway, it is possible that StaticString itself might change considerably or even be obsoleted.

SE-0027 Expose code unit initializers on String asked to make public otherwise private functions that simplified the process of moving to and from byte representations. The team writes,

At this point, the core team feels that we have not fully explored the design space here, and that known alternatives (e.g., making the UTF-16 and UTF-32 views of a String mutable collections) might provide a better long-term solution. Moreover, the String type itself is undergoing a significant re-evaluation, so the core team feels that improvements to String should be delayed until the newer design is better understood.

SE-0024 Optional Value Setter ??= added a Ruby-like “assign only if nil” operator. The team writes,

While the ‘??=‘ operator’s semantics are clear and fit with other compound assignment operators, the use cases are not strong enough to motivate inclusion of this operator. Radek’s lukewarm +0.5 review captures the sentiment of the core team fairly well (as was echoed by others): one very common use case in the Ruby’s similar ||= operator is to assign a default value to an optional parameter or a local variable. However, neither case works well in Swift because ??= does not erase the optionality of the variable (and cannot be used to change a parameter now that var has been removed from parameters). Property access and subscripting could still benefit from ??=, but the latter case is likely to be handled better by a Dictionary subscript operator that can substitute a default value (see, e.g., Joe Groff’s suggestion).

Beta 4: Zut alors! What’s new in Swift

I’m still downloading, so I can’t test anything yet, but a lot of familiar proposals just went live in this beta. I’ve just cleaned up things a little from the release notes, added some comments, and linked to proper titles.
Like my posts? Consider buying a book or two. Thanks!

Swift Language Version Build Configuration

You can now test for Swift version in code.

For example:

#if swift(>=2.2)
    print(“Hello!”)
#else if swift(1.0)
    println(“Hello!”)
#else
    This code will not parse or emit diagnostics
#endif

There’s a great (and active) discussion going on about other potentially supported conditions. Evan Maloney proposes:

  • Is the target an Apple platform (iOS, OS X, tvOS, watchOS) or not? (Answers the question “can I import Foundation”?)
  • Is the target a “common UIKit platform” (compiles on both iOS and tvOS) or not? (Answers the question “can I import UIKit”?)
  • Is the target a specific platform (iOS, OS X, tvOS, watchOS, Linux, etc.)?
  • Is the target in Debug or Release mode?
  • Is the target a simulator environment or a physical device?
  • Is the target built for running tests?

Other recommended tests include “Is this a Darwin target?”, “Does this target support importing UIKit (iOS, tvOS) or Cocoa?”, etc.

Referencing the Objective-C Selector of a Method

You now construct a Swift method’s Objective-C selector using #selector:

let sel = #selector(insertSubview(_:aboveSubview:)) // sel has type Selector

String literal selectors are now deprecated:

let sel: Selector = "insertSubview:aboveSubview:" // nope

The compiler will recommend fixits where possible, otherwise you’ll need to use a Selector initializer:

let sel = Selector("propertyName")

The compiler now checks that “the string literals used to construct Selectors to ensure that they are well-formed Objective-C selectors and that there is an @objc method with that selector.”

Replacing typealias with associatedtype

Swift 2.2 deprecates using the typealias keyword for associated types (which is being renamed) and Swift 3 will eliminate its support for this usage. From now on, use associatedtype, which describes a type associated with a generic item, for example, the elements and indices of a collection, or the streams combined together for a zipped sequence. You can continue using typealias for making type aliases indefinitely.

Naming Functions with Argument Labels

Since Swift enables you to overload functions, just using names can reference more than one function. Adding argument labels to function names provides disambiguation for a modern language.

let fn1 = someView.insertSubview(_:at:) 
let fn2 = someView.insertSubview(_:aboveSubview:)
let buttonFactory = UIButton.init(type:)

Eliminating Ophidiophobia

Swift 2.2 refactors screaming snake case identifiers to pleasant #-delimited expressions.

New #file, #line, #column, and #function expressions have been introduced to replace the existing __FILE__, __LINE__, __COLUMN__, and __FUNCTION__ symbols. The __FILE__-style symbols have been deprecated, and will be removed in Swift 3.

I have a particular fondness for this improvement, which enhances the way you can recover context when doing any kind of logging and debugging.

Survey results: labels

Yesterday, I ran a quick survey to get a sense of the kind of label naming schemes developers would prefer in a Swift setting. Because I don’t have a paid account over at Survey Monkey, my results ran out fairly quickly at 100 answers.

Even so, the 100 answers I can see do show trends worth exploring: Swift devs like first labels and dislike unnecessary linguistic “fluff” that complicates calls. It’s sort of an anti-ObjC style pushback.

It’s hard to track the comments against the answers (next time I do anything like this, I’m going to make it much clearer that comments should run like “I chose blah because…and then finish your comment”) but they too seem emphasize concision, consistency and simplicity.

If you take some time to review the results, I’d be interested in hearing any conclusions you build from them.

Pterodactyls and thylacines: What’s evolvin’ over in Swift

Putting aside any discussion about SE-0023 (API Design Guidelines), SE-0006 (Apply API Guidelines to the Standard Library), and SE-0005 (Translate Objective-C APIs into Swift), whose discussion will probably last to the next millennium, there are some other on-going reviews to take note of.

Feb 10-Feb 16 SE-0030 Property Behaviors introduces ways to generalize common patterns, like the lazy property instead of hard-coding them into the language. I’m really excited about this one, can’t wait to see how it irons out. The discussion has focused a lot on fleshing out the proposal and tweaking how the properties will be used in-line (the original proposal uses square brackets for behavior keywords), e.g.

var [lazy] foo = 1738

Feb 11-Feb 15 SE-0031 Adjusting inout Type Decoration moves inout from modifying parameter names, to modifying types, enabling the declaration to match a method or function’s type signature:

(x: inout T) -> U // => (inout T) -> U.

Not a lot of discussion on this one, so I encourage you to go give some feedback and a vote. An obvious +1 from me.

Feb 11-Feb 16: SE-0027 Expose String Code Units Initializers enhances developer-facing string-to-byte and byte-to-string calls. It extends them from the currently public pair of C-strings initializers to add and adapt currently private _fromCodeUnitSequence(_:input:) calls. Looks good to me.

Feb 12-Feb 17: SE 0024 Optional Value Setter introduces ??=, a conditional setter that mimics Ruby’s ||= operator.  It performs an assignment if and only if the optional on the left of the operator is currently nil, and will not overwrite an already set value.

I’m not sure how I feel about this one, as I don’t quite get the utility and benefit, and it confuses the use of the ?? nil-coalescing operator, which unlike this ??= one always produces a non-optional. I’m thinking I’m -1 on this.

I’d sort of prefer an operator that assigns a non-optional if and only if the right side of the assignment is non-nil, but that’s not what’s being proposed. You can read through the on-list discussion here.

Other upcoming reviews:

Interesting on-list discussions: