Julian Simioni

Deconstructing Fizz Buzz with Flip-Flops in Ruby

| Comments

Ruby is small. If it’s not your first programming language, picking up all the basic syntax in a weekend isn’t out of the question. I’ve been writing and reading Ruby code for several years now, and figured I was closing in on at least familiarity with all the core concepts.

Of course, there’s always more to learn, and there were more than a few very experienced Ruby programmers that learned about a new operator last week: the flip-flop.

Nithin’s blog post gives a great overview of the syntax, so lets look at a more complicated example from Reddit:

1
2
3
4
5
6
a=b=c=(1..100).each do |num|
  print num, ?\r,
    ("Fizz" unless (a = !a) .. (a = !a)),
    ("Buzz" unless (b = !b) ... !((c = !c) .. (c = !c))),
    ?\n
end

This code clearly came from an obfuscation contest1, and I’m not even going to attempt to suggest that I understood how this code worked after first reading it. But I was intrigued. Never mind the flip-flop operator, most of this code looks unfamiliar to someone used to reading idiomatic Ruby, and I wanted to know how it all worked. So lets break it down piece by piece, and see if some sense can be made.

Starting out with some assignment

The first line is perhaps the most normal. Chaining assignment is used frequently in many languages. And while many of the methods we use in Enumerable, like map, return something useful, the each method is actually defined on the Range class, and just returns the range.

But the code above uses the a, b, and c variables before the each iterator finishes, what is their value then? Let’s run a simple test script to find out:

1
2
3
4
5
# a no-op each
a = (1..2).each do |num|
  puts a.inspect # => nil
end
puts a.inspect # => (1..2)

Aha, it just is set to nil. Of course a variable that isn’t first initialized will throw an error, so this first line is really just a short way of initializing the a, b and c variables to something, before the start of the iterator. Let’s do out first refactor of the code then, to make it more readable:

1
2
3
4
5
6
7
a = b = c = nil
(1..100).each do |num|
  print num, ?\r,
    ("Fizz" unless (a = !a) .. (a = !a)),
    ("Buzz" unless (b = !b) ... !((c = !c) .. (c = !c))),
    ?\n
end

This code works the same way, so we know it was really a refactoring, with no changes to the behavior of the code.

Fun with Printing

The next line is actually the entire body of the block passed to each: the print method takes multiple arguments, and notably, does not automatically print a newline at the end (puts on the other hand, does always print a newline).

But what in the world does ?\r do? It turns out to be a poorly-documented character literal. It’s one character shorter than creating a string, such as "\r", but with the same result.

And what is "\r" anyway? It’s a carriage return, the little known sibling of the newline. Even in the 21st century, our computer screens still basically behave like a typewriter. Advancing to the next line and moving the cursor to the start of the line are two distinct actions, and so they have distinct character codes. Of course, the fact that Windows requires both a carriage return and a newline character, whereas Linux and OS X systems assume a carriage return with just a newline2, creates more than a little confusion.

So, in any case, what sort of behavior can a carriage return character give us? Let’s run a few experiments:

1
2
3
print "hello", " ",  "world", "\n" # => hello world
print "hello", "\r", "world", "\n" # => world
print "hello", "\r", nil    , "\n" # => hello

How interesting! A carriage return lets us write some text, and then later while writing the same line, essentially decide to erase that text. Remembering the requirements of the Fizz Buzz problem, and how one must ONLY print a number when neither Fizz nor Buzz are printed, the utility of this behavior is obvious.

Finally, flip-flop

At this point we can easily describe the overall structure of the code: it loops through the numbers 1 to 100, using control characters to optimistically print the number, and then based on the logic of flip-flops, print Fizz and/or Buzz instead of the number when appropriate. But when is the “appropriate” time to print Fizz or Buzz? And how does a flip-flop and only three temporary variables achieve that? Lets take a look at just the first use of the flip-flop, on line 3 of the original code.

The first thing to note is that the conditions of the flip-flop operator are actually assignment. This took me a long while to spot, and indeed is a common source of bugs. In this case though, it’s not a bug, its a feature.

The flip-flop operator is going to evaluate the “truthiness” of whatever expression is inside it, and remembering that the assignment operator in many languages returns a value, we can figure out what the flip-flop operator will do.

We know the initial value of a, b, and c is nil, so lets start there.

1
2
3
puts (!nil).inspect   # => true
puts (!true).inspect  # => false
puts (!false).inspect # => true

