Maia McCormick

Programmer, writer, nerd

My name is Maia. I’m a programmer based in New York City, currently working as a software engineer at Spring. This is where I (somewhat infrequently) chronicle my journeys through code, as well as other vaguely related adventures.

So Much for That Project

Alas, it seems that my dreams of writing a choral harmonizer in the style of J.S. Bach have to be put to bed until another day. Susan and I have been taking various stabs at this, trying out a few ineffective Python midi programs (one of these, incidentally, had ZERO documentation and was THE MOST FRUSTRATING THING EVER) before settling on mingus, a midi/music theory Python library. Unfortunately, it seems like no one’s addressed any bug reports since 2011, so when we realized that midi read-in was totally borked, we were a little stymied. Specifically, if we gave it this file as input:

Input file

It returned this mess here:

Output file

Asking for TOO MUCH Help?

(Apparently some people at Hacker School think I’m an Iron Blogger, despite me being nothing of the sort. There’s no money riding on whether or not I make consistent blog posts—but I figure I should do what I can to sustain this favorable impression of me!)

Since my HS halfway check-in, I’ve resolved to ask more questions and not let myself get stuck banging my head against problems that could be solved in a hot second by any of the three people sitting next to me. I think that I’ve done a pretty good job with this resolution; I ask for help way more frequently, and as a result, I think I get more done. However, I feel the need to remind myself that there is such a thing as asking for too much help.

Take this example: I was sitting down with Tristan, a fellow HSer, attempting to set up virtualenv and get all of my permissions and installs un-borked. I was totally in over my head, having never used virtualenv before, and he was helping me sort it out. There was some funky stuff that needed fixing having to do with my $PATH being invalid because one of the folder names contained a space. We dealt with that issue, and now most of the stuff worked, but I still couldn’t manage to run bpython from inside my virtualenv. I showed Tristan the error message my computer was spewing, and asked him, “What’s going on?”

His response: “What do you think is going on?”

Me: “Well, it won’t run bpython!”

Him: “Come on, you can do better than that.”

Observations From Phonebook Code Review

Here are some gleanings from Amy’s code review of my phonebook applet, and some self-study. Mostly for my own records and so I actually absorb all of this by writing out, but if anyone has comments, additions, disagreements with anything I’ve written here, fire away!

  • misc. layout stuff, like putting import statements in alphabetical order
  • avoid global vars when possible. I already knew this, but it’s good to remember. For example, if you’ve assuming your program will be run on the command line, you can put global vars in the main() function.
  • functions that only incidentally return stuff are bad news. I had a function called phonebook_exists that checked to see if the phonebook you were trying to look up existed; if it didn’t exist, the func. would throw an error, and if it did, it would return the data of the phonebook. Which in retrospect was super weird because nothing the function name indicated that it was what you should use to get the contents of a saved phonebook. A much more sensible way to do this is to have a function called read_phonebook which attempts to return the contents of the saved phonebook, but if it fails (which you figure out with a try/except), then it throws an error. (Incidentally, I had a similar confusion with when things should and shouldn’t be returned in another project I’m working on, my bootleg homemade git. I had a function called save_at_hash that would hash a file, save it at its hash, and then return the hash. Why did this function return the hash? I assumed it would be useful. Couldn’t really tell you why. I ended up refactoring it into two functions, make_hash—which took a file and returned a hash—and save_at_hash—which took a file and a hash and saved a copy of the file at that hash.)

Taming the Octopress

I was messing around with my website yesterday, and trying to make two sub-websites for my ‘Music’ and ‘Programming’ hats in a single Octopress install, and I really was going to be on time to my dinner plans except once my website experiment was borked and I tried to restore my previous site… well, long story short, it was the borked-est, and I spent an hour then and an hour today hunting around with Allison trying to fix the problem. Turns out that in trying to roll back my changes, I’d introduced some discrepancy between my master and gh-pages branches, and I could get around all of this on github with force pushes (-f), but not so easily with actually deploying my site (rake deploy). In the end, I had to go into my Rakefile and add a plus sign somewhere that tells Octopress not to worry whether it’s doing fast-forward commits1 and just commit anyway.

All About Git

Here are the fruits of a mini-seminar on git from the inimitable Mary—a sketchy portrait of the inner workings of git.

Git: The Bestest Version Control System with the Worstest UI

All of your Git-age lives in the .git folder

When you run git init, all it does is create a .git folder. That’s it! Your machine knows what folders are and aren’t git repos by the presence or absence of a .git directory. .git is a hidden folder, so to see it, type ls -a. Whenever you add or commit things to your git repo, they’ll get stored in here.

Nested Functions

Know what’s cool? Nested functions.

The other day, as I was making this craaaazy dance parser (that’s getting more and more convoluted by the minute), Alan suggested a really baller way of organizing it: using a bunch of little mini-parser functions that all look for something specific in your text, and smooshing related parsers together into one macro-parser that runs all of them in turn until one returns something. In Alan’s lovely mock-up code that I’m shamelessly copying over here, that might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def contains_an_a(input):
    return input.find("a") > -1

def contains_a_b(input):
    return input.find("b") > -1

def one_of(parsers):
    def parser(input):
        for p in parsers:
            result = p(input)
            if result:
                return result
    return parser

contains_an_a_or_a_b = one_of([contains_an_a, contains_a_b])

