Archive for April, 2016

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:

  • Familiarize yourself with this list of commonly proposed ideas.
  • Swift language changes should provide a highly focused tweak with limited impact and measurable benefits.
  • The baseline is not whether something is “nice to have”
  • 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.
  • If a feature doesn’t yet exist, show how it provides additional and non-trivial utility. (Xiaodi Wu)
  • If a feature should be removed, show how is harmful to the language or contrary to the direction in which Swift is evolving. (Xiaodi Wu)
  • Emphasize safety, speed, and expression.
  • Swift is an opinionated language.

Chris Lattner:

We intentionally want Swift to have a common “center of gravity” and be an “opinionated” language, rather than fall to the “design by committee” approach that leads to a watered-down design.  This means that decisions are really all shades of gray and cannot be specified or predicted by algorithm.  We aim to be as transparent as possible, and explain the rationale for decisions when they come out.

That said, I and many other people on the team are highly  motivated and effected by clear descriptions of problems being solved, and why current approaches are wrong.  Particularly moving are things written by people who are clearly familiar with Swift as it stands, and who speak to why a change will make Swift better.  

Someone saying “I saw thing X in language Y, so we should transplant it to Swift” – with no further justification – is not very motivating, because Swift is much different than any other language Y, and so the tradeoffs that make it compelling in Y may not translate over to make it compelling in Swift.

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?

The Tao of Pattern Matchage

Pattern or range to the left, value to the right:

if case .enumThing(let x, _) = value { ... }
if 100..<200 ~= value { ... }

The pattern matching operator is pronounced “twiddle-eek” not “bacon rocket”. Not only more fun to say but tells you the order in which to type the symbols. If you insist you’d rather “eeky-twid” instead of proper twiddle-eeking, you can always wrap your own:

infix operator =~ {
  associativity none
  precedence 130
}

public func =~<T : Equatable>(a: T, b: T) -> Bool { return b ~= a }
public func =~<I : ForwardIndexType where I : Comparable>(value: I, pattern: Range<I>) -> Bool { return pattern ~= value }
public func =~<I : IntervalType>(value: I.Bound, pattern: I) -> Bool { return pattern ~= value }
public func =~<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {return rhs ~= lhs }

Default reflection

Have you ever noticed how useless Swift’s class representations are? Value types automatically  show their members and values but classes don’t. What if you could add a simple way to automatically reflect those members, like with C2?Screen Shot 2016-04-18 at 12.55.01 PM

Mike Ash threw together an adorable solution that introduces a default reflection for any conforming class:

/// A reference type that provides a better default representation than the class name
public protocol DefaultReflectable: CustomStringConvertible {}

/// A default implementation that enables class members to display their values
extension DefaultReflectable {
    
    /// Constructs a better representation using reflection
    internal func DefaultDescription<T>(instance: T) -> String {
        let mirror = Mirror(reflecting: instance)
        let chunks = mirror.children.map({
            (label: String?, value: Any) -> String in
            if let label = label {
                if value is String {
                    return "\(label): \"\(value)\""
                }
                return "\(label): \(value)"
            } else {
                return "\(value)"
            }
        })
        if chunks.count > 0 {
            let chunksString = chunks.joinWithSeparator(", ")
            return "\(mirror.subjectType)(\(chunksString))"
        } else {
            return "\(instance)"
        }
    }
    
    /// Conforms to CustomStringConvertible
    public var description: String {
        return DefaultDescription(self)
    }
}

Unfortunately, you cannot (at least at this time) conform AnyObject and get this for free (“error: ‘AnyObject’ protocol cannot be extended”).

Manuel Carlos offers this:

Fast-tracking Swift reviews

I’d like to see Swift Evolution adopt a couple of styles of fast track reviews. Here’s how they would look.

STYLE ONE: Minor language enhancements AKA “Low hanging fruit”

It would help if the core team could add minor language enhancements without going through a formal proposal process with its normal review overhead. I have now been involved in several reviews that involved API changes that were otherwise unremarkable and primarily motivated by modernizing and style:

To this list, you could add:

Each of these proposals could have proceeded with a simple “any objections” sanity check discussion period rather than a more formal full review. As a another example (now unnecessary), consider the `dynamicType` keyword, which would have required a formal proposal to be modernized into Swift’s lowercase keyword standard. The hallmarks of these changes are:

  • They have limited impact
  • They increase language consistency
  • They are uncontroversial, offering simple, straightforward, and correct changes  that have already passed review in spirit, if not in letter
  • A preponderance of reviews are “+1” rather than in-depth discussions of why the proposal  should or should not be adopted.

I would recommend retaining a change document requirement for these proposals. This would be similar to a brief but formal proposal, that lays out the justification, detail design, and any associated background info for the change. Doing so would provide a historic record of the change and any notes from the team, and be in a form that would support the extraction of key details for use in release notes.

I do not know whether these would need to be grouped and numbered with the normal proposals or placed into their own numbering scheme.

STYLE TWO: Fast tracking viability

Once a draft has been discussed on-list and submitted as a pull request, I’d like to see a biweekly (or even once-a-month) Pull Request Review meeting from the core team where a review groups looks over the current pull-request queue and scores them: recommend closerecommend promoteneeds workdefer past 3.0. This approach:

  • Would offer closure to proposal authors who are otherwise unsure of the viability of their proposals
  • Naturally happens after a significant on-list discussion/pre-review period has already  taken place
  • Would allow the team to weed out proposals with significant issues before entering formal review
  • Would allow on-list reviews to give precedence to only those proposals that make sense both in the time context of Swift 3.0 and its overall design philosophy.

Swift is an opinionated language. This review style would introduce discernment and feedback slightly earlier in the process without stifling on-list discussion.

A few final thoughts

It is a given that Swift 3 is going to be the last opportunity to make large, code-breaking changes to the language. With that constraint, I’d like to see more time and effort go into improving Swift’s fundamentals. Any time, effort, and review that can be better spent getting collections and indices right rather than worrying about colons and casing is, in my opinion, worth a tradeoff in community control.

The natural tension between engagement and coherence requires a balance that serves the entire Swift community. Open evolution processes are, by nature, chaotic. Maintaining a coherent vision for something as complicated as Swift requires coordination and leadership.  That’s why the ultimate responsibility for adopting changes lies with the Swift core team, which establishes the strategic direction of Swift.

I hope by adopting these fast-track review styles that the Swift open source community can better focus on the big updates while making sure that the small details are attended to carefully and thoughtfully without overwhelming the process.