So each invocation of one “side” of the flip-flop will gracefully handle the initial nil value of the variables, and then swap them between true and false. The flip-flop operator consists of two identical expressions though, so what behavior will that produce?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = nil
(1..9).each do |n|
  puts "#{n} #{a.inspect}"
  "Fizz" unless (a = !a) .. (a = !a) # no output here, we just care about the changes to a
end
# =>
# 1 nil
# 2 false
# 3 true
# 4 false
# 5 false
# 6 true
# 7 false
# 8 false
# 9 true

So the flip-flop operator, with just a single state variable, is able to create a pattern that sets a to true every third time! This is exactly how often we want to print “Fizz”!

How does this happen? If the only operation used is negating a boolean, the boolean will return to its original value after an even number of operations. So how are an even number (maybe 2, 4 or 6) of operations squeezed into three runs of a loop? Lets investigate the value of a after each condition of the flip-flop, rather than once per loop. We’ll use two simple functions to print within the conditions of the flip-flop:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# given a value, print its negation, then return its negation
def print_negate1(value)
  puts "a #{(!value).inspect}"
  !value
end

#same as above, but print b instead of a so we can tell
#which condition is being checked
def print_negate2(value)
  puts "b #{(!value).inspect}"
  !value
end

a = nil
(1..3).each do |n|
  puts "#{n}"
  "Fizz" unless (a = print_negate1(a)) .. (a = print_negate2(a))
end

# =>
# 1
# a true
# b false
# 2
# b true
# 3
# a false

As can be seen in the output, the flip-flop operator does indeed cause print_negate to be called 4 times in every 3 iterations. How? The first time through, the first flip-flop condition evaluates to true (nil negated is true), so the second condition is checked, and a is set to false (true negated is false).

The flip-flop is now “open”. It will only check the second condition now. In the second iteration of the loop, the flip-flop checks if should “close”. False negated is true, so the flip-flop does close. Finally, in the third iteration, the flip-flop checks only if it should open. True negated is false, so it stays closed, and the cycle repeats.

There’s one more complication: the flip-flop doesn’t return based on the value of a, but on its internal state. A flip-flop starts “closed”, meaning it will return false. Once the first condition evaluates to true, it is “open”, and will return true until the second conditional returns true, “closing” the flip-flop. So what is the state of the flip-flop after each of the 3 cycles above?

The first time, it starts closed, opens, and then does not close. Because of the unless, this does not print “Fizz”. The second time, it starts open, and closes, but still returns true, since “Fizz” is again not printed. Finally, the flip-flop fails to open at all in the third iteration, and thus returns false. This allows “Fizz” to be printed, exactly when needed.

So an interesting property of the flip-flop is that it returns true if it starts open, but then closes.

Buzz!

After dissecting the logic for printing “Fizz”, we can describe without even reading the code how “Buzz” will be printed: two variables will be used with some flip-flops to create a cycle that repeats every 5 iterations of the loop.

But that description leaves a lot of the details, and in fact there’s quite a bit more to be learned. Looking at line 4 in the original code, the first thing we notice is a new operator, or at least a variation: here there is a familiar flip-flop nested in the second conditional of what looks like another flip-flop operator at first glance. However its important to note this flip-flop consists of three dots (...) rather than the more familiar two (..). What’s the difference? Using our test code from above with this variant tells us:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = nil
(1..9).each do |n|
  puts "#{n} #{a.inspect}"
  "Fizz" unless (a = !a) ... (a = !a)
end
# =>
# 1 nil
# 2 true
# 3 false
# 4 true
# 5 false
# 6 true
# 7 false
# 8 true
# 9 false

This variant simply alternates between true and false, meaning it has an odd number of negations in every cycle. Theres not much Ruby documentation on the flip-flop operator, but the Perl documentation describes the difference:

If you don’t want it to test the right operand until the next evaluation, as in sed, just use
three dots (“…”) instead of two. In all other regards, “…” behaves just like “..” does.

The Ruby flip-flop behaves the same way, and therefore will only ever perform one negation per iteration of the loop. Another way to describe the difference: the first flip-flop variant will allow itself to open and close in the same invocation, whereas the second will not.

Instead of instrumenting all 3 conditionals in the two flip-flops for this part of the code, lets see if we can just reason about it, and describe how it works.

First, we recognise the inside of the second conditional: its the exact same pattern as in the “Fizz” line, but with the c variable. We therefore know that it will cycle through returning true, true, false. However, its output is negated, so the second conditional in the first flip-flop is going to cycle through false, false, and true. Lets work through a couple iterations of the loop and see where this goes.