The handy thing about having all of these bite-size functions is that none of them gets too crazy bulky, and also, since they’re functions (and not dicts like I was using earlier), I can use regexes in them! I’m also jamming on the idea of passing functions to other functions, so I made an even bigger function called use_parser that takes a parser, a default value, and an ‘ask’, which it uses to ask the user (via raw_input) what the value should be. This way, I can take a single parser and customize it in a variety of ways. Say for example I have a distance parser: for do-si-dos and gypsies it should default to False (because those moves don’t necessarily need to take a distance) and for allemandes it should ask the user, “what’s the value of ‘dist’ here?”

Slicing Is Not Enough (or, Adventures in Deep Copy)

The sudoku solver that I’m working on with Miriam was nearly finished before it started when we were playing around with ways to draw a board to terminal. I came to the table with some initial code I had written—

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def draw_board(board):
    for i in range(0,9):
        board[i].insert(6, "|")
        board[i].insert(3, "|")
        row_string = "  ".join(map(str, board[i]))
        if i in [2, 5]:
            print row_string
            print "________________________________"
        else:
            print row_string

def newboard():
    return [[0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0]]

and the shiny output!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> myboard = newboard()
>>> draw_board(myboard)

0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0
________________________________
0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0
________________________________
0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0
0  0  0  |  0  0  0  |  0  0  0

Everything was awesome! Or so I thought. But look what happened when I ran the code again.

Checking in With the Hacker School Experience

Oh hai there, blag! It’s been a while. Too long. The days here blur together occasionally—hours of staring a screen working on multiple only-slightly-different problems will do that to you, and it’s really easy to lose track of what you’ve been working on, accomplishing, learning, and thinking about. Especially when those accomplishments seem really tiny and mundane. (“Yay, I got my database search page to work! Yay, I got my database search page to work for two things in sequence! Wait, it’s 7:00?”)

Had a one-on-one with Allison this afternoon about the State of the Hack so far—how HS is treating me, what I might want to do differently, what I might want to be different about the environment. Here are some thoughts prompted by that conversation.

  • I want to get better at asking for help, surmounting impostor syndrome, etc. I’m pretty good at this, all things considered, but I still need to do lots more work on this front. Sometimes asking a question on a Zulip thread isn’t what I need—it happens to not get responded to, or (more often) I would benefit much more from discussing it in person.
  • An interesting thing about the HS environment is how it’s way more normal to Zulip someone from across the room than go over and tap them on the shoulder. Generally, I get way more out of an in-person conversation than an online one, so I’d like to be better about just finding people in person to ask them questions. (Of course, the benefit of Zulip-ing is that you know who can/can’t be interrupted. Tricky balance here. But I should feel more able to approach facilitators, at least.)

Fluffy (and Often Queer/YA/Both) Book Recs

In response to a recent Hacker School discussion about fluffy book recommendations written by !(white & cis-male), here’s a list of some of my go-to’s, and books I’ve enjoyed reading lately. What defines fluff? That’s a more complicated question for a later time. How I’ve been thinking of it lately is as books that don’t require much effort to read/parse—i.e., not an awful lot of subtext, relatively simple language and not too much artistry of the obfuscating variety in the text itself—that play off characters and tropes that we like to read about. They will generally have not-terribly-well-developed characters, characters that are easy to identify with, and the stories and happy endings that we want for ourselves. But, regardless of my definitional musings, here are some books! And so, in no particular order:

  • Annie on My Mind by Nancy Garden: LOVE. I think it was the first bit of lesbian lit that I read, and thus holds a special place in my heart.
  • The Miseducation of Cameron Post, by Emily M. Danforth: follows a young girl’s sexual self-discovery, first love(s), and her time at a homosexual rehabilitation program.
  • Beautiful Game and Solstice by Kate Christie: fluff in the highest degree, but well-written, engaging, hold-your-attention-till-the-very-end fluff. (I also think it’s worth noting that I typed the title to the first as “Beautiful Gayme” the first time through. Oops…)
  • Anything by Tamora Pierce, but especially the Song of the Lioness quartet: because Tamora Pierce is the bomb, and has an incredible gift for plots, and has been the beginning of more girls’ feminism than can be counted. Feminist, sex-positive, swords-and-sorcery high fantasy at its best!

‘Wasting’ Time?

At Hacker School today, I didn’t get all that much done, and in my day’s worth of non-progress I brushed up against two distinct kinds of “wasted” time.

The first is somewhat productive, as wasted time goes. I spent most of the afternoon barking up various wrong trees as I tried to figure out how to structure the next step of my current project (a contradance database, which I’m sure I’ll blog about for real soon). Kind of like a real-life breadth-first search where every node takes several hours.

I’ve got a way to structure my data, and now I want to be able to search and sort and filter a bunch of these data-bundles. First I assumed I’d write the search code in Python and worry about making it web-app-y later. I started brainstorming and had no idea how I would optimize my code, and then someone suggested I use Data Tables a JQuery plug-in which will search and sort data super fast. So I spent a while reading up on Data Tables, looking through FAQs and add-ons and trying to figure out if it would give me some of the more advanced searching functionality I wanted. Someone else then suggested that if I ultimately wanted to search by a giant table of data invisible to the user, why don’t I just use mySQL and go right to the database end of things? So I talked to Andrew and hashed out a vague plan and set up mySQL on my machine and found some nice-looking tutorials… only to have someone else point out that hey, you don’t need to worry about learning SQL, Django can do all of that for you and you still get to write in Python. I gave Django a quick look, got excited, and then whoops it was 5:00.