Archive for July, 2016

Removing Bit Flags in Option Sets: or Fun with AVFoundation

AVFoundation’s unofficial nickname might as well be “that module with all the options”. So how do you port in an equivalent to this Objective-C number?

@(AVAssetReferenceRestrictionForbidAll & ~AVAssetReferenceRestrictionForbidLocalReferenceToLocal)

First, remember that pretty much all bit manipulation is now replaced by option sets. Second, remember the core rule of Swift renamification: start typing from the middle and let fuzzy completion find the new option set name for you.

Screen Shot 2016-07-20 at 10.03.03 AM

Then confirm you got the right item using Quick Help:

Screen Shot 2016-07-20 at 10.03.58 AM

You may be tempted to start using bit math like this. Don’t.

let forbidAll = AVAssetReferenceRestrictions.forbidAll.rawValue
let local = AVAssetReferenceRestrictions.forbidLocalReferenceToLocal.rawValue
let restrictions = AVAssetReferenceRestrictions(rawValue: forbidAll & ~local)

This is Swift. So modernize your “bits” thinking to “sets”. This code creates the complete .forbidAll set and then removes the local restriction.

var restrictions: AVAssetReferenceRestrictions = [ .forbidAll ]
restrictions .remove(.forbidLocalReferenceToLocal)

Interestingly,  you can also pass .forbidAll without brackets in the current version of Swift and it will compile.  (Update: I’m told that this option set syntax works because each element of an option set is itself an option set: [.forbidAll] is the same type and equal to .forbidAll. The array literal form of [.a, .b, .c] is syntactic niceness for creating an empty option set and then inserting (i.e. bitwise OR) each element)

What you cannot do is chain the two lines although you’d think you should be able to, wouldn’t you? Again, I think this is a bug, but you’ll get an error along the lines of:

Update: Another d’erp moment: Use the non-mutating subtracting method! (Thanks for the feedback!)

let restrictions: AVAssetReferenceRestrictions = .forbidAll.subtracting(.forbidLocalReferenceToLocal)
// Playground execution failed: error: AVTest.playground:7:50: error: cannot use mutating member on immutable value of type '[_]'
let restrictions: AVAssetReferenceRestrictions = [.forbidAll].remove(.forbidLocalReferenceToLocal)

Speaking of alternatives, while you could reduce this to one line by positively mentioning the three remaining restrictions, don’t. If Apple added a new restriction (improbable I admit), your code would break, failing to represent your intended logic.

public static var forbidRemoteReferenceToLocal: AVAssetReferenceRestrictions { get }
public static var forbidLocalReferenceToRemote: AVAssetReferenceRestrictions { get }
public static var forbidCrossSiteReference: AVAssetReferenceRestrictions { get }
public static var forbidLocalReferenceToLocal: AVAssetReferenceRestrictions { get }
public static var forbidAll: AVAssetReferenceRestrictions { get }

It’s kind of a pity that option sets (not being a separate type — and one that according to a conversation I had with Joe Groff will never be a separate type) won’t let you invert membership, even though all members must be known at compile time.

Anyway, lessons:

  • Eschew bits in Swift 3. Option masks are automagically upgraded to option sets. Use them.
  • Imported APIs with parameters whose type names contain the word Options are given a default value of [], the empty option set. If you don’t need options, you can omit mentioning the parameter.
  • When you mean to use “all but” don’t list individual cases. Look for all-encompassing “masks”, and then remove the cases you want excluded.
  • Like enumerations, option set members are lowercased in Swift 3. Keep this in mind when designing your own.

I may update this list as I think of more.

Stateful loops and sequences

An intriguing request came up on Swift-Ev a day or so ago:

I’ve come across a situation a number of times where I write code that has to try something one or more times using a `repeat…while` loop and the condition relies upon variables that should be declared within the scope of the loop.

repeat {
    let success = doSomething()
} while !success

What caught my eye about this request is the need for state that’s visible both within scope and in the control structure without being declared in the outer scope.

This mechanism already exists in Swift. Meet Swift’s new sequence functions. Swift offers two varieties. Both offer ways to establish state confined to the loop scope.