The first time through, b and c are both nil, and both flip-flops are closed. The first flip-flop will evaluate b = !b to determine if it should open. That will set b to true and return true, so the first flip-flop is now open. This flip-flop variant doesn’t check if it should immediately close, so we’re done.

The second time through, the first flip-flop checks the second conditional to see if it should close. We don’t need to work through the logic of the second flip-flop, we know it will return false this time, and so the flip-flop stays open. Remember, the unless statement means we will only print “Buzz” when the flip-flop returns false(is closed)!

We also know the result of the third time through: the flip-flop is open, and again the second-flip flop will return false; the first flip-flop stays open, and nothing is printed.

The fourth time, the first flip-flop DOES close. However, remember that a flip-flop returns true when it transitions from open to closed, so once again we don’t print anything.

On the fifth iteration, the flip-flop starts closed, b is currently true. The first conditional of the flip-flop is evaluated, and the result is false! This means the flip-flop doesn’t open, returns false, and finally, “Buzz” is printed, exactly when we need it.

Fin

Wow, that was some serious thought for just a few lines of code. I’ve put all the example code on Github, feel free to fool around further.

Needless to say, while I enjoyed the exercise, like most of the Perl-isms in Ruby, I won’t be using flip-flops in production code any time soon.


  1. If anyone knows or is the author, let me know!
  2. Probably a gross simplification or outright lie. If anyone wants to suggest a more accurate explanation that is also concise, please do!

Three Git Commands You Should Never Use

| Comments

Ahh, Git. One of the most powerful tools of our time. Also, one of the most confusing. There’s no doubt that Git has a few rough edges.

Many complain that Git is too difficult to use, and that it’s easy to shoot yourself in the foot. I’d agree to an extent, but in my experience, Git also gives you the tools to fix any problems you cause.

In my mind the most dangerous commands in Git aren’t things like git rebase, because any mistakes you make with already committed data can be fixed (perhaps with a little help from git reflog).

Instead, the most dangerous commands in Git are those that prevent you from getting your data into Git correctly in the first place, those that make the Git history harder to read than it had to be, or those that behave unpredictably and hide too much information from the user.

These commands are quite popular, but I stand firm, you should never use any of them.

git commit -a

On the surface, git commit -a is just a timesaver, and who doesn’t like to save time? In principle, there’s nothing wrong with a command to commit everything at once. But in practice, I find that invariably when using git commit -a, something not meant to be committed will be committed. Big surprise. It might be a harmless console.log, or it could be massive temporary simplification of a critical bit of code.

I like to take a second before each commit and review exactly what is going in. I’ve set up a helpful git st alias that shows me a denser version of git status.

Usually, I’ll use one of my favorite little known Git features, git commit -p (git checkout, git stash, and many other commands also accept the -p flag), which will go through each section of changed code and ask whether or not you want to commit it. It comes with handy keyboard shortcuts meaning you can go through lots of code in only a few seconds, and if anything is there that shouldn’t be committed, you can skip right over it.

git commit -m

There are two reasons why I hate git commit -m.

First, it incentives short, unhelpful commit messages. On any size team (even a team of one), commit messages are one of the most useful ways to record knowledge from that critical time when code is actually written. git commit -m "fixed big" throws that opportunity right out the window. Please everyone take a second and write awesome commit messages. Did you know Git commit messages have a well established format that all editors will help you with, and allows writing as much of a description as you want? It wasn’t written for nothing.

Second, did you know that Git will sometimes write your commit message for you? It’s true! Whenever you perform a merge that isn’t simply a fast-forward, Git will generate a beautiful commit message automatically. It records which branch was merged into which right in the commit subject, and puts a list of any files that had conflicts in the body. Those are the most likely places where bugs might have sprung up, so the value of keeping track of them should be clear.

You get all this for free, unless you use git commit -m.

git pull

Of the three commands, this is probably the most used. As a result, the negative effects will be felt the strongest. And what bad thing happens with git pull? Nothing less than a permanently confusing history (gasp)! While it’s true that one can figure out what happened with even the most convoluted history, why would you inflict that upon your friends, colleagues, and coworkers if you don’t have to?

So how does it happen? It takes three steps:

  1. Work is done by you directly on the master branch (or whichever branch will be pulled from eventually).
  2. Someone else also works directly on the branch and pushes their changes first.
  3. git pull is run and a merge commit is generated for even trivial and completely independent changes.

