Playground Secrets: Update and new tricks

A big thanks to James Dempsey for tracking down not one but two new playground markup keywords. In addition to the new Xcode 7.3 experiment, note, and important markup, you can now add example and callout.

The example keyword adds a well-formated example that introduces a section that demonstrates a new concept:

Screen Shot 2016-05-03 at 9.46.55 AM

The callout in constrast lets you use any title you want, enabling you to add flexible tips, warnings, cautions, trivia, and so forth.

/*: - callout(Trivia): The superscript dot over a lowercase (or miniscule) letter i is called a [tittle](https://en.wikipedia.org/wiki/Tittle) and is considered an integral part of the letter's glyph. ![tittles](tittles.png) */

Screen Shot 2016-05-03 at 10.04.43 AM

One more great find in Xcode 7.3, is that the fuzzy auto complete pop-up now incorporates documentation markup so you can view the description of any selected item:

Screen Shot 2016-05-03 at 8.17.02 AM

I’ve updated both Documentation Markup and Playground Secrets to include the new tech features and expanded coverage with regard to callouts, Swift 3 upcoming features, and more.

Both books are available at iTunes and LeanPub. Your continued support enables me to keep revising these works and buy an occasional cup of coffee. Thank you!

Despite ridiculous technological difficulties with Pearson’s pilot Content Update Program, I am still pushing ahead with incorporating the Swift 2.2 changes into the Cookbook. (Pearson, if you haven’t heard, laid off about half or more of their workforce, has shut down  marketing, and is likely to close its developer library program.)

Despite these difficulties, I think the Cookbook (the name was chosen long before I started writing, and no, I couldn’t change it when it became clear that Swift was still evolving) is a darned nice addition to any development library.

I think you’ll like the book a lot if you can get past the title. It’s full of practical, sensible how-to and is perfect for anyone who has finished Apple’s tutorial and wants to start with real development.

Thank you for buying my books and helping me to support my family.

The great space-delimited comma war

From an intense disagreement this afternoon:

func foo<T: protocol<A,B>>(x: T)

vs

func foo<T: protocol<A, B>>(x: T)

Clearly the latter wins. But why? Because orthography matters.

Strunk writes, “omit needless words”. But Strunk did not write, “omit needless keystrokes”. Space-delimited commas offer semantic and syntactic separation between two related items. It follows the convention commonly used in mathematics.

A space-delimited comma supports natural language precedent allowing the eye to scan each token as a distinct entity. It serves as a pause signal for the code reader, allowing mental differentiation between the two elements (in this case, dual protocols).

Without that pause, the two protocols blend into an undifferentiated mass, especially as they are surrounded by the angle brackets used to construct the protocol conformance and type parameter. Allowing space to breathe creates a more readable product, and is to be preferred to its spaceless alternative[1].

[1] This advantage is to be conveyed to all users, whether or not they are Canadian in origin.

Dear Erica: Why doesn’t NSLog support Swift objects

Dear Erica, when I try to run the following code in a playground, Xcode dies, with the complaint “error: ‘NSLog’ is unavailable: Variadic function is unavailable NSLog(“%@”, Foo()) Foundation.NSLog:2:13: note: ‘NSLog’ has been explicitly marked unavailable here“. What gives?

import Foundation
class Foo {}
NSLog("%@", Foo())

Your first problem is that Foo is not an NSObject.  If you subclass Foo from NSObject, the error goes away and the log statement outputs “<__lldb_expr_24.Foo: 0x7fc9d2920210>“. Still not exactly what you’re looking for, I know.

The reason is that in our discussion going back and forth I know you wanted to use CustomDebugStringConvertible with NSLog and the way you make that happen is by using normal string interpolation with NSLog:

class Foo: CustomDebugStringConvertible {
    var debugDescription: String {return "Superfoo!"}
}

NSLog("\(Foo())")

Swift and NSLog aren’t really set up to do the format string interoperation you were looking for. However, if you’re bound and determined to do so, there is a solution:

class Bar: NSObject {
    override var description: String {return "Superbar!"}
}

NSLog("%@", Bar())