public func sequence<T>(first: T, next: (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>

public func sequence<T, State>(state: State, next: (inout State) -> T?) -> UnfoldSequence<T, State>

The difference between the two is this: The simpler first function produces a sequence of the same type as its state. The second variation (which actually used to implement the first one) differentiates the state type from the output type, so you could generate integers and operate on strings if you wanted to.

If you think about it, a repeat-while loop really is just a sequence written in a different form. Here’s a simple example that counts by 5.

var i = 0
repeat {
    print(i) // some loop body
    i = i + 5
} while i <= 100

You can rewrite this to incorporate the i-variable state into the control structure like so

for i in sequence(first: 0, next: { $0 + 5 }) {
    print (i) // some loop body
    if i >= 100 { break } 
}

Or you can be slightly more daring and move all behavior and state into the next closure:

for _ in sequence(first: 0, next: {
    print($0) // some loop body
    let value = $0 + 5
    return value <= 100 ? value : nil
}) {}

There are three big things to note about this modification:

  1. The for-loop doesn’t need a variable. It’s only being used to run the sequence.
  2. The loop body is empty. It’s just there to complete the syntax for for in. You could just as easily perform Array(sequence) but that would require memory allocation, which is wasteful.
  3. The sequence must terminate by returning nil. This means the closure’s return type is T?, where T is the type of the first argument. This example returns value,  but it could just as easily return any number (like 0 or 1 or 42 or Int()) because that value will never be used in any meaningful way here. It’s just checking for false/nil.

If you’re going to treat Boolean conditions as optionals, it helps to have a quick way to convert a Boolean to an optional equivalent. This is overkill but it gets the job done.

extension Bool { var opt: Bool? { return self ? self : nil } }

Alternatively, you can build a function that operates on Boolean tests so you don’t need to convert Booleans to optionals when building weird for-loop sequences.

The perform function that follows creates a stateful repeat-while loop, which is more or less what I believe the writer was aiming for. It uses a Boolean test, hides the use of sequence(state:next:), and allows a trailing closure for the body of the loop.

func perform<T>(
    with state: T,
    while test: (T) -> Bool,
    repeat body: (inout T) -> Void) -> T {
    var updatedState: T = state
    let boolSequence = sequence(state: state, next: {
        (state: inout T) -> Bool? in
        body(&state)
        updatedState = state
        return test(updatedState) ? true : nil
    })
    for _ in boolSequence {}
    return updatedState
}

// The following example joins the words into a single space-delimited string.
let joinedWords = perform(
    with: ["Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"],
    while: { $0.count > 1 })
{
    (state: inout [String]) in
    guard state.count >= 2 else { return }
    let (last, butLast) = (state.removeLast(), state.removeLast())
    let joinedLast = butLast + " " + last
    state.append(joinedLast)
}.first!

debugPrint(joinedWords)

The key bit to notice is that the initial word array isn’t stored anywhere external to the loop but can be operated upon within the loop body. I believe this is exactly what the original writer asked for when he wrote, “code that has to try something one or more times using a `repeat…while` loop and the condition relies upon variables that should be declared within the scope of the loop”

Dear Erica: No-case Enums?

Dear Erica, Why would you create an enum with no cases?

This is such a great question! No-case enumerations represent a fairly obscure Swift “power tool”, and one that most developers are unaware of.

The answer, in a nutshell,  is that they enable programmers to establish a mini-namespace with little overhead and an assurance that you can’t accidentally create type instances. Under their umbrella, you can group static members into namespaces, build singletons, create cohesive collections of functionality with a minimum surface eliminating freestanding functions, and in one outlier case  provide services built around generic types.

Namespacing

For example, the standard library uses no-case enums to represent command line arguments for the current process. The Process enum has no cases. It provides a native Swift interface to the command line argc (count)/argv (strings) arguments passed to the current process.

/// Command-line arguments for the current process.
public enum Process {

    /// Access to the raw argc value from C.
    public static var argc: CInt { get }

    /// Access to the raw argv value from C. Accessing the argument vector
    /// through this pointer is unsafe.
    public static var unsafeArgv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?> { get }

    /// Access to the swift arguments, also use lazy initialization of static
    /// properties to safely initialize the swift arguments.
    ///
    /// NOTE: we can not use static lazy let initializer as they can be moved
    /// around by the optimizer which will break the data dependence on argc
    /// and argv.
    public static var arguments: [String] { get }
}

Singletons

If you’re thinking the preceding enumeration feels very much like a singleton, you would not be wrong. Consumers are prevented from creating instances and there’s a single entry point for all the functionality. Should you need  supporting state, you can always include an embedded type within a no-case enumeration.

Here’s a real world example I built that offers synchronous text-to-speech generation :

/// Synchronous Text-to-Speech support
public enum Speaker {
    /// Internal synthesizer
    private struct Synthesizer {
        static let shared = SynchronousSpeech()
    }
    
    /// Say the utterance passed as the argument
    public static func say(_ utterance: String) {
        Synthesizer.shared.say(utterance)
    }
}

The synthesizer is hidden from view outside the module, as you see in the public declaration.

import AVFoundation
import Foundation

/// Synchronous Text-to-Speech support
public enum Speaker {
    /// Say the utterance passed as the argument
    public static func say(_ utterance: String)
}

Users cannot create instances and the single entry point (Speaker.say()) limits access to the singleton’s restricted functionality.

Wrappers

I created a PlaygroundState enumeration singleton to centralize and simplify playground code I access over and over. Instead of typing PlaygroundSupport.PlaygroundPage.current.needsIndefiniteExecution, I use my PlaygroundState singleton to runForever().

The following example, which is cut down massively from its actual implementation, wraps several technologies including PlaygroundSupport and ProcessInfo to generalize access to simulator details and execution control:

/// Controls and informs the playground's state
public enum PlaygroundState {
    /// Establishes that the playground page needs to execute indefinitely
    static func runForever() {
        page.needsIndefiniteExecution = true
    }
    
    /// Instructs Xcode that the playground page has finished execution.
    static func stop() {
        page.current.finishExecution()
    }
    
    /// The playground's environmental variables
    public static var processEnvironment: [String: String] {
        return processInfo.environment
    }

    #if !os(OSX)
    /// Simulator's device family
    public static var deviceFamily: String {
    return processEnvironment["IPHONE_SIMULATOR_DEVICE"] ?? "Unknown Device Family"
    }
    
    /// Simulator's device name
    public static var deviceName: String {
    return processEnvironment["SIMULATOR_DEVICE_NAME"] ?? "Unknown Device Name"
    }
    
    /// Simulator's firmware version
    public static var runtimeVersion: String {
    return processEnvironment["SIMULATOR_RUNTIME_VERSION"] ?? "Unknown Runtime Version"
    }
    #endif
}

Consolidating Type Information through Generics

When reviewing SE-0101, Brent Royal-Gordon asked why the proposed MemoryLayout type needed to be a struct:

I think grouping these into a type is a sensible approach, but I don’t like that it allows the creation of meaningless MemoryLayout instances. The simplest fix would be to make `MemoryLayout` an empty enum instead of an empty struct. This would convey that no MemoryLayout instances do or can exist.

This is a pretty outlier use of caseless enumerations but it’s a valuable one. Rewriting my original struct into an enum, produces the following example. It uses generics to extract information about types:

/// Accesses the memory layout of `T` through its
/// `size`, `stride`, and `alignment` properties
public enum MemoryLayout<T> {
    /// Returns the contiguous memory footprint of `T`.
    ///
    /// Does not include any dynamically-allocated or "remote"
    /// storage. In particular, `MemoryLayout.size`, when
    /// `T` is a class type, is the same regardless of how many
    /// stored properties `T` has.
    public static var size: Int { return sizeof(T.self) }
    
    /// For instances of `T` in an `Array`, returns the number of
    /// bytes from the start of one instance to the start of the
    /// next. This is the same as the number of bytes moved when an
    /// `UnsafePointer` is incremented. `T` may have a lower minimal
    /// alignment that trades runtime performance for space
    /// efficiency. The result is always positive.
    public static var stride: Int { return strideof(T.self) }
    
    /// Returns the default memory alignment of `T`.
    public static var alignment: Int { return alignof(T.self) }
}

By using a caseless enumeration, users can query the types without ever creating instances, for example: MemoryLayout<Double>.size, MemoryLayout<NSObject>.stride, etc.

Like my posts? Consider buying a book. Content Update #1 is live. I also have books on Playgrounds (updated with the iOS 10 Swift Playgrounds App)  and Structured Documentation for sale at iBooks and LeanPub.

Update: 
See also: Natasha’s post on no-case enums and:

Announcement: Swift 3 Endgame and Swift 4 Kickoff

Via Ted Kremenek

Hi everyone,

Swift 3 has shaped up to be a remarkable release — a product of the inspiration, ideas, and hard labor many people from across the Swift open source community. It is now time, however, to talk about the endgame for the release.

Here are the key points:

  • The last day to take planned source-breaking changes for Swift 3 is July 27.
  • On that day, there will likely be a set of approved-but-not-implemented proposals for Swift 3 — including proposals for source-breaking changes. Will have an open discussion on that day on the fate of those unimplemented proposals in the context of Swift 3 and future Swift releases.
  • Starting on August 1 we will open up discussion about Swift 4. Part of this discussion will likely be guided by important work that was deferred from Swift 3, as well as the a goal of achieving binary stability in Swift 4. Until then, however, discussion should remain focused on Swift 3.
  • Note that there is an intentional gap of a few days between the last planned day to take source-breaking changes for Swift 3 and when we start talking about Swift 4. The idea is to provide some time for the community to take stock of where things have ended up for Swift 3.
  • The final branching plan for Swift 3 development is to be determined, but the final convergence branch is likely to be cut from master around that date or shortly after. Part of it comes down to the discussion on July 27 on how to handle the remaining unimplemented proposals for Swift 3.
  • The final release date for Swift 3 is TBD, but essentially after July 27 the intent is that Swift 3 is in full convergence and not in active development.

With these dates in mind, I want to call attention to some approved-but-not-yet-implemented proposals that currently I have nobody on Apple’s Swift team able to tackle in the next couple weeks:

Some proposals — like SE-0075 — are things we can add at any time, but many of the others tie into the goal of achieving some degree of source-stability for Swift in Swift 3. I’m letting the community know that these proposals currently have no implementation traction in case there is interest in helping make them happen in time for Swift 3.

Related, I’d like to call out a special thanks to the community for getting implementation traction on SE-0095:

Currently there is a JIRA issue and pull request tracking work on implementing this proposal.

In addition to these language proposals, there is also an assortment of outstanding work for the Standard Library that would be great to do for Swift 3. There is a gist summarizing those tasks:

These tasks are broken down in relative order of difficulty, with a JIRA issue associated with each one of them. If a JIRA isssue is currently not assigned to anyone, please consider them fair game to tackle if you are interested. API changes that have currently not gone through the evolution process will still need an evolution proposal, even if they are listed in the gist. If you take on a specific task, please assign the JIRA issue to yourself so others know it is being tackled.

Thank you to everyone — and I mean everyone — who has contributed to making Swift 3 happen.

Ted

Like my posts? Consider buying a book. Content Update #1 is live.

Paleogene Therapy: What’s up in Swift Evolution

Accepted

SE-0091: Improving operator requirements in protocols is accepted with minor revision. Team writes:

The second iteration of this proposal has been very well received by both the community and core team.  The core team requests one minor modification: in an effort to reduce the scope of the proposal, it should specifically require that operator declarations in classes be written as static (or equivalently, as “final class”).  In the future, support for operators may be extended to support dynamic dispatch, and the core team wants to keep the design space open.  The core team also observed that the impact on the standard library is not captured in this proposal, but that can be incorporated later (as an amendment to this proposal) since it should have little user impact.

SE-0107: UnsafeRawPointer API is accepted. Team writes:

The community and core team agree that this proposal clarifies the rules around the unsafe pointer APIs, while making them “work by default” and balance safety and unsafety in an understandable way. Andy has revised the proposal several times due to community feedback (which is why we extended the review period), which makes my job easier because the core team agrees to accept it nearly as-is :-). The only request from the core team is to remove the default value from the ‘alignedTo:’ parameters of the allocate and deallocate methods, forcing their callers to be explicit about the alignment required by an allocation.

SE-0118: Closure Parameter Names and Labels is accepted with (slight) modification. Team writes:

The proposal has been very well received by the community and core team.  The core team agrees with community contributions that “ManagedBuffer<Header,Element>.create(minimumCapacity: 10, makingValueWith: makeHeader)” should be renamed to “makingHeaderWith:”.  The core team extensively discussed the name of “lines.split(whereSeparator: isAllWhitespace)” and agreed to keep the name as proposed, because the alternative name “lines.split(where: isAllWhitespace)” could be confusing given the behavior of dropping the “separator” from the result.

SE-0086: Drop NS Prefix in Swift Foundation is accepted. Team writes:

This proposal has evolved greatly from a single bullet item in the original proposal for improving the translation of Objective-C APIs (SE-0005: Better Translation of Objective-C APIs Into Swift). Discussion spawned the transformative work on Foundation value types (SE-0069: Mutability and Foundation Value Types), and other improvements to the mapping of Objective-C APIs into Swift (e.g., SE-0033: Import Objective-C Constants as Swift TypesSE-0044: Import as MemberSE-0112: Improved NSError Bridging) have informed and improved this proposal.
The community and core team are overall positive on the removal of the Boolean protocol, under the rationale that it is not pulling its weight and its name is confusing next to Bool.  Several members of the core team and a member of the community points out that the *functionality* provided by the Boolean protocol could make sense for Swift if a well-considered design was available, but the core team feels that we should remove Boolean for Swift 3, and consider adding back a replacement when and if a compelling use-case presents itself to motivate that work.
The community and core team agree that this proposal is a huge step forward that enriches the experience working with and extending the Cocoa NSError model in Swift. The core team requests one minor renaming of “attemptRecovery(optionIndex:andThen:)” to “attemptRecovery(optionIndex:resultHandler:)”. It also discussed renaming CustomNSError and RecoverableError, but decided to stay with those names.
The community discussion and core team unanimously agree that this is the right thing to do.
The community and core team agree that this proposal is a better set of names for these protocols.  The core team agrees with the community sentiment that “By” is better than “As” in the protocol names, and has accepted the proposal with this revision.

Returned for Revision

SE-0117: Default classes to be non-subclassable publicly is returned for revision. Team writes,

The review of “SE-0117: Default classes to be non-subclassable publicly” ran from July 5…11, 2016. As expected, this proposal was extremely polarizing, with valid arguments on both sides. The opinions held by supporters and opposers are held very strongly, and hundreds of emails were generated in a healthy debate about this topic.

The review manager read every post on this topic, and the core team discussed this topic at length. The core team concluded three things:

  • First, the core team *agrees with conviction* that it is the right default for public classes to be non-subclassable outside their module, unless they carry some additional indication from the API author that the class was designed to be subclassed.
  • Second, there was insufficient discussion about anything *other* than the first point. The proposal also contains the “overridable” concept, which is highly impactful, but lacked significant discussion.
  • Third, the core team agrees that the concrete syntax of “subclassable class” is … suboptimal.

On the first point, there are three related arguments against SE-0117:

  • First is that clients of Apple frameworks often choose to subclass classes that Apple publicly documents as being “not for subclassing”, as a way of “getting their job done,” typically as a way to work around claimed bugs in Apple frameworks. The core team and others at Apple feel that this argument is analogous to the argument that Swift should “support method swizzling by default”. Swift loves dynamic features, but has already taken a stance against unanticipated method swizzling, by requiring an API author to indicate where they allow method swizzling with the ‘dynamic’ keyword. Almost all classes vended by Apple APIs are subclassable (which isn’t changed by this proposal) so this argument is not compelling to the core team, nor is it consistent with the existing design of Swift. It is also important to note that Cocoa also makes heavy use of delegation (via protocols) which allows client code to customize framework behavior without subclassing.
  • Second is that clients of some other public API vended by a non-Apple framework (e.g. a SwiftPM package) may end up in a situation where the framework author didn’t consider subclass-ability, but the client desires it. In this situation, the core team feels that a bigger problem happened: the vendor of the framework did not completely consider the use cases of the framework. This might have happened due to the framework not using sufficient black box unit testing, a failure of the imagination of the designer in terms of use cases, or because they have a bug in their framework that needs unanticipated subclass-ability in order to “get a job done”. Similar to the first point, the core team feels that the language is not the right place to solve this problem. Instead, there is a simple and general solution: communicate with the framework author and get them to add the capabilities that you desire. If they simply need to add subclass-ability, then that is no problem: it is a source-compatible change to a dependency.
  • Third is a longer-term meta-concern, wherein a few people are concerned that future pure-Swift APIs will not consider subclass-ability in their design and will accidentally choose-by-omission to prevent subclass-ability on a future pure-Swift API (vended by Apple or otherwise). The core team feels that this is an extremely unlikely situation for several reasons. First of which is that it heavily overlaps the first two concerns. More significantly, any newly-designed and from-scratch APIs that are intended for Swift-only clients will make use of a breadth of abstractions supported by Swift—structs, enums, protocols, classes. The primary reasons to use classes in Swift are subclassability and reference semantics, so the core team feels that the likelihood of accidental omission is small. Likewise, the decision to require every member of a public class to be marked public in Swift indicates a commitment (in line with SE-0117) that expects cross-module API authors to think carefully about the API they are authoring as well as their use cases.

To reiterate, as a summary, the core team *agrees with conviction* that it is the right default for public classes to be non-subclassable outside their module, unless they carry some additional indication by the API author that the class was designed to be subclassed. However, it does not yet have an opinion as to what that concrete syntax is.


To sum this all up, the core team is rejecting this proposal and requesting a revision to change the concrete syntax to “public open class Foo” instead of “subclassable class Foo”. This approach satisfies the *unwavering* goal of requiring additional thought when publishing a class as public API, makes subclass-ability orthogonal to access control, and (admittedly as a bit of a swift-evolution process hack) asks the community for an in-depth discussion of the secondary points of the proposal: does it make sense to require every member to be marked as “overridable” in order to be overridden by an open subclass outside of the current module?

The core team appreciates that this is a situation where it is impossible to please everyone, while also recognizing that the challenges faced by developers of pure-Swift code are not exactly analogous to those faced by Objective-C developers. Thank you to the many and diverse opinions and perspectives that have come in as part of this review cycle!

Team Updates

Update on SE-0111: Remove type system significance of function argument labels. Team writes:

Shortly after SE-0111 was accepted last week, several people newly noticed the proposal and started a discussion about how it appears to be a regression for closure parameters (e.g. callbacks) that could formerly carry labels, but are now not allowed to. These folks observed that it would be more expressive (and consistent with the rest of Swift) to allow parameter labels in function types, because the invocation site of a closure “should” be required to provide those labels. The core team has been following the discussion, agrees that this is a concern, and wants to update the community with a path forward.

The reality of the situation is that the current implementation of parameter labels in function types is inherently broken. Specifically, as one example, there is an implicit conversion from “(a: Int) -> Int” to “(Int) -> Int”. However, there is also an implicit conversion from “(Int) -> Int” to “(b : Int) -> Int”. This means that the compiler currently allows converting from “(a: Int) -> Int” to “(b: Int) -> Int”, which doesn’t make sense, introduces surprising behavior, introduces complexity into the compiler implementation, and is generally a problem. We do have one specific hack to prevent conversion of (e.g.) “(a : Int, b : Int) -> Void” to “(b : Int, a : Int) -> Void”, but this only triggers in specific cases. There are other more complex cases as well, e.g. when using generics “T<(a : Int)->Int>” cannot be considered compatible with “T<(b : Int)->Int>”.

These problems are what initially motivated SE-0111. However, given the feedback, the core team went back to the drawing board to determine whether: a) SE-0111 by itself is the right long term answer, b) whether there were alternate models that could solve the same problems in a different way, or c) whether SE-0111 was the right first step to “ultimate glory” in the field of closure parameter labels. After a long discussion, and many alternatives considered, the core team believes in c), that SE-0111 (with a minor modification) is the right step for Swift 3, because it paves the way for the right model over the long term.


