Six Friends, Ten Seasons

Growing up in the 1990s, the only TV that I watched regularly was PBS, Jeopardy!, and The Price is Right. I've since learned that I have quite a bit to catch up on.

My wife and I recently finished watching all ten seasons of Friends, both of us for the first time. Friends aired from 1994 to 2004, and we were struck by how it felt so ahead of its time. Given some of the hot topics that were frankly discussed, it's no wonder my parents disapproved. I'm glad we finally took the plunge, as it's now officially one of my favorite TV shows.

(Spoilers follow, but as I'm the last person on Earth to watch this show, it shouldn't matter much.)

The characters were great, though I sometimes got annoyed with Ross for being a big baby. A few episodes in, I remember saying to my wife, "Phoebe is so weird; why are they friends with her?" I take it all back now, though, having seen Phoebe grow into the most kind and understanding character.

The show was funny throughout all ten seasons. There were no "bad" seasons that I'd recommend skipping entirely—just an episode here and there that was perhaps less funny than the others. Compared to another of my favorites, Star Trek: Voyager, this is quite an accomplishment. Voyager may have had higher highs, but its lows were certainly lower in some particularly slow episodes.

9/11 occurred only weeks before the airing of season eight. Throughout that season, there was a subtle, yet noticeable increase in the number of American flags in the background, and Joey often wore FDNY shirts, too. I wouldn't consider myself especially patriotic, but these small choices in art direction were meaningful.

I enjoyed the frequent cameos throughout the show, which were always heralded by several seconds of raucous cheering from the studio audience. This was especially amusing when I had no idea who the guest was, since—again—I didn't watch much TV in the 1990s. Perhaps my favorite cameo was when Brent Spiner (that's Data from Star Trek: Next Generation) appeared as a representative from Gucci.

I do have two quibbles with the show's narrative choices towards the end.

First, though I very much like Paul Rudd in general, I could never bring myself to care about his character Mike at all. I was always rooting for Phoebe and Joey to end up together, as she was the only character who really understood Joey. I would even have been okay with Phoebe and David, the scientist who spends most of the series stuck in Minsk. Mike felt like a last-minute addition, and his character was never developed well enough for me to be interested. I ran this opinion by my wife, who suggested that it would have been too cliché for the six friends to all end up paired off with each other. Fair enough; if Mike's role was to avoid this ending, then he fulfilled his role well.

Second, I was disappointed that Rachel had to give up her new job in Paris to stay with Ross. I was excited for her to continue advancing her career, especially since she admitted that she'd gotten all she could out of her previous job at Ralph Lauren (not to mention her history of awkward interactions with her boss there). I didn't think it was fair for her to have to give up her new job just because Ross asked, especially since Ross just got to enjoy a career-advancing move of his own by getting tenure. My wife suggested that Rachel did already have a baby to take care of in New York City, so leaving the country for a job should have already been out of the question by default. This is also a fair point, and I have to agree—in the end, I'm just happy that Ross and Rachel finally got their heads in the game and got together once and for all.

Yet these minor points are the only complaints I can surface. Series endings are often treacherous—the worst possible example being that of How I Met Your Mother, which carelessly squandered and reverted eight seasons of character development just to tick some items off of a stale, pre-planned story checklist. Friends, in stark contrast, pulled off a triumph of an ending.

Friends captured a certain magic that happens when you are lucky enough to have a group of close companions that truly experiences life together. I've only felt this a few times in life: in grade school, at Baylor, and most recently at my gym. In Friends, as in real life, these moments come and go. The ending of Friends was a perfect reminder that even after an ending, there is always time for reflection and another cup of coffee with the special people in your life.

Repetition in Swift

A couple of years ago, partially just for fun and partially for a school assignment, I wrote a Sudoku puzzle solver in Java. The core of the program was a handful of state-checking functions. Each of these looked at the current state of the board and did a few tests to see if any new numbers could be placed.

If any one function solved and placed a number, all the checks needed to be run again using the new board state. The functions were called repeatedly until the board state no longer changed between executions. Since some checks were faster and more basic than others, I had an elaborate system of recursive calls and boolean didAnythingChange checks. The program worked pretty well, but got stuck if there wasn't enough information to produce a solution. If the board started out with only one number marked, for example, the program would fail, as it didn't do any brute-force searching for solutions.

I've recently been playing around with creating an iOS app to implement my personal strategy for a favorite board game. As it is somewhat a puzzle-based game, the solution process is similar. The app needs to run some checks on the game state until the checks turn up no new information. This game is a bit simpler than Sudoku, so I'm not worried about prioritizing certain checks over others.

Remembering the mess of recursive calls I wrote for the Sudoku solver, I thought to myself, there has to be a better way...

Enter the repeater:

func repeat(function: () -> (), untilNoChangeTo sentinel: () -> String) {
    var initial, final: String
    
    do {
        initial = sentinel()
        function()
        final = sentinel()
    } while initial != final
}

In this example, the game board state is condensed into a String that serves as a poor man's hash of the game state. When used as below, the repeat function takes care of monitoring the game state and repeating as necessary.

class Game {
    func checkForSolution() { ... }
    func gameState() -> String { ... }
}

repeat(game.checkForSolution, untilNoChangeTo: game.gameState)

For my new app, repeat calls a parent function that, in turn, repeats the individual solution-checking functions. This is probably a bit overenthusiastic, but as the game state for this particular game isn't too complex, I'll give it a pass for now.

I like this repeat function, but it's a shame that it's tied to String. There must be a better way...

Enter generics.

func repeatGenerically<T: Equatable>(function: () -> (), untilNoChangeTo sentinel: () -> T) {
    var initial, final: T
    
    do {
        initial = sentinel()
        function()
        final = sentinel()
    } while initial != final
}

Only a few changes are needed to make the function much more reusable. Dropping in the generic type <T> takes care of almost everything. The last modification is specifiying that T must be Equatable, since we need to compare two values of type T after the do-while.

This was a fun discovery, one of the many made possible by Apple's use of Swift to nudge programmers into the 21st century. Here's a Gist if you want to give either of the above repeat functions a spin.