Archive for April, 2016

Ask Erica: How do I count with reduce?

“how do I use reduce() to get number of items in an array that aren’t nil?”

Here’s an answer:

let exampleArray: [Int?] = [1, 3, nil, 4, nil, 10]
print(exampleArray.reduce(0, combine:{return $0 + ($1.map{_ in 1} ?? 0)}))

But I think you’d be better using flatMap or for case

print(exampleArray.flatMap({$0}).count)

var count = 0; for case _? in exampleArray {count += 1}; print(count)

Or you might think about why you’re counting items instead of just using the result of flatMap directly.

Triassic Park: The Swift Evolution

Newly Accepted

SE-0048: Generic Type Aliases introduces type parameters that are in-scope for their definition, for example:

typealias StringDictionary<T> = Dictionary<String, T>
typealias DictionaryOfStrings<T : Hashable> = Dictionary<T, String>
typealias IntFunction<T> = (T) -> Int
typealias Vec3<T> = (T, T, T)
typealias BackwardTriple<T1,T2,T3> = (T3, T2, T1)

The alias redeclares constraints for its new type. For example, in the string dictionary example, the primary key type must be hashable for this approach to work. The Swift compiler should be adding feedback when expected constraints aren’t found:

typealias DictionaryOfStrings<T> = Dictionary<T, String>
// error: type 'T' does not conform to protocol 'Hashable'

Cool stuff.

SE-0049: Move @noescape and @autoclosure to be type attributes follows the lead of earlier proposals in moving things that describe characteristics of types to the types themselves.

func f(fn : @noescape () -> ()) {}     // type attribute.
func f2(a : @autoclosure () -> ()) {}  // type attribute.

SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Implementations removes a quirky exception that allowed enumeration cases to be referenced without a leading dot in member implementations. In no other case could an instance implementation directly access a static member, and this acceptance removes that exception.

SE-0062: Referencing Objective-C key-paths improves the safety and resilience of key-path code (for both KVC and KVO) using compiler expression checks. The new #keyPath() expression expands at compile time to a  key-path literal string, which is checked for validity.

By having the #keyPath expression do the work to form the Objective-C key-path string, we free the developer from having to do the manual typing and get static checking that the key-path exists and is exposed to Objective-C.

SE-0064: Referencing the Objective-C selector of property getters and setters expands upon SE-0022 to support #selector expressions for properties.

let firstNameGetter = #selector(getter: Person.firstName)
let firstNameSetter = #selector(setter: Person.firstName)

SE-0057: Importing Objective-C Lightweight Generics adds a way that ObjC’s new type parameters can be imported into Swift.

Cocoa and Cocoa Touch include a number of APIs that have adopted Objective-C lightweight generics to improve static type safety and expressiveness. However, because the type parameters are lost when these APIs are imported into Swift, they are effectively less type safe in Swift than in Objective-C

This adoption allows ObjC classes to be parameterized on the types they work with in a manner that’s similar to Swift’s generics syntax.

SE-0063 SwiftPM System Module Search Paths enables Swift to   better import C libraries from locations other than /usr/lib and /usr/local/lib. Support is added for brew and apt-get, and newly introduced `pkgConfigName` entries to specify further search locations through SwiftPM .pc (package configuration) files.

Deferred

SE-0058 Allow Swift types to provide custom Objective-C representations is deferred until after Swift 3. This proposal provides an ObjectiveCBridgeable protocol that allows a Swift type to control how it is represented in Objective-C by converting into and back from an entirely separate @objc type. This frees library authors to create truly native Swift APIs while still supporting Objective-C:

We agree that it would be valuable to give library authors the ability to bridge their own types from Objective-C into Swift using the same mechanisms as Foundation. However, we lack the confidence and implementation experience to commit to `_ObjectiveCBridgeable` in its current form as public API. In its current form, as its name suggests, the protocol was designed to accommodate the specific needs of bridging Objective-C object types to Swift value types. In the future, we may want to bridge with other platforms, including C++ value types or other object systems such as COM, GObject, JVM, or CLR. It isn’t clear at this point whether these would be served by a generalization of the existing mechanism, or by bespoke bridging protocols tailored to each case. This is a valuable area to explore, but we feel that it is too early at this point to accept our current design as public API.

Active Reviews

Proposals awaiting scheduling

Like my posts? Consider buying a book or two. Thanks!

Building OS X Drag and Drop Playgrounds

With the latest changes in Xcode 7.3, you can once again build drag-and-drop playgrounds to provide simple Swift-based utility apps with minimal coding.

Unlike older solutions, XCPlayground’s interactive live views don’t require pop-up windows. You don’t have to do anything special to make the page application run with a different priority. Just open the assistant and the app is there, running, and interactive.