In this case, instead of trying to conform to CustomDebugStringConvertible, you override the built-in NSObject property to get the custom output you were looking for. Implementing description (OS X 10.10 and later) returns a string that “describes the contents of the receiver”. NSLog can then use this result to create a textual representation of your object, which can be used in a formatted string.

2016-05-02 14:12:43.106 Untitled Page 3[5161:524832] Superfoo!
2016-05-02 14:12:43.107 Untitled Page 3[5161:524832] Superbar!

Like in Swift native classes, NSObject also supports a debug variation (debugDescription, OS X 10.8 and later), which is preferred for presentation in the debugger.

Survival of the Swiftest: What’s up in Swift Evolution

Accepted

SE-0068: Expanding Swift Self to class members and value types is accepted with modifications:

The review of SE-0068: “Expanding Swift Self to class members and value types” ran from April 20…25, 2016. A subset of the proposal has been *accepted*:

This proposal had light discussion in the community review process, but the core team heavily debated it.  It includes two pieces:

1. Expanding the existing support for Self to work in value types, and in the bodies of classes.
2. Replacing the x.dynamicType expression with x.Self, a purely syntactic change that eliminates the “dynamicType” keyword.

The core team has accepted the first half for this proposal.  This allows the use of “Self” as shorthand for referring to the containing type (in the case of structs, enums, and final class) or the dynamic type (in the case of non-final classes).  Most of the discussion in the core team centered around whether people familiar with the former behavior would be surprised by the (more general) behavior when using it in a class, but they came to agree that this is actually a simple and general model, and a helpful point of consistency.

In contrast, there are still a number of concerns with rebranding x.dynamicType as x.Self.  This may (or may not) be the right ultimate direction to go, but it should be split out of this proposal.  There is another outstanding proposal that would eliminate the “Type.self” syntax as being necessary, and the core team would like to resolve that discussion before tackling x.dynamicType.

A third part of the proposal, already removed, which would introduce #Self, to be replaced at compile time with the calling context for use in return types, variable types, and debug statements, will also be deferred until after the “Type.self” syntax is settled.

SE-0065: A New Model for Collections is accepted.

We propose a new model for Collections wherein responsibility for index traversal is moved from the index to the collection itself. For example, instead of writing i.successor(), one would write c.index(after: i). We also propose the following changes as a consequence of the new model:

  • A collection’s Index can be any Comparable type.
  • The distinction between intervals and ranges disappears, leaving only ranges.
  • A closed range that includes the maximal value of its Bound type is now representable and does not trap.
  • Existing “private” in-place index traversal methods are now available publicly.

SE-0067: Enhanced Floating Point Protocols [ACCEPTED] enters Review #2 with incorporated feedback to 4/29. “Revision 2 reintroduces some of the details of the Arithmetic protocol from earlier drafts of this proposal, but as methods in the FloatingPoint API, with the goal of reducing the number of overloads for basic operations. This change was requested by some members of the core langauge team. Revision 2 also incorporates a number of suggestions from the review list and corrects some typos; thanks especially to Xiaodi Wu for thoughtful feedback.”

SE-0070: Make Optional Requirements Objective-C-only [ACCEPTED] in review to 5/3. “Swift currently has support for “optional” requirements in Objective-C protocols, to match with the corresponding feature of Objective-C. We don’t want to make optional requirements a feature of Swift protocols (for reasons described below), nor can we completely eliminate the notion of the language (for different reasons also described below). Therefore, to prevent confusion about our direction, this proposal requires an explicit ‘@objc’ attribute on each optional requirement to indicate that this is an Objective-C compatibility feature.”

SE-0071: Allow (most) keywords in member references [ACCEPTED] in review to 4/29. “The Swift API Design Guidelines consider enum cases as values that use the lowerCamelCase naming conventions. This means that case names that previously did not conflict with keywords (such as DefaultPrivateRepeat) now cause conflicts, a problem that is particularly acute when the naming conventions are applied by the Clang importer (per SE-0005). To mitigate this issue, this proposal allows the use of most keywords after a “.”, similarly to how SE-0001 allows keywords are argument labels.”

SE-0061: Add Generic Result and Error Handling to autoreleasepool() [ACCEPTED] in review to 4/26. Not to be confused with Generic Result and Error Handling in Deadpool. “The autoreleasepool function in the standard library does not currently support a return value or error handling, making it difficult and error-prone to pass results or errors from the body to the calling context.”

