Why I Stopped Using ES6

Written by J David Smith
Published on 18 July 2015

Pushing ClojureScript or Elm didn't seem like a great way to spend my time, so I instead chose to toy with another relatively new bit of technology: EcmaScript 6. This page has a great overview of the new features coming to JavaScript with ES6, but most of them haven't actually made it in yet. I used the Babel transpiler to compile the code down from ES6 to ES5.

I was initially going to title this post "Why I Stopped Using Babel", but that would make it sound like there was some problem with Babel. I have had no issues whatsoever with Babel. The transpilation time was almost negligible (~1s for my code, combined with ~4s of browserify run time), it didn't perceivably impact performance (even when I was profiling inner loops written in ES6), and it never caused any bugs. On the whole, Babel is excellent software and if you want to use ES6 now, I highly recommend it. But there's the catch: you have to want to use ES6 now. And slowly, over the course of a couple of months, my desire to do so was sapped away (through no fault of Babel, and almost no fault of ES6).

The problems I had were mostly with integration. Two very important pieces of my workflow are Tern and Istanbul. Tern provides auto completion and type-guessing that is integrated into Emacs. Istanbul provides code coverage reports. Neither of them support ES6. With Istanbul, it was possible to work around it by running babel on my code and then covering the ES5 output. However, the coverage reports were then off because of the extra code that babel has to insert in order to properly simulate ES6 in ES5. Tern, on the other hand, did not have an option. If I chose to use only fat arrows, it would be workable because I discovered I could copy and past the code for normal functions to those and it worked more or less as expected. However, everything else was a wash.

So why not ditch Tern and put up with the Istanbul workaround until it gets ES6 support? As I used ES6 over the summer, I came to realize that in 99% of my usage, it wasn't much of an improvement. let is certainly useful (and the way it always should have been), arrow functions are awesome, and for(a of as) finally gives a sane looping construct in the language. Other than that, the only feature that's really exciting is destructuring, and while it is a bit of a pain to destructure complex data by hand, it isn't something that I have to do often. Classes were not of any use to me for this project either. None of my data made sense to represent as a class. Although in theory my React components would make sense as classes, I'd rather use the old, well-documented, clear method that has support for mixins (which would have to be implemented through inheritance were I to use ES6 classes).

The decision ultimately came down to three things:

  1. I wasn't getting much (just let, for of, fat arrows, and destructuring) from ES6
  2. ES6 vs ES5 is just one more thing my team would have to pick up after I'm gone.
  3. ES6→ES5 transpilation is a thing that somebody would have to support after I'm gone, and there is no telling how long it will be before it is no longer needed.

In the interest of making the life of my successor a tiny bit easier to manage, I ultimately chose to ditch ES6 for ye olde ES5. I had to throw out a bunch of the ES6 prototype code anyway, so there was very little additional cost in stripping it out of the code. Ultimately, I believe that this was the right decision for this project. Although losing those few additional features I was using was a bit painful, gaining the proper support of my tools and losing the incidental complexity of transpilation was worth it I think.

I'll probably still use ES6 with Babel for small side projects. (Anything large won't be in JS, even if it compiles to it!) If you want to try out ES6, Babel is a very safe and easy way to do it. I look forward to the day that ES6 has widespread support and Babel is…well, still needed for ES7 transpilation, but that's for another day.


I don't like the import syntax and don't even get me started on classes and inheritance in ES6.

Change Can Happen

Written by J David Smith
Published on 27 June 2015