Screen Shot 2016-04-14 at 9.42.46 AM

I’d really like to see Xcode drop the “open the assistant view” requirement at some point and let you embed into the main playground. For now, though, you need to set up Xcode and display the main timeline, the assistant, and typically the console, all at once.

My drag-and-drop implementation is pasted over at gist.github.com. The samples consist of three files. Place the main DropView code into the shared playground folder and add the two examples to new playground pages.

My DropView builds a drag-supporting text field. A text fields makes it easy to add the “drop here” label. The view registers for drag operations in its initializer and calls a settable handler with a list of file paths.

The example pages consist of nothing more than creating a view, setting its prompt, and adding a handler for the file paths. You can tweak the handler however you like, as user-supplied dropped paths aren’t sandboxed away from you.

I’ll be updating Playgrounds with the new examples, probably within the next week.

Pinning tabs in Safari

Because sometimes people forget: Right-click the tab and choose Pin Tab from the pop-up. To remove a pinned tab, right-click again and either un-pin or close it.

Pinned tabs appear in all new tabbed browser windows as well.

Screen Shot 2016-04-13 at 4.04.55 PM Screen Shot 2016-04-13 at 4.05.02 PM

Stop the Madness and fix the Swift API guidelines

Surely I can’t be the only one who thinks that “union/unionInPlace” is clearly, obviously, and measurably superior to “formUnion/union” (or, even worse, unioning or unioned). While I’m pleased with most of the Swift API design guidelines, there are just a few places it steps too far. Here are a few quick ways to improve the guidelines, IMO:

Remove “Prefer method and function names that make use sites form grammatical English phrases.” This isn’t Objective-C. It’s time to move on. This single guideline, while superficially lovely, is causing too much strain and pain in the language. Shoehorning code into grammatical English doesn’t benefit the code or make it more understandable.

Remove “Use the “ed/ing” rule to name the nonmutating counterpart of a mutating method, e.g. x.sort()/x.sorted() and x.append(y)/x.appending(y).” Here’s another pain point. Using “in place” reads better and makes more sense. This is a clear example of not, to steal a phrase, using terminology well.

Add “When creating mutating/non-mutating counterparts, prefer names that relate to each other and use the new `MutatingCounterpart` and `NonmutatingCounterpart` document comments to connect those items”. SE-0047 simplifies the entire cross-referencing situation without having to use “form” (or as it’s read more often, “from”, as in “fromMorePerfectUnion“), “ing”, or “ed”.

Add: “Prefer nouns for methods with no side effects (or only incidental ones, like logging) and verbs for methods with significant side-effects.” When taking side effects (or their lack) into account, you want to name verby things with verby names and nouny things with nouny names, but don’t be too prescriptive.

Got any other changes you’d want to see? Drop a comment, send an email, or tweet me.

Sensible Cocoa and Cocoa Touch Defaults

Many Cocoa and Cocoa Touch calls are boilerplate. They use common argument values that are the same with nearly every call. Why not take advantage of Swift’s default system instead? We’d like to simplify calls like this:

dismissViewControllerAnimated(flag: true, completion: nil)

to calls like this:

dismiss()

Default Values

SE-0005 introduced a number of ways in which ObjC APIs will gain default values through automatic translation. Under this accepted proposal, any method that matches certain patterns will now provide default values.

Daniel Steinberg and I love this defaulting behavior and approached the Swift Evolution list to see whether we could expand defaults for Cocoa and Cocoa Touch APIs even further. David Abrahams replied that we should best proceed by putting together specific requests and file them as radars for the UIKit/AppKit teams, who would then presumably provide extensions that pass the default values.

Here’s our preliminary list of updates we’d like to see. We’re requesting community input to help us expand this list so when we approach Apple with our bug reports, we’ve already thought through and prioritized the kinds of changes we’re invested in.

I’ve put up a gist and hope that anyone who’s interested in contributing will ping us by comment, twitter, or email.

Controls

We feel that UIControl states should always default to .Normal. So, for example, you’d call button.setTitle("Hello") vs button.setTitle("Hello", forState: .Normal). Since these are just defaults, you can always override the state (for example, when using highlights) with the fully specified argument.

Control actions are also fairly predictable. Buttons normally trigger with .TouchUpInside and sliders and switches with .ValueChanged.  By providing defaults, the code simplifies except in those cases where the author intentionally means to use a non-standard pattern.

Core Graphics

We want to default all CG constructors to 0.0, namely x, y, dX, dY, width, and height. You would not be limited, of course, from specifying all elements but at the same time, you could create origin-based rectangles with just CGRect(.width: 200, .height: 100).