SE-0069: Mutability and Foundation Value Types [ACCEPTED]  in review to 5/4. This one gives “mutability when you need it” to wrap Foundation variations invisibly to Swift use.

SE-0017: Change Unmanaged to use UnsafePointer [ACCEPTED] in review to 5/3. “The standard library Unmanaged<Instance> struct provides a type-safe object wrapper that does not participate in ARC; it allows the user to make manual retain/release calls”. SE-0017 proposes to replace the use of of COpaquePointer with UnsafePointer<Void> and UnsafeMutablePointer<Void> in the Unmanaged API.

SE-0052: Change IteratorType post-nil guarantee [ACCEPTED] in review to 5/3. “Currently, the documentation for IteratorType.next() has the precondition that when calling next(), no preceding call to next() should have returned nil, and in fact encourages implementations to raise a preconditionFailure() for violations of this requirement. However, all current 27 IteratorType implementations in the standard library return nilindefinitely. Many users are likely unaware of the precondition, expecting all iterators to return nil indefinitely and writing code that might rely on this assumption. Such code will usually run fine, until someone does in fact pass in an iterator not repeating nil (it’s a silent corner case).”

SE-0032: Add find method to SequenceType [ACCEPTED]  in review to 5/3. I have personal issues with SequenceType, namely that there may non-terminating sequences. My issues have nothing to do with this proposal, which Kevin clarifies: “I have seen people write code like seq.lazy.filter(predicate).first, but this doesn’t actually work lazily because .first is only a method on Collection, which means the call to filter() ends up resolving to theSequence.filter() that returns an Array instead of to LazySequenceProtocol.filter() that returns a lazy sequence. Users typically aren’t aware of this, which means they end up doing a lot more work than expected.”

SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib [PARTIALLY ACCEPTED: parts returned for bikeshedding over the naming] in review to 5/3Love the proposal. Hate the name mismatch. Either prefix/suffix or take/drop makes more sense to me. Worse, the beautiful and fairly obvious iterate is under fire and may become something like “ice ice baby” or “unfold(_:applying:)“. This review gets all the +1s, except for the naming.

In Review

  • SE-0060: Enforcing order of defaulted parameters In review to 5/9. I vote no. Details at link.
  • SE-0066: Standardize function type argument syntax to require parentheses in review to 5/2. “This proposal suggests that we simply eliminate the special case and require parentheses on all argument lists for function types.” I’m strongly for this one.
  • SE-0072: Fully eliminate implicit bridging conversions from Swift runs to 5/2. “In Swift 1.2, we attempted to remove all implicit bridging conversions from the language. Unfortunately, problems with how the v1.2 compiler imported various un-annotated Objective-C APIs caused us to scale back on our ambitions. In the interest of further simplifying our type system and our user model, we would like to complete this work and fully remove implicit bridging conversions from the language in Swift 3.”
  • SE-0073: Marking closures as executing exactly once in review to 5/9. “This proposal introduces an optional once argument to the @noescape attribute. The @noescape(once) attribute enforces that the closure does not escape, and that it is run exactly once on any code path returning from the function. For clients, it allows the compiler to relax initialization requirements and close the gap between closure and “inline code” a little bit.”
  • SE-0074: Implementation of Binary Search functions in review 5/9. “Swift does not offer any way to efficiently search sorted collections. This proposal seeks to add a few different functions that implement the binary search algorithm.”
  • SE-0076: Add overrides taking an UnsafePointer source to non-destructive copying methods on UnsafeMutablePointer in review to 5/9. “UnsafeMutablePointer includes several methods to non-destructively copy elements from memory pointed to by another UnsafeMutablePointer instance. I propose adding overloads of these methods to UnsafeMutablePointer that allow an UnsafePointer source.”
  • SE-0078: Implement a rotate algorithm, equivalent to std::rotate() in C++ in review to 5/9. “There are three different versions of the rotate algorithm, optimized for collections with forward, bidirectional, and random access indices. The complexity of the implementation of these algorithms makes the generic rotate algorithm a perfect candidate for the standard library.”
  • SE-0080: Failable Numeric Conversion Initializers in review to 5/9. “Swift numeric types all currently have a family of conversion initializers. In many use cases they leave a lot to be desired. Initializing an integer type with a floating point value will truncate any fractional portion of the number. Initializing with an out-of-range value traps. This proposal is to add a new family of conversion initializers to all numeric types that either complete successfully without loss of information or throw an error.”