The specific revision requested by the core team to SE-0111 is that all “cosmetic” labels should be required to include an API name of _. For example, this would not be allowed:

var op : (lhs : Int, rhs : Int) -> Int

instead, it should be spelled as:

var op : (_ lhs : Int, _ rhs : Int) -> Int

With this change, we believe that we have paved the way for a purely additive proposal (and thus, post-Swift 3) that will restore the expressive capability of closures with parameter labels.


Here is a sketch of how that would work, in two steps:
First, we extend declaration names for variables, properties, and parameters to allow *parameter names* as part of their declaration name. For example:

var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property.
x = op(lhs: 1, rhs: 2) // use of the variable or property.

// API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) {
    x = op(lhs: 1, rhs: 2) // use of the parameter
}

foo(opToUse: +) // call of the function

This will restore the ability to express the idea of a closure parameter that carries labels as part of its declaration, without requiring parameter labels to be part of the type system (allowing, e.g. the operator + to be passed into something that requires parameter labels).
Second, extend the rules for function types to allow parameter API labels *if and only if* they are used as the type of a declaration that allows parameter labels, and interpret them as a sugar form for providing those labels on the underlying declaration. This means that the example above could be spelled as:

var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax
x = op(lhs: 1, rhs: 2) // Same as above

// API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”.
func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) {
    x = op(lhs: 1, rhs: 2) // Same as above.
}