Views

We’d like to default animated to true for most UIKit calls. We’re not saying use super.viewWillAppear() — go ahead pass the animated argument that was passed to you. We’re saying instead in calls like dismissViewControllerAnimated, that the most common UIKit (and probably Cocoa) scenario uses animation. Adding a default here simplifies the calls with an understood “common practices” approach.

Auto Layout

We have a rather mixed bag with NSLayoutConstraint. Pretty much we and everyone we’ve talked to agree that a default multiplier of 1.0 and constant of 0.0 are sensible.

However, my initial suggestion that the default relation (relatedBy:, .Equal), second item (toItem:, nil), and second attribute (attribute:, .NotAnAttribute) raised the question of defaults hiding parameters and reducing readability, especially since it’s far more common to layout multiple views with respect to each other than single view attributes (NSLayoutConstraint(item: view, attribute: .Width, constant: 400.0)). We’re less wedded to the second half of this default pattern.

Other Common Patterns

Apple’s UIKit Framework Reference offers a further overview of UIKit classes, additions, functions, constants, and data types. I’m sure there’s an equivalent for Cocoa as well somewhere in the reference library. If you want to pitch in, what we’re looking for are examples of common API calls that use predominantly default API values that the developer must currently enter at each call site, and whose defaults are not already subsumed by SE-0005.

If you have any examples of these, just ping either of us and we’ll update the gist with your feedback. Our goal is to try to grow this set and have it peer reviewed before we start submitting radars to Apple.

Thanks in advance!

Proposal Spotlight: SE-0045 Add scan, takeWhile, dropWhile, and iterate to the stdlib

While SE-0045 hasn’t yet been scheduled for review, it’s a proposal  I’m really looking forward to. Lily Ballard introduces several standard library functions to support sequence operations. Commonly found in other modern languages like C#, Haskell, and Scala, the proposal includes three new sequence functions (scan(_:combine:)takeWhile(_:), and dropWhile(_:))  and a global iterate(_:apply:) function.

The scan function successively applies a function across the members of a sequence. It uses a rolling result and the next sequence value to create each new member of the output sequence. So you might, for example, create an ever-updating sum or product:

extension SequenceType {
  /// Returns an array containing the results of
  ///
  ///     p.reduce(initial, combine: combine)
  ///
  /// for each prefix `p` of `self` in order from shortest to longest, starting
  /// with the empty prefix and ending with `self`.
  ///
  /// For example:
  ///
  ///     (1..<6).scan(0, combine: +) // [0, 1, 3, 6, 10, 15]
  ///
  /// - Complexity: O(N)
  func scan<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> [T]
}

You can think of scan as a brother of reduce, but one that outputs a sequence of intermediate values along the way.

The iterate function in particular is one that many Swift developers have been clamoring for, as it gives you a simple and obvious way to create mathematical progressions that extend beyond simple “n, n + m, n + 2*m, …” strides:

/// Returns an infinite sequence of lazy applications of `apply` to the
/// previous value. For example:
///
///     iterate(1, apply: { $0 * 2 }) // yields: 1, 2, 4, 8, 16, 32, 64, ...
func iterate<T>(initial: T, apply: T -> T) -> IterateSequence<T>

The two “while” functions respectively return the longest prefix of elements that satisfy a given predicate (takeWhile), and the corresponding suffix (dropWhile).

protocol SequenceType {
  // ...
  /// Returns a subsequence by skipping elements while `dropElement` returns
  /// `true` and returning the remainder.
  func dropWhile(@noescape dropElement: (Self.Generator.Element) throws -> Bool) rethrows -> Self.SubSequence
  /// Returns a subsequence containing the elements until `takeElement` returns
  /// `false` and skipping the remainder.
  func takeWhile(@noescape takeElement: (Self.Generator.Element) throws -> Bool) rethrows -> Self.SubSequence
}

Combining iterate with takeWhile basically introduces a Swift-er version of the C-style for loop. Here are a couple of examples that show how these functions would look like in practice.

for x in iterate(0.1, apply: { $0 + 2 })
    .takeWhile({ $0 < 10 }) 
{
    // ... 0.1, 2.1, 4.1, ...
}

and

for view in iterate(startingSubview, apply: { $0.superview })
    .takeWhile({ $0 != nil }) {
    // ... view, view.superView, view.superView.superView ... 
}

Like for loops, each example has a starting value, a closure that lazily updates that value for each iteration, and a sequence generator that produces values until its predicate returns false. While you can convert for loops using Swift’s existing do and while statements, both iterate and takeWhile provide a natural, fp-style correspondence.