Taken on its own, one extra merge commit is not a big deal. But if even two or three people are not working to prevent unneeded merge commits, things get nasty real fast.1

The dangers of git pull come partially from it’s bloated nature: it both fetches updates from others, and immediately and automatically decides how to reconcile those changes with yours. This should be two steps.

My workflow is to periodically run git fetch. This ONLY updates my remote branches, so I can see what work others have done. Usually, I’ll quickly inspect the changes that have been pushed using another great alias, git lg. Finally I decide what to do. Usually I simply want to make a linear history with my changes coming after the changes I just pulled. git rebase will accomplish this just fine, and then if it turns out the resulting conflict resolution is difficult, I can abort the rebase or start over and know exactly where thing stand.

On the other hand, even with git pull --rebase (which is a more sensible default than to merge), any conflict resolution is done immediately. There wasn’t a chance for you to figure out what sort of changes were just pulled in (are they huge refactorings that will change a lot and require careful analysis? Or were they simple changes that shouldn’t be a big deal), so resolving the conflicts is also hard. And what will the state of your working copy be after you abort the conflict resolution? Good question.

In summary

Everything that I believe makes for good Git usage comes from a few simple rules: understand what is happening under the hood, use source control as a great source of information, and play nice with others.

These are a few things that don’t work with those rules, next time I’ll cover some ways to follow them.


  1. For a great example of good and bad merge commits: check out this helpful Gist.

The FAA Made the Right Call on Plane Sharing

| Comments

About two years ago I had just received my private pilot’s license and was excited to share my love of aviation with my friends. My first few flights were never unsafe, but they had their share of moments that showed just how little one knows even after training with an excellent instructor.

I learned a lot from those first few flights, and I still learn something new with every flight. That should come as no surprise: pilots that have been flying for decades, and logged tens of thousands of hours in all types of aircraft say the same. I made a few passengers nervous early on1, but over time I’ve improve not just my flying but my ability to make my passengers feel calm and safe. I’ve had one friend say she overcame her fear of flying commercial just from flying with me once!

As it happens, the FAA allows me to share the costs of flying with my friends, but only under a very narrow set of circumstances. Anything beyond that, and I’m required to at least have a commercial pilot’s license, and possibly comply with even more regulations. This make sense for ensuring the safety we expect of airlines, but would be impossible for pilots flying on their own to afford. I have to say that this allows me far more opportunity to share my love of aviation with my friends than would otherwise be possible, and my flying has improved in the process.

Of course, after the success of companies like Uber and Lyft, it should come as no surprise that someone would try to adapt the ride-sharing model to general aviation. In fact, at least two such companies have appeared: Flytenow and Airpooler. Both companies offered an interpretation of FAA regulations that allow their users to share the costs of travel with their passengers under the same exception that allows me to share expenses with my friends when I fly.

And to their credit, both companies were proactive and reached out to the FAA hoping for clarification and a blessing.

Pilots have been trying to cleverly skirt around these regulations forever (“okay, you fly me to New York for free, but then I’ll buy that pen off you for $500”) and the FAA has always stated clearly that there are no loopholes2. So when those of us in aviation who also follow the happenings of tech companies heard about Flytenow and Airpooler, many of us were hesitant to try it out. We all know the regulations (our flight instructors no doubt drilled it into our heads during our training), and there’s no mistake that our license in on the line.

It didn’t come as a surprise to many pilots when the FAA issued their ruling last week: flight-sharing websites violate FAA regulations.

But, of course, governing bodies have come out and ruled against many tech companies. And in those cases many hold the opinion that the laws are wrong, the government is corrupt, and the tech companies are helping everyone by offering a little competition to a stagnant industry. So the same logic should be applied here, and we should all lobby the FAA to allow plane-sharing, right?

Well, not so fast. It’s worth taking a minute and examining if the situation really is the same here.

What good are the regulations anyway?

I’ve always felt that many laws and regulations do more harm than good. Part of the popularity of companies like Uber, and Lyft comes not just from their product itself but from excitement about giving slow-moving monopolies or oligopolies like the taxi companies some much needed competition.

I admit myself I find it interesting that I’m taking this side. But what I’ve also found interesting is that after hours of reading FAA regulations both during and after my private pilot training, I’ve found them to be extremely sensible, if a bit complicated.