First, on June 17th, Dylann Roof killed 9 people in a racially motivated attack on a black church in Charleston, South Carolina. He apparently intended to start a race war, but that didn't happen. Instead, we saw people unite to against a symbol of racial hatred: the Confederate flag. Today – ten days later – [Brittany "Bree" Newsome climbed the flag pole at the South Carolina capitol](http://www.cnn.com/2015/06/27/politics/south-carolina-confederate-flag/) and did what the South Carolinian politicians would not: took down the flag. It went back up soon after, but the internet exploded in support of her action. And one must not forget [President Obama's incredible eulogy for those lost in the massacre.](https://www.youtube.com/watch?v%3DRK7tYOVd0Hs)

That was not the only significant event in recent days, though. Yesterday, on the 26th of June, 2015, [SCOTUS ruled that bans on gay marriage were unconstitutional.](http://www.vox.com/2015/6/26/8823655/gay-marriage-legal-scotus-obergefell-v-hodges) This was followed by much hate from the Republican end of the US political spectrum. [Some states are even considering not issuing any marriage licenses.](http://www.newsweek.com/following-supreme-court-decision-mississippi-may-stop-issuing-any-marriage-347740) Justice Scalia issued an opinion on the decision (pdf link) that alternated between being entertaining, baffling, and scary. However, the general public seemed to react very positively to the news.

Yet another major event is the [Supreme Court's 6-3 decision in favor of the Affordable Care Act.](http://www.cnn.com/2015/06/25/politics/supreme-court-ruling-obamacare/) I heard much less about this one. It was overshadowed by other events and, honestly, I'm not even sure what it means anymore. So much of the ACA has been marred by general misunderstanding and intentional disinformation by parties with axes to grind that I don't understand the full implications of the ruling. That will change over the next few days, as I intend to catch up on it.

All of these things have potential to be major historical events in their own right. We will have to wait and see the aftermath to be sure, but there are some very important lessons that we need to take from this (in my opinion).

Change Happens – Slowly but Surely

Too often it seems that I hear people depressingly discussing the sad state of affair in our world. Nothing seems to change. We push and pull and nothing moves. But then, how long have people been fighting for gay rights? The first documented demonstration was in Berlin in 1922 (citing Wikipedia because the primary source is a book and I can't link to that). That pins the SCOTUS decision at 93 years after the first demonstration. What's more: gay marriage is still illegal in Germany. Americans have been fighting over racial inequality since at least the Civil War in 1861 (154 years ago), and we still haven't finished dealing with it. The smallest of the three issues (universal, affordable healthcare) has been debated endlessly [since at least 1912](https://en.wikipedia.org/wiki/HistoryofhealthcarereformintheUnitedStates#1900s-1920s) (103 years), when it was an issue in Theodore Roosevelt's presidential campaign.

These issues are far from resolved, but all have been a part of political discussion for at nearly a century – yet we still today are seeing change in these issues. It is important to keep this in mind as we push towards a better future: change is often slow, but it does occur. (Note: I am not saying that change is always slow or necessarily slow. I am merely trying to point out that even when change is not obvious, in the end our efforts can pay off)

Change Takes Work

This ties in closely with the previous point. The modern LGBT rights movement in the United States can be traced back to the Stonewall Riots in 1969 (yet another wiki link, too many sources – not enough internet sources). The movement has been active and relentless for more than 40 years! Again: the war isn't won yet, but an important battle has been. 40+ years of work led to this change, and that same dedication will lead to future change.

The Work Is Not Done

The Charleston Massacre shows just how far we are from having solved racism and racial inequality. Significant effort has been expended in dealing with these problems, and much more remains to be done. This horrific event serves as a reminder that even after significant victories (like the dismantling of Jim Crow laws, or the electing of a black president), we can't continue to be or become complacent.

(I am not saying that others have been, but rather that I have been. The last few months have been enlightening for me as I've seen how much change still needs to happen.)

Next Steps

One may ask how to get involved. Unfortunately, I am not the best one to answer that question. For all my words, I have been largely a bystander. A "social media activist". I have tweeted, retweeted, faved, liked, and even donated some small amounts. However, I've not done much.

Better people to ask would be those on the front lines. Shaun King has done a tremendous job of bringing awareness to racial equality issues (especially those to do with police brutality). Wikipedia has a long list of [LGBT rights organizations in the United States](https://en.wikipedia.org/wiki/ListofLGBTrightsorganizationsintheUnitedStates) (and other countries).

I feel weird and a bit hypocritical having done nothing and yet writing this post, but in some way this is a call for myself more than anyone else. The SCOTUS ruling(s) show us not only that change can happen, but that change does happen. The Charleston Massacre has the dual nature of showing how much hatred remains and showing how we can move forward from tragedy towards a better future. This is my moment of realization that my attitude of depressing complacence accomplishes nothing, and that by action I may help move our society to a better place.

Anarchy Online: Why?

Written by J David Smith
Published on 23 May 2015


I started playing AO a bit more than a decade ago, right when they began allowing players to play for free. Free players (colloquially known as 'froobs') have access only to the base game and the Notum Wars boosters, not any of the (4 at present) expansion packs. I played on and off as a froob for much of that period, never reaching higher than level 80 (of 200).

So why do I keep coming back? More than that: why the hell did I pick up the full expansion set this last time around? It was only $20, but still: Why? I am beginning to understand, I think. The game is one giant puzzle.

I was playing my new Fixer, running around in the Shadowlands, trying to figure out where to go next to keep leveling. I googled it, found some info, and set about trying to act on it. And failed over and over again. Dangerous enemies were between me and my goal. As of writing this, I have yet to figure out a way to slip past them.

It isn't that these enemies are over-leveled for me either: they are on level, and I can fight one and sometimes even two at a time without dying. However, every entry point seems to set me against situations where I fight minimum two and often three of these creatures.

There are many possible ways I could deal with this. Maybe I need to temporarily blow some IP (for the uninitiated: IP increase skills) in Concealment and sneak past them. Maybe I need to go hunt for better nanos and the requisite buffs to equip and cast them. Maybe I need a better gun (or two). I don't know.

As someone who loves puzzles and is absolutely unconcerned with reaching the level cap in a timely manner, I enjoy this. The struggle just to succeed. I have fond memories of pugging ToTW on my Agent (Emallson – my namesake), pushing all the way to the legionnaires for efficient XP or the final boss encounter for the wonderful loot (though I can't remember these days what he drops). Getting there as a solo player without any consistent help was hard. For about a month I was stuck on level 41, continuously dying before dinging and feeding the XP into my bonus pool (Aside: dying loses XP, which goes into a bonus pool that gives you 1.5x XP until you've regained all of it. I really like this system).

Again: it was a puzzle. How do I survive? What can I change? Where do I go? Who do I work with? It was fun. It is fun. This is why I still play this ugly, unwieldy game. Come to think: its unwieldiness actually feeds into that. It gives you most of the information you could reasonably ask for, but it's scattered around. Figuring out which nanos I can buff into reasonably requires finding not only what nanos I can get (in the shop) but also what buffs I can get cast on me (by an MP most often), what weapons I can pull from missions without spending too much on the search is something that doesn't have a good answer because of the QL system, etc.

There are a lot of things that I like about this game. There are enough of them that I feel I can look past the ugliness and unwieldiness to enjoy it. It's fun to explore this world. And that's what I want from a game: fun.

Good-Better Decision Making

Written by J David Smith
Published on 7 March 2015

This also happens to be pretty relevant to my current life status (grad school decision, hurray!), so I'm going to write about it.

Fair warning: this is amateur philosophy and psychology. If you have an allergy to that stuff, ye might best skip to the 5 section.

In the Beginning, there were Games

If one were to ask me to trace my exposure to ideas back to the earliest source I can remember, I would more often than not stop around the time I became active in the MMO community at large (beginning primarily in *Anarchy Online and Shadowbane*). Optimality is one of the most central tenets of online gaming culture.

MMO communities (and probably communities in general, but I'm trying to speak from experience) have a tendency to focus on playing their games of choice in the 'optimal' fashion according to some metric. This may manifest as maximization of XP rates during leveling, attempting to optimally pack daily quests for reputation gain rates, or setting up elaborate macro systems to ensure complete buff coverage (looking at you, Shadowbane). The pervasiveness of this focus on optimality had a significant impact on my view of the subject. Around my junior year of high school, I reached the point that I began to outright reject the pursuit of optimality.

That was about six years ago. A lot has changed since then, but I feel even more confident now that the pursuit of the 'best choice' is often not worthwhile. I'm going to attempt to outline my reasons for this, and then cover some ideas that I've found as beneficial substitutes for optimum-focus.

The State-Space Exploration Problem

The first and most significant problem with pursuing the best decisions, the best actions, the best techniques, the best X is not with convincing oneself to take the best action, but simply determining what the best action is! The mental model I hold as an explanation for this is derived from experience with optimality problems in mathematics and computer science.

The two primary reasons that choosing the best X is hard, in my view, are:

From Wikipedia: "A heuristic technique, sometimes called simply a heuristic, is any approach to problem solving, learning, or discovery that employs a practical methodology not guaranteed to be optimal or perfect, but sufficient for the immediate goals." In this case, by "comparison heuristics" I mean techniques for comparing choices and their outcomes. We use these all the time without even thinking.

Consider a small example: you are having a conversation with a friend. They make a statement. What is the best response? How does one approach determining what the best response is? Well, first we need to have some way of saying response A is better than response B. Then, we need a way to navigate the space of all possible responses in order to find the best choice.

But given an arbitrary statement, how many possible responses are there? Even if we think only about verbal responses (ignoring all non-verbal things like view intensity, line of sight, posture, etc), there are an incredible number of options to choose from!

Suppose they say "I don't feel prepared for my Calculus exam tomorrow." Do you respond humorously in order to help them relax or seriously to help keep them focused? Do you offer to help them prepare for it or maybe refer them to someone else who could? Suppose you respond humorously. Do you use sarcasm? Tell a funny (to you) story? Use a comically bad metaphor? I already feel overwhelmed with the number of responses, and we aren't even at the point of choosing words yet!

Then there's the question of comparison. Even assuming we can reasonably explore the state space, how does one compare a light-hearted response with a serious offer of help? Which is the best choice? It seems to me that it depends a lot on the situation that you're in and who you are talking with (which has the implication that maybe learning uniformly best responses is also impractical).

The choice of heuristic comparisons and possible responses is simply overwhelming, and this is only for a very simple, everyday interaction! What about life-altering decisions like what graduate school to attend or what topic to choose for your dissertation? The consequences are potentially enormous. How does one choose the best decision?

This overwhelming feeling is one that I associate strongly with feelings of indecisiveness. Being unable to quickly make decisions is something I'd like to avoid. Inability to reach decisions is something that is easy to notice in others, yet the common advice of 'just pick something' – while practical for deciding what kind of burrito to get – simply isn't something I'm comfortable with for any sort of significant decision.

Degenerate Behavior

Indecisiveness is something that I'd call a degenerate behavior. The behavior is not something that I want in myself, but is not far from behavior that I do want (thoughtfulness: thinking before acting). In some sense, it has degenerated from desirable into undesirable. Why does this happen? How can we prevent it?

One reason that indecisiveness can strike is a heuristic that just takes a long time to evaluate. If your method is trying to find the best option among hundreds of millions of options, it follows that it might take awhile. Great! We're done, right? Problem solved?

Not quite. People are really good at doing these sorts of searches. Every moment of every day, we make decisions about how to move, how to think, how to speak. Each of these involves an efficient search of a space of possible motions/thoughts/sayings. Take motion as an example. When walking down stairs, I see the stairs and make a decision on how to place my limbs. If I make a poor choice, I could twist an ankle or fall down them.

So is the problem that these searches are actually slow, or is there more to it? My experience in online-gaming communities leads me to believe that it is often not a slow search that causes indecisiveness, but rather conflicting heuristics that cause it!

Suppose you're playing World of Warcraft. (If you've never played, just pretend. My point isn't dependent on this one example.) You're leveling a new character. What is the best way to do this? There are several different schools of thought on this very straightforward-seeming question. Some insist that the best way to level a character is to blitz through dungeons from 15 - 85 and then race through quests for the remaining levels. Others take a more balanced stance by proposing to maximize experience gain without significantly dampening your enjoyment of the game. Still others consider experience gain to be a very low priority in the leveling process (I myself fall in this camp).

What we see here are three different – but still valid – comparison methods. Which one should I use? The community as a whole pushed the 'zomg XP' heuristic for a long time as the metric. It is still very much dominant, but others are seeing more discussion (in my experience). I began using that heuristic because it was well established and very common.

However, over time I discovered that I didn't really enjoy this. I entered a transitional period, in which I was constantly debating whether to go for the XP or just enjoy myself. In the end, I fell into the latter method and am happier for it. This is not to say that everyone should do the same! One of my good friends (you know who you are (Rodger)) applies the XP-maximizing method and enjoys playing WoW more than I. My point is twofold: our environment can shape our methods of decision-making, and conflicting heuristics can cause indecision.

We can observe similar situations of borrowed heuristics in everyday life. I learned to be conservative with food spending from my mother, but learned the joys of good lunches hanging out with friends at my (well-paying) internship last summer. These two desires regularly come into conflict. How can I resolve this conflict? Everything has come down to the problem of deciding between heuristics. I propose a simple solution: change the problem statement.

Rephrasing the Problem

We began this adventure by thinking about the problem of finding the best choice. What if we don't? Let's instead think about determining if a choice is merely good. Then we might also be able to decide if another choice is better and – more importantly – why.

Going back to the food example:

While there is a core algorithmic difference between the two (determining best requires considering all options, but deciding good doesn't), I consider the key difference between this approach (henceforth good-better) and the best-first approach to be awareness. With the best-first approach, I have the tendency to let my brain run until it gives me an answer I am satisfied enough with to take action on. I tend to be dissatisfied with this choice because it isn't the one I was looking for.

With the good-better approach, I am actively aware of what options I'm evaluating. When I reach a time that I have to act, I can simply do so with my currently optimal choice. I almost always feel better about the result because I know my choice is good, although better choices probably exist.

Further Reading

I am certainly not the first person to think about this. Although I have not read any of these papers, the citations of the Wikipedia page Satisficing appear very closely related. The whole page is a good read. Really, I could have probably just linked that page and been done with it, but where's the fun in that?

In Conclusion

This is the approach that I've been using for the better part of the past year, and have only just now formulated it concretely enough to write about. I know that it is based wholly on my own experience, and I'm okay with that. My objective was not to somehow prove that my way was better, but merely to describe it.

I have noticed a marked improvement in my general mood following decisions after starting to use this approach. I have also noticed that I act differently when alone doing things. When playing WoW I do all the same things as before, but focus on doing good things rather than the best things. I enjoy it more as a result.

This approach is also informing my decision on which graduate school to attend / whether to jump into the industry for a while. I still often get stuck thinking about what the best option would be, but when I regain control of my thoughts and focus on good-better I tend to relax significantly. It's comforting to think about deciding whether one good choice is better than another, rather than thinking about why my options aren't the best they could be.

I've broached this subject to a few different people, and the responses seemed generally positive. My decision-making process is constantly evolving, but this change made a noticeable improvement in my life. Here's hoping that it might improve others' lives too.

P.S. Leave comments.


1 One might ask: why heuristics? How do I know what my decision processes actually are? It is simple: always ask why. In my case, the answer is usually that I've observed or received a positive outcome from making certain kinds of decisions. I encourage you to think about your own decision making processes and draw your own conclusions.

2 That's an understatement if there ever was one.

3 Note that this is not dissimilar to the phrasing of reinforcement learning.

2014 in Review

Written by J David Smith
Published on 12 January 2015

Interning at IBM

When I applied for internships in December of 2013, I wasn't sure what would happen. I applied to big names – Google, Microsoft, IBM, and others as I did the year prior. In 2012-2013, I got no responses. In 2013-2014, I got many. My applications to both Google and IBM were accepted, Riot Games asked for an interview (which I unfortunately had to decline because I'd already accepted IBM's offer), and Microsoft ignored my existence (maybe because my resumé is slathered in Linux tooling and has not a whiff of Microsoft on it).

I struggled for weeks with the decision between Google and IBM. Working at Google is a dream job, but there was a catch: the project I would be working on there was boring. Meanwhile, the project I was offered at IBM was really cool and exciting. At the time, it involved significant open-source contributions. Although it changed later, the change helped refine the project goals and clarify what my team would be doing.

In the end, I chose IBM. I was both looking forward to and dreading starting there at the end of May. What if I had chosen incorrectly? Once we got started, however, all my doubt vanished. The project turned out to be just as exciting as it had sounded. Even better: I had the pleasure of working with a phenomenal group of people. On the IBM side, we had a fantastic manager ([Ross Grady](https://twitter.com/rossgrady)) and great support from the group we were working with.

On the intern side, things couldn't have been better. My team was phenomenal: John and Walker were (and are) great technically, and all four of us (me, John, Walker, and Chris) worked together without even a hint of an issue throughout the Summer. What's more, I was surprised at how welcome I felt in the intern group. I've never been very comfortable socially, and yet by the end of the Summer there is but one that I'd not call a friend.

The biggest benefit of the internship for me was not the technical knowledge I gained, the skills I developed, money I made. It was the opportunity to work with these people. Prior to this, I had never had the chance to work with other programmers. I'd worked in a research lab, but that is a very different focus. Seeing how capable my fellow interns were and realizing that I was actually capable of keeping up with them was a tremendous confidence boost for me.

I have no regrets about my decision to work at IBM this past Summer. I came out of it knowing more, having more friends and contacts, and with several offers for positions at IBM. I ended up declining all of them to pursue a PhD, but set up an internship with one of the security software teams for Summer 2015.

The Interview

In the middle of the Summer, I got a wholly unexpected phone call: a Google recruiter contacted me about interviewing for a full-time position. At the time, my plans for the future were undecided but leaning heavily towards the pursuit of a PhD. I told him that I would be willing to talk more after the Summer ended, when I had more time.

When I followed up with him in August/September, things moved rapidly. I was able to skip the phone interviews because I'd done well enough on the ones for the internship to receive an offer. I got to fly to California and do interview in person! Working full-time at Google requires passing a high bar, so being interviewed indicates that I may be close to it.

In the end, I did not receive an offer. However, I was thrilled at the thought that I might be capable of reaching and surpassing the skill level needed for entry. This also forced me to mentally work out how to deal with serious rejection. I have been generally successful throughout my life, and hadn't had any rejection on this level before. I am glad that it came at a time when I had the opportunity to stop and think about it, rather than a super-busy season.

The Fulbright Program

I also began working on an application to the Fulbright U.S. Student Program in the summer. This program – if I were accepted – would let me study at a school almost anywhere in the world. The program grant covers one year, but I will be able to build a case for financial aid and visa for continuing on should I desire.

The application for this is for the most part not too bad. However, the two essays that go along with it (Personal Statement & Statement of Purpose) were especially difficult. I had never written anything like them before and was ill-prepared to do so. The advisor at UK was incredibly helpful in this, and I believe that I ended up with a competitive application. Regardless, I spent a solid month and a half thinking about nothing else. This prepared me well to write the statements for grad school applications, but was a significant time sink.

The worst part about this application is that I won't know the result until March of this year, while the deadline was September of last year. The long waiting period is killer, and is a problem I am facing in other areas as well.

Graduate School Applications

This is where I made my biggest mistake of the year: I did not work on grad school applications on Thanksgiving break. I took the week off: I slept, I played video games, I wrote code. I did not apply to grad school. Because of this, I was ill-prepared to meet the popular 15 December deadline. I was more prepared to meet the 1 January deadline that others have, but between the insanity of finals week (15-20 Dec.) and Christmas, ended up being largely tardy with that as well. (Also, far fewer schools have the later deadline)

I learned in 2012/2013 not to wait so long. I made a point of doing internship applications in '13 on Thanksgiving break so as to not miss deadlines. I learned the lesson, and then in arrogance forgot it. I applied to four schools: MIT, Texas A&M, UFlorida and UKansas. I have already been accepted into UKansas (0.0), but we'll see what happens.

I probably won't hear back from the other three schools until mid-March. I will have little enough time to make a decision, and will have to start planning for the Fall immediately. What really gets me is simply the waiting period. I do not know what will happen. I cannot realistically make any plans for or assumptions about after the summer until March. It sucks. I don't like it.

Goals for 2014

I didn't really set goals for 2014. One that I stumbled upon through meditation on Tom Shear's (Assemblage 23) Otherness. This is a long-term goal: be a better person. I started trying to write down a concrete list of this while writing this blog post, but I will need to think about it more. I realize how incredibly wishy-washy 'be a better person' is, and need to nail it down so I know what I'm going for. Details will be a blog post sometime in the next week.

Looking Forward: Goals for 2015

I am not a fan of New Years resolutions, and thus have none. However, over the course of last semester I became of several deficiencies in my overall behavior. In particular: my aversion to lists and my inconsistency.

Lists are helpful tools, yet I often do not use them. I saw how my dad became dependent on his lists to remember things and suppose I overreacted. I started keeping lists of assignments and due dates during this semester, and it helped reduce the number of times that I missed an assignment due to forgetfulness.

This is one method of moving towards my present goal: becoming more consistent. Self-discipline is not one of my strong points, but I have been working on improving. The impact of this will be better control over what I buy, what I eat, and how I spend my time. It meshes well with my goal of 'be a better person' (lol), as control will allow me to be who I want to be.

I have a long way to go.

Un-Bonus Tracks

Written by J David Smith
Published on 19 December 2014

Since this task is most easily done with mpc (which has a searchable list of my collection) and metaflac (a command line flac metadata editor), I turned to shell scripting. The full script to accomplish this was pretty trivial:

suffix=" (Bonus Tracks Version)";
for songpath in $(mpc search album "$suffix"); do
    echo $songpath;
    tag=`metaflac --show-tag=ALBUM "$root$songpath"`;
    metaflac --remove-tag=ALBUM "$root$songpath";
    metaflac --set-tag="ALBUM=${${${(C)tag#ALBUM=}%$suffix}/The /the }" \

This few lines of code let me fix the six or seven albums that I'd been putting off fixing for months. The heart of it is in the nested substitutions being performed in the metaflac –set-tag command. It looks pretty insane, but actually is quite simple.

It breaks down into 4 separate transformations (listed in order of application):

The <code>#</code> tells zsh to remove the string <code>ALBUM=</code> from the *beginning* of the
string if it is present. This is removed because the next transformation
will muss it up.
Capitalizes the first letter of each word (and lowercases the rest) in the
Removes the value in the <code>$suffix</code> variable from the *end* of the
string. Note that this is an exact match &#x2013; not a regular expression &#x2013; so
the parentheses in the `$suffix` are fine.
Replaces all instances of <code>The</code> with <code>the</code> in the string. If there is one
word I am picky about capitalization for, it is `the`.
This analogous to doing `sed -ie s/The /the /g $file`

The result of all these transformations is an album title that is (more or less) properly capitalized and missing the "(Bonus Tracks Version)" suffix!


Breaking the void (Bonus Tracks Version)
Empty (Bonus Tracks Version)
Gotta get mad (Bonus Tracks Version)
Letting go (Bonus Tracks Version)
Moving on (Bonus Tracks Version)
Return (Bonus Tracks Version)
Winter Cities (Bonus Tracks Version)


Breaking the Void
Gotta Get Mad
Letting Go
Moving On
Winter Cities

The simplicity of this script means that I will likely be able to extend it in the future to fix common music tagging ailments.

Of course, I'll have to make sure I never run it on a Skinny Puppy album. Ye ever seen one o' those?

Home is Where?

Written by J David Smith
Published on 26 November 2014

The questions were innocent enough: "What about you hometown makes you feel at home?" for example. This is a difficult question for me, because I don't feel at home here. I've always known this, but it's been relegated to the back of my mind where it could (hopefully) do no harm. Now I faced it before me.

I spent a solid twenty minutes staring at the blank space below that question. I briefly considered writing down some vague nonsense, but I couldn't lie to myself. Ultimately I wrote something to the tune of "Nothing. I do not feel at home here."

Then I played video games til 4 in the morning.

A Bit of Today in the First Person

Today, things were generally better. My mind had settled, had forced that thought back out of my mind. For much of the day, that was enough. Much of the day.

My little brothers convinced me to play a game of League of Legends about an hour ago. Although my skills have decayed significantly, I'm still more-or-less on their level (especially in the jungle). As soon as I logged on Mumble, I was greeted with my youngest brother (Jo) talking at his usual 90 miles per hour. I'm used to it, but normally he stops after a little while.

We queue for a match, and I get thrown into the ADC role. This is blind pick, so we don't have any control over their picks. Of course, they include Blitzcrank and Zed. Both are nasty to play against as squishy, squishy Tristana. Unfortunately, their Blitzcrank was rather good.

Our lane started off with me getting hooked and barely escaping after blowing both Flash and Heal. All the while, Jo is still talking at 90 miles per hour and my other brother Seth is responding to questions as Jo fires them.

I very nearly snapped. Less than 5 minutes in Mumble with them and I leave their channel and just sit for a moment, doing nothing in game or reality. I switch my playlist from Schwarzblut's latest album to a mix of the later T.O.Y./Evil's Toy synthpop albums. Usually, that calms me down. Sure enough, Rainbows vs Stars helped. But things felt off, perhaps foreign.

I insist that we surrender at 20 minutes. By the time the vote passes, I'm 2/7/2 with abysmal CS. Immediately, Mumble and LoL are closed. I finish my half-eaten dinner, and refill the liter Hofbräu mug that I've re-purposed as a water glass.

I fire up steam and immediately close it again. Or at least I tried – the updater popped up moments after I closed the previous window. I let it run, leave it open and grab my laptop to write this.

All Things in Time

I don't know why I wrote all of that down. I am unsure of a lot of things right now. One thing I do know is that I have not recovered from facing this truth quite yet: I do not belong here.

There have been a few times that I've been more-or-less comfortable. This summer, working with the great people in ExtremeBlue at IBM. These days, when hanging out in the ACM room at UK. Thinking back, that actually about sums it up. Regardless, the feeling of belonging is always broken. Almost always by some small, off-hand comment with large, unintended consequences.

It's ok, though. I have the twin questions of "Where do I belong?" and "Why not here?". I do not know the answer to either. In truth, the second question bothers me more. Regardless, I know one thing: I will learn the answers, or will discard the questions. Why do I know this? Simple: everything works out. Everything always works out – just not in the way one might expect.

A Small Post-Script

I tend to be very anti-social, but I feel the need now to express gratitude to my friends just now. There may not be a place that I feel at home, but they are the people that I can turn to. One of them messaged me last night after my tweet-storm to see if I was okay. That meant a lot to me. More than I knew then. It's all the small things, really. All the small things.

Introversion: Seeking Balance

Written by
Published on 4 August 2014

The Dream

Of course, it wasn't an exact match, but it was close enough that my mind drew a connection. My eyes teared up as the long forgotten memories suddenly forced their way to the forefront of my mind. For a moment, I relived the dream. Then it fled – just as quickly as it had all those years ago.

In my dream, I was on a dirt path deep within a pine forest. It was night, and the clouds held a beautiful purple hue. The power of a coming storm made the air buzz more than the incessant sound of insects did. Aside from said insects, the forest was silent.

As the dream fled from me, I felt a heavy longing settle over me. I wanted to be there, to bask in the beauty of the forest and the power of the storm. To exist – if only for a moment – in that most beautiful environ. Before long, my contemplation led to the realization of how much I miss the forests.

The Woods and I

I didn't have much exposure to woods growing up. My home was on the outskirts of a small city for most of the first 13 years of my life. We had a couple of trees, but nothing much. On occasion, we went camping. I always complained about it (as all children do), but I still liked it. Most of my experience with the woods comes from playing in the trees out back of my friend Brandon's home.

Brandon lived at most a mile from the Kentucky River. Behind (in one sense of the word behind) his home, there was a great mass of trees stretching off into the distance. We often went exploring in these woods, trekking to the river and back in zigzagged patterns. Once we went alongside the river until we came to a long rocky slope cutting right across our path. We hadn't realized how long we'd been gone until sunset arrived and quickly began departing. Our mothers weren't very pleased with our little adventure, seeing as we didn't make it back til nearly dark.

Over time we became more interested in video games than exploring the woods. This was partly because we'd already seen much of them, and partly because video games offered more to explore. I don't regret that shift in priorities, but I do miss the trees.

Alone-ness: My Paradoxical Longing

Introversion is a definitive aspect of my personality. It has displayed prominently ever since I was an infant. In fact, I have been told that as an infant I would cry incessantly when put to bed – until everyone left the room, at which point I would immediately calm down. Were my mom or dad to re-enter the room, I would begin bawling my eyes out again.

This dream reminded me of how much I miss being alone in a way that no city can provide. In the woods, I am alone. When I am alone, I am free. At the same time, I cannot help but remember the objective I held in the dream-forest: finding my friends. Among the fleeting trees, I sought companionship. I longed for it even as I now long to be alone.

The Importance of Balance

Ultimately, this experience has served as a reminder to me that I'll not be happy until I find my balance. I have often contemplated seeking out a hermitage. It has been a 'not now, but maybe' train of thought in recent years. While I now believe that a hermitage might be taking things a bit too far, it is certainly the right direction.

While at school this past year, I increasingly felt the need to escape from the constant press of humanity. During this summer, I have found much respite, despite the fact that I am constantly surrounded by people. This is largely due to a difference in density: here I am surrounded by people, but in small quantities – unlike on campus, where even a walk through the engineering complex can take me past more than a hundred people easily. I dread the great mass of humanity more than anything else as I contemplate returning to school.

Even still, I have felt the need to escape during this summer. Certainly, my current environment is a step in the right direction, but it is not enough. I must be constantly wary of overshooting my target, but I cannot yet say that I have found the proper balance. Now I must wonder: will I be able to?

Evaluating JavaScript in a Node.js REPL from an Emacs Buffer

Written by J David Smith
Published on 1 June 2014

A Survey of Existing Tools

One of the first tools I came across was the swank-js / slime-js combination. However, when I (after a bit of pain) got both setup, slime promptly died when I tried to evaluate the no-op function: `(function() {})()`.

Many pages describing how to work with Node in Emacs seem woefully out of date. However, I did eventually find nodejs-repl via package.el. This worked great right out of the box! However, it was missing what I consider a killer feature: evaluating code straight from the buffer.

Buffer Evaluation: Harder than it Sounds

Most of the languages I use that have a REPL are Lisps, which makes choosing what code to run in the REPL when I mash C-x C-e pretty straightforward. The only notable exceptions are Python (which I haven't used much outside of Django since I started using Emacs) and JavaScript (which I haven't used an Emacs REPL for before). Thankfully, while the problem is actually quite difficult, a collection of functions from js2-mode, which I use for development, made it much easier.

The first thing I did was try to figure out how to evaluate things via Emacs Lisp. Thus, I began with this simple function:

(defun nodejs-repl-eval-region (start end)
  "Evaluate the region specified by `START' and `END'."
  (let ((proc (get-process nodejs-repl-process-name)))
    (comint-simple-send proc (buffer-substring-no-properties start end))))

It worked! Even better, it put the contents of the region in the REPL so that it was clear exactly what had been evaluated! Whole-buffer evaluation was similarly trivial:

(defun nodejs-repl-eval-buffer (&optional buffer)
  "Evaluate the current buffer or the one given as `BUFFER'.
`BUFFER' should be a string or buffer."
  (let ((buffer (or buffer (current-buffer))))
    (with-current-buffer buffer
      (nodejs-repl-eval-region (point-min) (point-max)))))

I knew I wasn't going to be happy with just region evaluation, though, so I began hunting for a straightforward way to extract meaning from a js2-mode buffer.

js2-mode: Mooz is my Savior

Mooz has implemented JavaScript parsing in Emacs Lisp for his extension js2-mode. What this means is that I can use his tools to extract meaningful and complete segments of code from a JS document intelligently. I experimented for a while in an Emacs Lisp buffer. In short order, it became clear that the fundamental unit I'd be working with was a node. Each node is a segment of code not unlike symbols in a BNF. He's implemented many different kinds of nodes, but the ones I'm mostly interested in are statement and function nodes. My first stab at function evaluation looked like this:

(defun nodejs-repl-eval-function ()
  (let ((fn (js2-mode-function-at-point (point))))
    (when fn
      (let ((beg (js2-node-abs-pos fn))
            (end (js2-node-abs-end fn)))
        (nodejs-repl-eval-region beg end)))))

This worked surprisingly well! However, it only let me evaluate functions that the point currently resided in. For that reason, I implemented a simple reverse-searching function:

(defun nodejs-repl--find-current-or-prev-node (pos &optional include-comments)
  "Locate the first node before `POS'.  Return a node or nil.
If `INCLUDE-COMMENTS' is set to t, then comments are considered
valid nodes.  This is stupid, don't do it."
  (let ((node (js2-node-at-point pos (not include-comments))))
    (if (or (null node)
            (js2-ast-root-p node))
        (unless (= 0 pos)
          (nodejs-repl--find-current-or-prev-node (1- pos) include-comments))

This searches backwards one character at a time to find the closest node. Note that it does not find the closest function node, only the closest node. It'd be pretty straightforward to incorporate a predicate function to make it match only functions or statements or what-have-you, but I haven't felt the need for that yet.

My current implementation of function evaluation looks like this:

(defun nodejs-repl-eval-function ()
  "Evaluate the current or previous function."
  (let* ((fn-above-node (lambda (node)
                         (js2-mode-function-at-point (js2-node-abs-pos node))))
        (fn (funcall fn-above-node
              (point) (lambda (node)
                        (not (null (funcall fn-above-node node))))))))
    (unless (null fn)
      (nodejs-repl-eval-node fn))))

You Know What I Meant!

My next step was to implement statement evaluation, but I'll leave that off of here for now. If you're really interested, you can check out the [full source](https://gist.github.com/emallson/0eae865bc99fc9639fac).

The final step in my rather short adventure through buffevaluation-land was a *-dwim function. DWIM is Emacs shorthand for Do What I Mean. It's seen throughout the environment in function names such as comment-dwim. Of course, figuring out what the user means is not feasible – so we guess. The heuristic I used for my function was pretty simple:

This is succinctly represent-able using cond:

(defun nodejs-repl-eval-dwim ()
  "Heuristic evaluation of JS code in a NodeJS repl.
Evaluates the region, if active, or the first statement found at
or prior to the point.
If the point is at the end of a line, evaluation is done from one
character prior.  In many cases, this will be a semicolon and will
change what is evaluated to the statement on the current line."
   ((use-region-p) (nodejs-repl-eval-region (region-beginning) (region-end)))
   ((= (line-end-position) (point)) (nodejs-repl-eval-first-stmt (1- (point))))
   (t (nodejs-repl-eval-first-stmt (point)))))

The Beauty of the Emacs Development Process

This whole adventure took a bit less than 2 hours, all told. Keep in mind that, while I consider myself a decent Emacs user, I am by no means an ELisp hacker. Previously, the extent of my ELisp has been one-off advice functions for my .emacs.d. Being a competent Lisper, using ELisp has always been pretty straightforward, but I did not imagine that this project would end up being so simple.

The whole reason it ended up being easy is because the structure of Emacs makes it very easy to experiment with new functionality. The built-in Emacs Lisp REPL had me speeding through iterations of my evaluation functions, and the ability to jump to functions by name with a single key-chord was invaluable. This would not have been possible if I had been unable to read the context from the sources of comint-mode, nodejs-repl and js2-mode. Even if I had just been forced to grep through the codebases instead of being able to jump straight to functions, it would have taken longer and been much less enjoyable.

The beautiful part of this process is really how it enables one to stand on the shoulders of those who came before. I accomplished more than I had expected in far, far less time than I had anticipated because I was able to read and re-use the code written by my fellows and precursors. I am thoroughly happy with my results and have been using this code to speed up prototyping of Node.js code. The entire source code can be found here.

Wot I Think: Heroes of the Storm Technical Alpha

Written by J David Smith
Published on 23 May 2014

Once I had survived finals (with all A's, no less! ^.), I got the download going. Gotta say one thing: getting set up for Blizzard alpha/beta games is super-easy with their unified launcher. I literally just clicked 'Install', selected a location, and was done save for the download itself.

As I'm going through wot I think of the game so far, keep in mind that it's still in Technical Alpha. Also, I've only played somewhere between 20 and 30 games so far: enough for a 'First Impressions' but not a full-on review.


One of Blizzard's strong points has always been their excellent presentation. Due to artwork that relies heavily on stylization over poly counts, their games tend to look surprisingly good even on low-end hardware.


The system I'm playing on is getting a bit dated. The important specs are:

Passable, but not particularly powerful. I have been playing the game on Medium or High settings depending on the match. Performance has varied from match to match, but overall has been very good – most of the time. Some champions heroes hurt my framerate more than others; the difference makes sense, as some (ex: Diablo) are much more particle-heavy than others (ex: Nova). Considering that this is an alpha, I was pleasantly surprised at the generally consistent framerates.

Graphics & Style

Blizzard has continued in their path of very stylized graphics. While some models seem more-or-less ripped from their respective games on the surface, the ones I've seen appear to have been tweaked to better fit the style of the game. That said, it will always look funny to see Diablo riding a horse. Poor horse.



While on the surface Heart of the Storm is quite similar to other contemporary MOBAs, the similarities are only at the mechanical level. The game is played in 5v5 competitive matches from an isometric perspective with RTS-style click-to-move controls. The core gameplay is roughly the same as League of Legends or Defense of the Ancients. However, several systems changes have dramatically altered the dynamic.

Prepare to be Broke

The first of these is removal of gold as a resource. This has the effect of reducing the snowball effect. While snowballing still occurs for reasons I'll discuss in a moment, it is not nearly as severe as in LoL or DotA. The removal of this system entirely has not been without controversy. However, it has received a suitable replacement for customization in the Talent system.

Talented, Aren't We?

Every few levels (starting at 1), players are given the option of 2-4 talents. These range from passives like Path of the Wizard, which grants increased mana and mana regeneration, to the choice of Ultimate Heroic abilities at level 6. Players are not able to change talents during a match – only choose them – but they are reset after every match, in classic MOBA style.

I should make it clear that the talents are chosen in a style similar to WoW's current system: you are given 2-4 choices and must take one (and only one). You can't take 2 from tier 1 and none from tier 2 or any of that chicanery. Come to think, I should test and see what happens if I don't take any talents when more are offered.

With this system, experience has effectively replaced gold as the currency du jour. Talents offer raw stat buffs as well as interesting active effects (such as Malfurion t2 offering an OP as fuck shield spell). However, this means that we won't ever see crazy builds like AP Rengar. Then again, I would be much happier if I'd never had to deal with the BS that was AP Yi. Win some, lose some.

Overall, I'm pretty excited about the talent system. I don't feel like it restricts my options much during play, while it eases the introductory learning curve significantly and has potential to reduce the frequency of significant balance issues.

Team-wide Experience

Another important change is Blizzard's move from per-hero experience to per-team experience. No hero (even those AFK) is left behind in this system. However, it does make it so that a bad player can impact your performance much more quickly. Both player and minion kills give experience – but only if someone on your team is in range. Therefore, if another lane is feeding then not only is their lane gaining an advantage, but yours is as well. Additionally, because the feeding lane is going to spend more time dead (and thus away from the creeps) your entire team will fall behind in experience.

This isn't as disastrous as it sounds. The most significant difference I've ever seen in levels is 4. I've heard that there are catch-up mechanics in place, but I've not done the research to confirm or deny this hearsay. Regardless, being 4 levels behind is about as bad as being 4 levels behind in LoL: painful, but not insurmountable. It's nowhere near "our bot lane went 0-20 in 10 minutes" bad, as the occasional LoL game will be.


The map design and implementation is also considerably different from classic MOBAs. Where LoL and DotA effectively have only one map with only one mode, HotS has 4 as of this writing – each with its own secondary objectives. This is similar to how Guild Wars 2 has several different maps with the same primary objective (king-of-the-kill; win at 500 points) but disparate secondary objectives (kill boss mobs for extra points, invade enemy base for lots of points, control catapults).

The primary objective is the same as in LoL / DotA: destroy the enemy ancient nexus core. The method of attaining this objective is, again, similar: farm and push. However, there is a significant twist common to all maps: mercenaries.

This Ain't Your Daddy's Jungle

Where LoL / DotA (henceforth abbreviated as LotA) have neutral camps scattered in the 'jungle' between the lanes, HotS has Mercenary camps. These camps are significantly more difficult than their counterparts in LotA, but they do not scale in level as the game progresses like they do in LoL. When a camp is killed, a capture point becomes available. Obtaining control of this point will spawn a band of mercenaries that will push on your team's behalf and put the camp on a ~3 minute cooldown.

What results is a pretty clever solution to the game length problem: pushing becomes considerably easier as the game progresses without snowballing causing one team to dominate the other in team-fights. Adding in secondary objectives is really just icing on the cake – I'd be happy to play a mode lacking them.

The secondary objectives in HotS are varied enough that – provided the RNGods favor you – the game stays fresh even when playing the same hero over and over again. One map features two shrines that, when controlled by your team, allow one team-member to transform into a powerful dragon. Another has players traveling under the map in a mine full of undead, collecting skulls to summon powerful golems. Yet another asks us to fight mercenary camps and bust open treasure chests to pay a greedy pirate captain to bombard the enemy base with his cannons. While some still need tuning (it is very difficult to come back from being hit with a team-wide curse that reduces all of your creeps' HP to 1, reduces structure HP by half, prevents turrets from firing, and prevents natural HP regeneration), they certainly provide interesting gameplay.

Notably lacking right now is a Starcraft-themed map. The others are fantasy-themed – not even really Warcraft- or Diablo-themed, which is kind of disappointing. This is one area that I feel Heart of the Storm is really lacking in right now. While the characters belong to well-defined universes, the maps don't really belong anywhere. I'd like to see the existing maps changed to fit better into one of the existing Blizzard universes. This would make the game as a whole feel more cohesive.


MOBA games tend towards a certain balance level at early stages of development. Heroes of Newerth, as an example, was more-or-less balanced with the exception of a handful of heroes that were completely over the top. In my experience, this is pretty common. The underlying mechanics are well-understood, but it is still quite easy to over-tune a hero and turn it into a walking murder machine.

Heart of the Storm does not have this in my experience. Certain map mechanics need re-balancing right now (Undead Mines and Curse of the Raven Lord), but I've never seen a hero that just made me shout "that is bullshit!" – except for Nova.

The Stealth Problem

Nova has a lot of things going for her: decoys, stealth, high damage, high range. Meanwhile, she is super-squishy to help balance things out. This would normally work fine, except for stealth. In HotS, stealth works like its Starcraft II incarnation: predator-style shimmer around you, not true invisibility. Stealth automatically activates after 2 seconds of not taking damage.

2 seconds

This is only a problem because there is not a good way to stick on her for many heroes. One bad choice by the pathing algorithm pretty much means that she's gone unless you're ranged or have a low-cooldown gap closer (because you probably blew it to reach her the first time). Even this wouldn't be a problem if the stealth worked entirely as advertised.

This kind of stealth is really cool in concept, except that it suffers from a very odd problem: what to do on low-power machines. The predator-style effects are expensive. Thus, there are three choices Blizzard could make about this:

  1. Leave them on for all machines, potentially causing significant FPS loss on low-power machines.
  2. Turn them off on low-power machines, turning stealth into true invisibility.
  3. Swap them for a cheaper but less subtle effect on low-power machines, making stealth less reliable against people playing on the lowest setting.

I am honestly not sure which one Blizzard is using right now.