Awaiting Scheduling

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

Dipping toes into coworking

As George RR Martin would have put it if his kids were in public school: Summer’s coming. (“A Song of Bored and Cranky”) This Summer, I plan to try to use some coworking spaces to get the heck out of the house and away from the kids for a couple of days a week.

So far, I’ve tried out “eat-working” (Starbucks, Panera, Einsteins), which really doesn’t offer the kind of long-term desk situation I’m looking for, “public-working” at the library, which had iffy chairs and tables and intermittent Internet, and (so far) one commercial day trial, which had great desks, horrible chairs, nice ambience, but a no-talking policy which meant I couldn’t conference, use my phone, or use Siri except by stepping outside. (And absolutely no way to turn up the iTunes volume and shout it out, shout it out loud…)

If you’ve coworked and have any recommendations for what I should be looking for in a good coworking space, please share. I’m not exactly looking for place recommendations (unless you have specific ones to mention) but more to put together a list for myself of what makes a good coworking environment so I can better evaluate what I”m looking at before committing to any monthly or longer contract. I’d appreciate any advice you have to offer.

I’m looking for something fairly local, inexpensive, with good business-level WiFi, comfortable business-level chairs and desks (I can bring in my own lumbar cushion and footstool if needed), safe area, clean bathrooms, nearby shops, a microwave, easy in-and-out, and  daylockers of some sort so I don’t have to carry absolutely everything in and out with me every time I hit the bathroom or go to lunch. I’d also like to be surrounded more by tech folk than marketing folk but I recognize that’s not going to be something I can control.

I will say that while I was remarkably productive on my days out, I was productive in all the wrong ways: I zoomed through my correspondence. I’m now set up beautifully with my calendar and with “Things“. I got nothing done on actual development or real writing work. And I did nothing that needed phones, such as making appointments or checking in on projects. I also found it really hard to take breaks, stretch, and just do the “wander and think” thing.

What kind of work opportunities do you reserve for outside your office? And how do you adapt your workflow to small screens (I have the new MBP with me), strange places, and ergonomic limits?

Thanks in advance for your thoughts.

Ruby Tuesday: Slicing arrays

A friend writes, “So I want earch_slice, something like [1,2,3,4,5,6] / 2 == [[1,2],[3,4],[5,6]]. How do I get that in Swift?”

I recommended using a lazy sequence, consuming n indices at a  time.

extension Array {
    func sliced(by n: Int) -> AnySequence<ArraySlice<Element>> {
        assert(n > 0, "Slice must be positive integer")
        var idx = self.startIndex
        return AnySequence {
            return AnyGenerator {
                if idx >= self.endIndex { return nil }
                let nextEnd = idx.advancedBy(n, limit: self.endIndex)
                defer { idx = nextEnd }
                return self[idx ..< nextEnd]
            }
        }
    }
}

From there you can use for-in to produce [1, 2], [3, 4], [5, 6], etc:

let testArray = [1, 2, 3, 4, 5, 6]
for x in testArray.sliced(by: 2) { print(x) }

He responded, “Sure you can like [1,2,3,4,5,6].each_slice(2) and get sets of [1,2] but you have to push them somewhere, don’t you? Like tmp = []; [1,2,3,4,5,6].each_slice(2) {|x| tmp.push(x)}?

With Swift, you don’t really have to push a sequence anywhere. It’s more a promise of data than the data itself. Just hold onto it and use it when you need it.

If you want to force things and collect results into an array, you can initialize an array with a sequence:

let result = Array(testArray.sliced(by: count))

But what you get from this is actually an array of array slices, which is what my generator produces. To build an array of arrays instead, a little functional application converts each slice into an array:

let result = Array(testArray.sliced(by: count).map(Array.init))

According to ruby-doc.org, each_slice(n) returns groups of n items at a time with the final group containing the remainder. I based my odd cases on this behavior:

// Test odd slicing
print("test", Array(Array<String>().sliced(by: 1)))
for count in 1 ... 7 {
    let y = Array(testArray.sliced(by: count).map(Array.init))
    print(count, y)
}

 

The rules of Swift Evolution

Not a complete list but a few I’ve made note of:

  • Swift language changes should provide a highly focused tweak with limited impact and measurable benefits.
  • Fix real problems, not theoretical ones.
  • A proposal should introduce a single distinct change. If a proposal introduces multiple changes, it should be separate proposals.
  • Try to break things before 3.0 and not after.

Dear Erica: String matching without Foundation

Dear Erica, what is the best way to string.contains(substring) … without Foundation?

Of course, after this initial query, I was told what he wanted was really hasPrefix and not contains. This led me on a merry chase through strstr and a bunch of other ridiculous approaches, until Mike Ash suggested using startsWith and SequenceType.

The following contains ended up being pretty brute force (there’s a better version by Oisin K below) but prefixedBy does what seems to be needed. I renamed it so it didn’t overlap with the existing OS X hasPrefix.

And here’s the much nicer version from Oisin Kidney, which performs a kind of mapcdr approach.

Oisin points out that you also may want to check out this Swift version of the Boyer-Moore algorithm by Marcin Krzyżanowski.

So I probably could have spent a half an afternoon more productively but it was nice to dive back into C interop, especially touching base with pointers (strstr returns a pointer offset, so no Swift value types thank you) and remembering how to allocate, write to, and use memory directly. So not a complete waste.

It should be noted that my limited interest in diacriticals and other niceties would have come into play eventually. Using Swift-specific solutions offer a much better approach.

SE-0066: The one-argument function outlier

Swift requires parentheses when you declare a function:

f(x: T) -> U

Swift requires parentheses when you call a function

let _ = f(value)

Swift only requires parentheses when you declare a function type if the function takes 2 or more arguments:

let g1: (T) -> U // legal
let g2: T -> U // legal
let g3: (T, U) -> V // legal
let g4: T, U -> V // illegal

SE-0066 proposes to standardize function type argument syntax and discard that one legal outlier case (g2).  It introduces no changes to the syntactic sugar used for closure short-hand. All it does is clean up this one outlier case.

This proposal has led to heated discussion on the Swift Evolution list with Alan Skipp representing the surprisingly large push-back. He writes, “I’d place the ability to omit parenthesises for single args in the same category as being able to omit `self` when accessing properties. They are small conveniences that make a large difference to an entire codebase.”

John McCall writes, “To me, the unparenthesized style suggests that the input and output are peers, which feels more natural for the sort of value-to-value transform/predicate where this most commonly occurs.”

Radosław Pietruszewski writes, “To me, `func blah(f: Int -> Float) -> String` is easier to read that `func blah(f: (Int) -> Float) -> String`.” He also has concerns regarding Swift’s future should Swift adopt higher order functions.

Some list participants feel that (T, U) -> (V, W) reads more as tuple-to-tuple than 2-arguments-to-tuple. The actual tuple-to-tuple declaration is ((T, U)) -> (V, W) and would not be affected by this proposal.

Even the Void typealias has come under fire, with some members requesting that it be entirely banned.

Personally, I like SE-0066 and support its adoption. I also much prefer `func blah(f: (Int) -> Float) -> String` to `func blah(f: Int -> Float) -> String`. To me the consistency outweighs any minor savings in the odd parenthesis here and there, and clarifies the domain-to-range projection over using input and output peers.

Chris Lattner writes, “[R]egardless of why we always require parentheses on Decls and ApplyExprs, we really do (and that isn’t going to change).  Being consistent between func decls and function types is quite important IMO.”

If you’d like to jump into the discussion, SE-0066 should be up for review soon and the discussion on the initial pitch is active…and lively.

Style q: Returning on default?

SASDOE asks, “by convention if everyone of my cases returns, should default break and there be a return after the switch or should the default return?”

Screen Shot 2016-04-20 at 8.03.54 AM

If the behavior and style is consistent throughout an all-cases switch, I’d perform the return in the `default` case. Only break if there’s a significant difference in how the default case is handled. For example, when you need to perform clean-up work, workarounds, or recovery.

I promised to throw this out there for other opinions and guidance. What do you do?