It wasn’t always the case, but flying today is incredibly safe. Through decades of work, aviation experts have analyzed every aspect of flying, from everyday occurrences to the most unusual of incidents3. While the taxi industry lobbied to create things like the medallion system and car accidents grew to one of the leading causes of death in the United States, aviation has become dramatically safer over time: the 2010 fatality rate in general aviation is half that what it was in 1970.

Why? As the saying goes: flying is not inherently dangerous, but it is unforgiving. Unlike other industries, where lobbying and public opinion have overridden careful analysis, with aviation the stakes are high, and the consequences of even a minor oversight dire. Things that don’t work have a much harder time sticking.

That’s not to say all in aviation is perfect, but more than any other part of the government I can think of, the aviation industry uses real data and real science to make decisions.

A Question of Scale

Many argued that there is no difference between asking a few friends if they want to go on a weekend flying trip, posting a paper ad on the bulletin board of your local airport offering to share flight expenses, and using the internet, perhaps with a flight-sharing app, to extend the same offer to thousands of people. In some senses, this is true.

However, the key difference, and why the FAA allows a pilot to ask a few friends if they want to go flying, will probably let pilots get away with posting at their airport but might investigate if things get fishy, and flat out refuse to allow dedicated, high traffic flight-sharing apps or websites, is simple: scale.

A well-connected pilot asking many of his or her friends and acquaintances to fly could probably set up a trip almost every weekend. At a busy airport, a note on a bulletin board might allow for a flight both days of every weekend. But imagine a pilot in a big city being able to advertise to a couple hundred thousand people or more. It would be easy to schedule multiple flights every day. There’d always be someone willing to go.

The FAA allows pilots to share expenses as an exception to the otherwise simple rule that a private pilot can’t be in it for the money. This exception is feasible only because it’s expected to apply to a relatively small number of flights. Flight-sharing companies inherently work directly against keeping this exceptional case limited.

Not every industry needs to be disrupted

After the FAA’s ruling, many in tech were concerned. Flytenow quickly replied to the FAA with what I felt was a disappointing analysis of the FAA’s position, and vowed to continue their service with the cost sharing aspect removed. AirPooler reportedly may attempt to reverse the ruling.

I have no doubt everyone involved in both of these companies share a strong love of aviation, and are genuinely trying to make things better for pilots and passengers. I also know how hard it is to build a company from nothing, especially one that skirts the edge of existing laws. And I know that the founder mindset is specifically geared towards conquering obstacles, of which this may just appear as the biggest yet.

With all that in mind, I have a request for the founders of Flytenow and Airpooler: please don’t continue to pursue the current flight-sharing model.

The idea is admirable, and there was no wrong done in testing it out. But the division between a private and commercial license has stood fairly clearly for a long time, and in general it has worked out. Blurring the lines between flying with friends and flying with paying customers will inevitably cause issues.

General aviation currently faces opposition on many fronts. Even aside from what will happen in the case of an accident, there are bound to be cases where the expectations of paying passengers don’t match up with the experience a low-time private pilot like myself can provide. The fallout from these events will be trying for our entire community.

We still need the help of tech companies

The last thing I’m suggesting is that Flytenow or Airpooler close up shop, go home, and call it a day. Now more than ever general aviation needs the help of those of us who have the skills and desire to bring technology to our industry. Everyone among us who can start companies, launch products, and solve problems is extremely valuable.

I couldn’t even begin to list all the ways to improve aviation right now. Just look at the advances in mobile hardware, batteries, sensors of all kinds, and machine learning that are revolutionizing entire industries. And in aviation we have plenty of innovators to inspire us:

  • The Foreflight team has arguably made an iPad required equipment and made flight planning easier than ever
  • OpenAirplane is making renting planes across the country as easy as renting at your local airport
  • PilotEdge has created an amazing network of flight simulator enthusiasts and is helping real pilots practice their skills safely from their own computers
  • Even individuals are contributing: developers like Jacob Eiting are making awesome aviation apps, and video series like those from FlightChops are helping more people learn about aviation, and aviation safety, than ever before