foo(opToUse: +) // Same as above.

These two steps will provide the simple and expressive design approach that we have now, without all of the problems that representing parameter labels in the type system introduces. The core team believes that the temporary regression in expressiveness is an acceptable loss for Swift 3, particularly given that this will have no impact on Cocoa or the standard library. In the case of Cocoa, recall that C and Objective-C don’t have parameter labels on their corresponding concepts (Blocks and C function pointers), and the higher order functions in the standard library should not require parameter labels either.

-Chris & the Core Team

 In Review

The names of things

Last night, someone was asking what you call the things created by types. My take on the subject is this: Classes, structures, and enumerations are constructs. You create new instances by calling a constructor, even when building things that aren’t reference types.

I avoid calling reference types “objects”. I stick with instances, following the Swift Programming Language’s lead, e.g. “Use the init?(rawValue:) initializer to make an instance of an enumeration from a raw value.” and “Create an instance of a class by putting parentheses after the class name.”

A big naming challenge derives from what do you call the thing that stores a value. The Swift Programming Language has this to say: “Use let to make a constant and var to make a variable”, which is not at all helpful because you end up saying “Declare a variable or constant”, “use the variable or constant as a parameter to the function”, etc, etc.

While constants and variables are “bound symbols”, “value bindings”, or just “bindings”, those are hard names to use in writing. “Create a value binding of 5” doesn’t communicate the way “create a new variable or constant and set its value to 5” does.