When you add in the new SE-0065 collection and index updates, the upcoming stride function and range operator revisions, and floating point math fixes, all of which are under active proposal development,  then pretty much all the C-style for loop inadequacies are addressed in a modern, Swift-native style.

Auto-defaulting ObjC Arguments

My recent post about Objective-C name pruning in Swift 3 garnered some lovely  feedback. I thought I’d throw up a few more posts about the big 3 proposals and SE-0005 in particular, and how automatic translations of ObjC APIs will affect Cocoa use in Swift.

Of the upcoming changes, auto-defaulting is probably my favorite part of the SE-0005 proposal. Among its other automated changes like pruning, SE-0005 introduces rules that allow imported APIs to default many arguments, enabling you to skip parameters when calling from Swift.

Any method that matches one of the following patterns will now provide default values:

  • Trailing closures: nullable closure parameters will default to nil.
  • NSZones: nullable zones also default to nil. (The proposal notes that they should always be nil to begin with as they are unused in Swift.)
  • Option sets: Any type name containing the word `Options` defaults to [], the empty option set.
  • Dictionaries: NSDictionary parameters with names including `options`, `attributes`, and `info` default to [:], the empty dictionary.

This translation excludes single-parameter setters so `setCompletionHandler: value` and `setOptions: value` aren’t affected by these rules.  Otherwise, the upshot of these rules means that a call like this:

rootViewController.presentViewController(
    alert, 
    animated: true, 
    completion: nil)
UIView.animateWithDuration(
    0.2, delay: 0.0, options: [], 
    animations: { self.logo.alpha = 0.0 }) { 
        _ in self.logo.hidden = true 
}

simplifies to this in Swift 3:

rootViewController.present(alert, animated: true)
UIView.animateWithDuration(0.2, delay: 0.0, 
    animations: { self.logo.alpha = 0.0 }) {
        _ in self.logo.hidden = true 
}

This automated default introduction has the greatest impact on completion handlers, user info dictionaries, attribute dictionaries (for example when working with `NSFileManager` and `NSAttributedString`), and option groups (like AVFoundation’s `AVMusicSequenceLoadOptions`, `AudioComponentInstantiationOptions`, and `AVMovieWritingOptions`).

The result is a much cleaner Swift, where you choose when to introduce customization on calls instead of reflexing populating them with “opt-out” values like nil and `[]` and `[:]`. View side-by-side examples of these changes here, by searching for “= nil”, “= []”, and “= [:]” on the green right Swift 3 side.

Why doesn’t `NumericalArithmeticType` exist in Swift?

Asked on-list today: Why are there two mutually exclusive protocols for number types instead of a single unifying `NumericalArithmeticType`?

Jordan Rose answered:

This comes up often enough that we should probably write it somewhere, but we don’t have this protocol for the simple reason that there are very few algorithms that are correct for both integers and floating-point numbers. Even something as simple as “average” needs to be handled differently.

Preparing for 3.0 API Pruning

Just another reminder this morning, with a quote from Chris Lattner that Swift 3 is barreling towards us with a huge impact on Cocoa and CocoaTouch familiarity:

[I]n Swift 3, “.blackColor()” becomes “.black()”.

This change is covered in SE-0005, the proposal about translating Objective-C APIs into Swift. The rule in question (Pruning #3) prunes the word color based on the match between the tail of the property name and the property type name:

class func darkGrayColor() -> UIColor
// so
foregroundColor = .darkGrayColor()
// becomes
foregroundColor = .darkGray()

Here’s a quick summary of the pruning rules. Keep in mind that if following the rules produces a no-go result (an empty selector, a Swift keyword, etc), that rule is skipped.

Pruning #1: Chop type names off the front of members that preserve the same type:

let c = myColor.colorWithAlphaComponent(0.5)
// becomes
let c = myColor.withAlphaComponent(0.5)

Pruning #2: If the type name is followed with by and is followed by a present participle gerund chop the “by” off too.

let img = myImage.imageByApplyingOrientation(o)
// becomes
let img = myImage.applyingOrientation(o)

Pruning #3. Prune the type name at the tail of a selector when it matches the type name under the following circumstances:

From the tail of: Prune a match for:
a selector piece that introduces a parameter the parameter type name
the name of a property the property type name
the name of a zero-argument method the return type name
documentForURL(_ url: NSURL)
var parentContext: NSManagedObjectContext?
class func darkGrayColor() -> UIColor
// becomes
documentFor(_ url: NSURL)
var parent: NSManagedObjectContext?
class func darkGray() -> UIColor

Pruning #4: Prune types after verbs in method names:

myVC.dismissViewControllerAnimated(...)
// becomes
myVC.dismissAnimated(...)