Again, I’m not suggesting we halt progress on technology in aviation. In fact I know we’re going to continue going forward. But disruption isn’t the only way to improve. We’ve got some great organizations here in general aviation: we can all make flying more fun, more popular, and safer with cooperation.


  1. When you mean to ensure your passengers that despite the somewhat ragged appearance a 1970’s Cessna may have, the engine and components are maintained to the same high level of quality as a new plane, one thing you should never say is: “Yeah, they don’t really take care of these old planes”.
  2. The FAA has ruled definitively on all sorts of schemes: you can’t use your private pilots license to aid your business, even simply flying employees to meetings. You can’t act on a hint from your boss that a ride in your plane will convince him to give you a promotion. You can’t offer your mechanic a free flight to get a reduced rates on your next annual inspection. You can’t even fly your drama teacher in exchange for a more prominent part in the school play.
  3. Perhaps my favorite story is that of United Airlines Flight 232. One of the plane’s engines failed catastrophically requiring an emergency landing. Investigators recovered the critical piece of the engine they needed to analyze the failure, even though they had to search hundreds of square miles of Iowa farmland around where the accident occurred to do it. It was analyzed and despite being damaged from falling several miles, the analysis detected a crack caused by fatigue that lead to the accident. The team then investigated the maintenance and production logs for the airplane going back 18 years, and determined the part was manufactured with the defect, the defect was detected, but the part was not rejected as it should have been. This is the lengths we have to go to if we want to ensure flying is safe.

Javascript: The Good Parts, a Review

| Comments

Today I wrote up what turned out to be a somewhat lengthy review for Javascript: The Good Parts. Since it goes a bit beyond strictly reviewing the book and talking about Javascript itself, I figured I’d post it here.

I though I had read this book before, but when I sat down to reread it this weekend I found a couple interesting things: 1.) I had never reviewed/rated this book on Goodreads, 2.) I had a bookmark halfway through the book 3.) I didn’t remember any of the content for most of the chapters after my bookmark.

So here goes..

Javascript: The Good Parts made (or at least helped make) the Javascript language. Yes, the book was published in 2008, and yes, Javascript was created in 1995, and yes Javascript was widely used by at least the year 2000. But before The Good Parts, no one was allowed to view Javascript as anything but a toy. Worse, a toy with many sharp pieces that would hurt you if you tried to use it.

The Good Parts is still hard on Javascript, both in the main chapters of the book and in two special appendices cataloguing the Awful Parts and the Bad Parts, and there’s plenty of good reasons to be hard on Javascript.

Part of this comes from Crockford’s personality. While I find him likeable overall he is sometimes a bit abrasive and critical. In one of his talks, he mentions he considers colored syntax highlighting to be a feature “for children”. Beyond making more than a few skilled developers angry, I’m sure comments like these do their share to keep new people out of our field. The “REAL programmers don’t use X” rhetoric is strong enough without people wondering if finding value in syntax highlighting means they aren’t cut out for programming.

I also notice a disconnect between Crockford’s suggested pattern of Javascript usage, and that which is actually common today. Crockford was adamant that the “new” keyword never be used. He suggests we abandon what he called the “pseudoclassical” inheritance features that somewhat resemble C++ or Java, and embrace the prototypal inheritance that he considers to be the core of the Javascript language. At least in the world of Backbone.js, which is the most widely used framework I know of that isn’t trying to rebuild Rails on top of Javascript, but rather work with the language, things have settled on a strange combination where prototypal inheritance handles defining objects that look eerily similar to traditional classes, and then the dreaded “new” keyword is used to intansiate individual objects.

Finally, I can not believe that Crockford isn’t suffering at least a little from a case of Stockholm syndrome. I know this because I’ve been writing Javascript for over 10 years, and have seen my own admiration for the language grow even while I questioned whether or not my admiration was valid.

There IS an elegance in the Javascript language that this book helps unearth, but whether or not that elegant system actually makes Javascript useful is more uncertain. I see the beauty in using closures to hide access to private variables, but is it worth the cognitive load over simply declaring something private?

In any case this book is a must read for anyone doing Javascript development. I don’t think this book has achieved the top status of “must reread every year”, but it seems reasonable that you should read this book twice: once after you first dive into Javascript and want some semblance of clarity after the initial confusion you will no doubt encounter, and then sometime later when you are experienced with Javascript and wish to achieve Zen with the language.

Thank you RailsConf!

| Comments

I’m finally back home and settled in from a crazy and amazing week in Chicago. I just wanted to say thanks to everyone for an amazing time. Speakers, attendees, staff, everyone.

To everyone I met or talked to during the week, it was great to see you.

Speakers! You guys gave some amazing talks and it was awesome to watch you give them and get to chat with you about them later.

And last but not least, to everyone who attended my talk: thanks so much! I hope you had as much fun listening as I did giving it. The slides are here and you can see the video of my talk from MWRC on youtube.

See you all at the next conference!