This is why, I prefer to stick with variable to describe both in any indeterminate situation. Constants are really immutable variables, egregious oxymoron and all. And, as Joe Groff points out, constants are still variables according to the mathematical meaning of the term.  It’s not a great solution but nearly everyone gets it.

So unless you’re going for precision, go ahead and declare a variable to store that value. If you don’t or won’t mutate it, the compiler will remind you to mark it as a constant. Long live “let variables“. It may not be technically precise but it does communicate expressively.

 

Swift Developer’s Cookbook Content Update #1 is live

I’m pleased to announce that the Swift Developer’s Cookbook content update has gone live. My editor writes:

Hi Erica,
The Web Edition has been updated and is live (I just registered my book and checked it). To access the Web Edition, anyone who purchases the book can just register it at Informit.com. After doing so, the Web Edition will show up on the Account page.
You can feel free to post a blog entry, tweet, et cetera that the first update is live.
Thanks,
Trina

Pearson’s Content Update Program is brand new. It has experienced significant challenges over the past months: floods in Chennai followed by a massive downsizing at Pearson, which caught the CUP point people in the layoffs. With luck, further updates will not take so long. It’s a very weird time to be in the technical writing business.

If you’ve purchased a copy of the book from any vendor, you should be able to register it with InformIT and receive access to the refreshed material. If you have any difficulties, ping @InformIT on Twitter.

