By Casey Liss
 

This week I joined Lisa Schmeiser, Dan Moren, and Mikah Sargent on Clockwise.

In this episode, we discussed our [probably questionable] security practices, services we yearn for, Twitter’s experiments with reply limitations, and apps we’ve recently fallen in love with.

Fast and fun without fail, Clockwise is always a blast.


 

One of my favorite holiday traditions — the Do By Friday holiday party — has happened again. As with last year’s, my fellow ATP co-hosts and I joined the Do By Friday hosts, including Kevin Budnick, to have a holiday party.

To discuss the goings-on of the episode is to take an express train to Spoiler City, so I’ll just say that this one was a fun one.


Neat Swift Trick: AnyIterator

As with all programming posts, we start with a completely contrived example that makes no sense in the real world.

Say you’re writing ListOfIntegers, which is, well, a list of integers. In the real world, you’d absolutely use Array<Int> or something similar. Just go with me on this.

We can start this way:

class ListOfIntegers {
    typealias Element = Int
    private var backingStore = [Int]()

    init() { }
    init(_ value: [Int]) {
        self.backingStore = value
    }
}

At a minimum, you probably want your ListOfIntegers to be a Sequence, so you can iterate over your list. Thus, you need to provide a makeIterator() function. This provides the Iterator that will allow Swift to perform that iteration.

Creating an Iterator seems like a whole lot of work, involving making a whole new subtype. No thanks. I’m lazy; that’s why I’m a developer.

AnyIterator

This week I discovered a very neat shortcut: AnyIterator<T>. When I first saw this struct, I thought it was simply there for the purposes of type erasure. Looking through the class documentation, however, I found this gem:

/// Creates an iterator that wraps the given closure in its next() method.
init(_ body: @escaping () -> Element?)

Wait… what?

If you look at IteratorProtocol, it’s rather simple:

public protocol IteratorProtocol {

    /// The type of element traversed by the iterator.
    associatedtype Element

    /// Advances to the next element and returns it, or 
    /// `nil` if no next element exists.
    mutating func next() -> Self.Element?
}

Suddenly AnyIterator<T>'s init(:)'s comment makes sense:

Creates an iterator that wraps the given closure in its next() method.

By providing a closure to the init(:), we can provide an implementation for this Iterator’s next() method. Sweet!

Adding an Iterator to ListOfIntegers

We can leverage this to easily add an Iterator to our ListOfIntegers:

class ListOfIntegers: Sequence {
    typealias Element = Int
    private var backingStore = [Int]()
    
    init() { }
    init(_ value: [Int]) {
        self.backingStore = value
    }
    
    func makeIterator() -> AnyIterator<Int> {
        // We establish the index *outside* the
        // closure. More below.
        var index = self.backingStore.startIndex
        // Note the use of AnyIterator.init(:) with 
        // trailing closure syntax.
        return AnyIterator { () -> Int? in
            // Is the current index before the end?
            if index < self.backingStore.endIndex {
                // If so, get the current value
                let currentValue = self.backingStore[index]
                // Set a new index for the next execution
                index = self.backingStore.index(after: index)
                // Return the current value
                return currentValue
            } else {
                // We've run off the end of the array, return nil.
                return nil
            }
        }
    }
}

A couple things to note here:

  1. We’re expressly returning AnyIterator<Int> instead of the default ListOfIntegers.Iterator. The latter would require us to have a second typealias to specify the type of the Iterator; by being explicit, the compiler can infer ListOfIntegers.Iterator to be AnyIterator<Int>.
  2. When I first wrote this, I made the rookie mistake of creating var index within the closure. This meant that every time the iterator was asked to move to the next element, instead it just started over. 🤦🏻‍♂️ Thus, it’s important to create your index outside the closure, so it doesn’t get reset every time you call next().
  3. Since we’re using an Array<Int> as our backing store, a much simpler implementation would be to simply
    func makeIterator() -> Array<Int>.Iterator { 
        return self.backingStore.makeIterator() 
     }
    
    but that would defeat the purpose of this post.

I don’t often find myself in a situation wherein I need to create a custom Sequence; much less, a custom Iterator for that Sequence. However, when I find myself needing a custom Iterator in the future, I’ll certainly start with AnyIterator<T>.

If you’d like to play with this in a Playground, I’ve put the code up in a gist. Just copy/paste that into a new Playground.


 

It’s the holidays, so the ATP Store is back!

For this season, we have a new retelling of an old story. We’re continuing to suck what we can out of returning to the //////ATP logo, but this time, doing so in six colors and two modes.

All the shirts are available in both men’s and women’s cuts, in tri-blend and 100% cotton.

First we have ATP’s take on the Six Colors theme:

Shirts in light mode

Additionally, we have the same in Dark Mode:

Shirts in dark mode

We also have some older merchandise returning:

Everything except the pins is available for pre-order until Sunday, November 17. Don’t miss out! Every year we hear stories of people who procrastinated, and then missed out! Don’t be that person. Order now!


 

I can’t remember the first time I saw Sneakers, but I was surely no more than around ten years old. A nerd since birth, but more recently discovering my future as a computer nerd, Sneakers spoke to me like few movies of the time were able to. It was fun, interesting, and exciting.