Dear Erica: Why this Swift gotcha?

Hey There!  First of all I wanted to start by saying I read a lot of your stuff and am very appreciative of the time you take in writing down your thoughts, books and answering user emails.

I wanted to share with you a very interesting gotcha I stumbled upon today while working with Float currencies. Apparently when a Float is wrapped in an Optional, it loses its precision.  Here’s a screenshot to show what I’m talking about 🙂

3880CE58-D45C-4B56-89E6-BD091383024A

This isn’t a huge deal since unwrapping solves the problem, But I thought if someone would like an odd swift-WAT moment like this, It’d be you.  What do you think? Ever stumbled upon something of sorts?

Many thanks, Shai

I don’t believe this is a gotcha. I think what you’re seeing is that Optionals use different code to render their output descriptions than Floats. I created a workaround, submitted a bug report, and will explain here what’s actually going on:

To test whether an amount is “losing precision”, I started with your code:

let amount: Float? = 3.8
print(amount)
print(amount!)

And then I declared a non-optional amount:

let nonoptAmount: Float = 3.8

Floats are 4 bytes long. You can test this for the moment using sizeof(Float.self). (I have a proposal in that changes this call.) Your hypothesis states that unwrapping the value loses precision. So I performed an unsafe bitcast on both the unwrapped and the unwrapped amounts to UInt32, which is also 4 bytes long.

public func --><T, U>(value: T, target: U.Type) -> U? {
    guard sizeof(T.self) == sizeof(U.self) else { return nil }
    return unsafeBitCast(value, to: target)
}

let optbits = (amount! --> UInt32.self)!
let nonoptbits = (nonoptAmount --> UInt32.self)!

If the unwrapping has truly lost precision the two UInt32 values will have different bit representations, but they don’t:

print(String(optbits, radix: 2))
print(String(nonoptbits, radix: 2))

Screen Shot 2016-07-13 at 9.39.34 AM

Then I pushed the bits from the UInt32 back to a float and wrapped them in an optional, to make sure the results were the same. They were:

Screen Shot 2016-07-13 at 9.41.00 AM

What’s actually going wrong is that Optional does not conform to CustomStringConvertible, so when it prints it’s not leveraging the wrapped value’s preferred output style — assuming the wrapped value itself conforms to CustomStringConvertible.

So I went ahead and implemented an extension to let Optional take advantage of this protocol. Doing so, immediately changed the results of your print(amount)/print(amount!) output:

Screen Shot 2016-07-13 at 10.02.56 AM

Bug Report SR-2062

Update: Via Joe Groff at Swift JIRA:

This behavior is intentional. Optional does conform to CustomDebugStringConvertible.  We wanted to make it clear you’re printing a wrapped Optional so that in playgrounds or printf-debugging scenarios, it’s clear the value is wrapped.