I didn’t understand half of it, but I didn’t care.

As a grown man, I can see there’s so much more to Sneakers than I had ever understood as a kid. It’s a much deeper movie than I gave it credit for, and in these awful times, more prescient than I’m comfortable with.


As I’ve said before, I consider The Incomparable to be the major leagues of podcasting. I’ve appeared on the show a couple times before, and every time, it’s a tremendous honor.

On this episode, I was joined by host Jason Snell, my ATP co-host John Siracusa, Erika Ensign, and Dan Moren to discuss the film. I had a blast, and if you’re my kind of nerd, I think you will enjoy it too.

One of these days, if I’m asked to return, I’ll remember to come up with a pithy closing remark. 🤦🏻‍♂️


 

This week I joined Brianna Wu, pinch-hit blast-from-the-past host Jason Snell, and my long-lost-twin Dan Moren on Clockwise.

In this episode, we discussed our plans for macOS Catalina, the software/hardware we’d most/least like to lose, good OSes on bad hardware, and the legality of accessibility on the web.

Clockwise is always fun and always fast. If you’ve somehow missed out on the show so far, today’s a great day to jump in.


As discussed on recent episodes of ATP, I’ve had some issues with my iMac lately. A trip to the Apple Store and new logic board later, I had functional hardware but no software installed upon it. Finally, I had the opportunity to try out something I’ve been preparing for a long while: my Brewfile.

Much in the spirit of Ruby’s Bundler, Homebrew has Bundle. For both Bundler and Bundle, you provide a file with a list of software/dependencies you want installed, and the apps will install them automatically. In the case of Bundler, it’s all Ruby gems; in the case of Bundle, it’s command line apps, Mac apps, and even fonts.

Last week, I loaded up my iMac from scratch using a Brewfile I had been adding to over the last couple years. Finally getting the opportunity to use it has given me the opportunity to refine it.

These refinements ended up being extremely convenient, as just yesterday I decided to nuke my MacBook and reload it to try to get it operating properly. Thanks to Bundle, that took considerably less time than it would have in years past.

Terminal.app re-running Homebrew Bundle

All it took was having ~/Brewfile, and then running

brew bundle install

Give it a bit of time — a lot if you’re installing Xcode — and just like that most/all of your favorite software is installed. All in one easy peasy command line incantation.

I can’t overstate how much time this has saved me. 🥳

Furthermore, as I add new items to my Brewfile, I can feel free to run brew bundle install again. It will automatically skip software that’s already installed. In fact, the screen shot above was me re-running Bundle long after it had worked its magic.

Your Brewfile is unique to you; it’s a distillation of your own particular toolchains and requirements. There are many like it, but this one is mine.


UPDATED 2019-10-09 3:00 PM: Several people have asked “okay, but, how do I create a Brewfile to begin with?”

For me, I went spelunking through /Applications to see what I had and what I knew I couldn’t live without. Generating my Brewfile from scratch was, to no small degree, the point.

If you’d like to take a shortcut to get yourself started, you can do:

brew bundle dump

This will create a Brewfile of everything Bundle recognizes on your existing system. At that point, you can go through and cull what you don’t think you really need.


 

Finding a new podcast is a double-edged sword. I’m already living in a state of near-bankruptcy when it comes to my podcast queue. Adding something new is a decision I don’t take lightly.

Fun Fact is my most recent add, and I did so within the first couple of episodes. It’s a really fun and silly — yet serious — show about little nuggets of information you probably didn’t know.

Never condescending, hosts Arik and Allen bring a couple of little tidbits to the table each episode. The meandering path that these gems take us is most of the fun.

Despite the dubious decision of putting Follow Up (©️ 2011 John Siracusa) at the end, Fun Fact is a great show that I’m glad I found.


On this fortnight’s episode, I stood in for new dad Arik. Allen and I discussed quiet places, odd ways to represent state geography, software asset management, jazz music, and took a trip down 90s memory lane.

I stressed out a lot over choosing good and fun facts to bring to Allen; hopefully I did at least a passable job. 😊


 

Last night I recorded a podcast with my pal Tyler Stalman on his show, The Stalman Podcast. Tyler received review units of the iPhone 11, iPhone 11 Pro, and Apple Watch Series 5. After a whirlwind day of him testing the phones, Tyler made some time to sit down with me to discuss them.

In this episode, I turned the tables on Tyler and interviewed him. As a professional photographer, Tyler naturally had a lot of thoughts about the new two-camera system on the 11 and the three-camera system on the 11 Pro.

I had a ton of fun recording this with Tyler, and for those of you waiting in line tomorrow, or debating buying a new iPhone, this episode is for you.


 

Just over five years ago, Myke and I announced Analog(ue). It doesn’t feel like it was that long ago, but here we are. Analog(ue) is older than both of my children; Myke and I have released 163 episodes of the show. Not bad for something we thought would peter out after ten or twenty episodes.

To celebrate Analog(ue)'s Relay’s fifth anniversary, over twenty hosts joined Myke and Stephen in San Francisco to record a live game of Family Feud. It was a blast, and probably the zaniest podcast I’ve ever been a part of.

The whole episode is up on the Connected feed, if you’d like to have a listen. There may be video in the future, but no guarantees. If there is, I’ll link it here.