The perils of fallthrough

Quick. Without testing or looking things up, tell me what is the outcome of running the following code:

let x = 5

switch x {
case 5:
    print("5")
    fallthrough
case 6:
    print("6")
default:
    print("anything else")
}

A lot of people get it wrong, including some coders I was helping out last evening. Fallthrough does have a compelling use case. But it doesn’t do what many people think it will, which can be summed up as “execute this case and then continue pattern matching”. When you’re looking for the conjunction of multiple tests without complex if-then-else statements, don’t use fallthrough. Either conjoin the cases with an associated where clause or use tuples.

My coder was attempting to test two variables, an integer count and a string as a proof of concept. His goal was to print “High count” for counts over 3. He also wanted to print either long or short name, depending on whether the string was over 5 characters, with appropriate capitalization. These are his four possible outcomes: “High count, long name”, “High count, short name”, “Long name”, and “Short name”.

A tuple approach might look like this:

func checker(_ count: Int, _ name: String) {
    let highCount = count > 3
    let longName = name.characters.count >= 5
    switch (highCount, longName) {
    case (true, true): print("High count, long name")
    case (true, _): print("High count, short name")
    case (_, false): print("Long name")
    case _: print("Short name")
    }
}

And a where clause approach like this:

func checker(_ count: Int, _ name: String) {
    let charCount = name.characters.count
    switch count {
    case 4 ... .max where charCount >= 5: 
        print("High count, long name")
    case 4 ... .max: print("High count, short name")
    case _ where charCount >= 5: print("Long name")
    case _: print("Short name")
    }
}

Although these  demonstrate how switch statements can handle multiple conditions without fallthrough, I don’t particularly like their code readability. I think the cases for this particular example would be better served with more explicit patterns:

case (true, true): print("High count, long name")
case (true, false): print("High count, short name")
case (false, true): print("Long name")
case (false, false): print("Short name")

When you go to the trouble of creating complex logic in switch statements, do everything you can to make the code self-document its conditions. This better supports inspection and enables the compiler to find incomplete logic coverage on your behalf.