An Algorithmic Lucidity

a blog

September 2013

App Academy Diary, Week Three

Monday 30 September 2013— Today's assessment was implementing Crazy Eights in accordance with the given RSpec tests. In the afternoon, I worked with Dan Quan on exercises from the SQL Zoo, which varied wildly in difficulty.

Tuesday 1 October 2013— Today I worked with A. J. Gregory again, this time on a cute Ruby program for interacting with a database. A few remarks follow. The first remark: I much prefer the %Q syntax for multiline strings over heredocs. The second remark: it turns out that using string interpolation to compose database queries is very bad, because it leaves you vulnerable to SQL-injection attacks. The third, and final, remark: you shouldn't name any of your Ruby classes "Data," because apparently this name is already used by a regrettably exposed implementation detail of the interpreter itself.

Saturday 5 October 2013— Dear reader, suppose again that you're building the great American dog-sharing site. One problem that you face is that the the most convenient way of storing data in the database isn't exactly the same as the most convenient way to manipulate data in your program. It would be nice to have some standard tool for translating the rows in your database table to occurrence of a particular class in your favorite programming language and back again, without having to futz with the syntax of the systematic questioning lexicon every time you add a new feature ... some sort of—occurrence–row matching ...

The Ruby on Rails framework (does anyone else think Ruby on Rails sounds like the title of an action movie about a woman named Ruby who has to fight spies on a train?—no?) includes a library called ActiveRecord for this purpose. Suppose your database has a users table for storing all the user data, and a dogs table for storing all the data about dogs. And suppose we want to say that each dog is owned by a particular user. We can do that by including an owner_id column in the dogs table; for each row in the dogs table, this column will store a number referring to a row in the users table, thus indicating the user that owns that dog. Columns like this that refer to another table in the database are called foreign keys, and we also want to tell the database to index them so that we can search them in logarithmic rather than linear time in the number of rows. Then, when we write the classes to represent users and dogs in our application code (these are called models), Rails gives us nice shortcuts to make it easy to retrieve (respectively store) their information from (respectively in) the database. In the User class, we say that a user "has_many :dogs, :class_name => "Dog", :foreign_key => :owner_id, :primary_key => :id", and we put a similar belongs_to statement in the Dog class (the belongs_to corresponding to a has_many always goes in the class whose database table contains the foreign key), and then everything is great forever.

On Wednesday I worked with Mainor Claros on a simple URL shortener, and on Thursday I worked with Scott Silver on models for a simple polling application. Yesterday the original plan was to have a solo day during which each of us would implement our own simplified version of ActiveRecord (... SedentaryRecord?), but at some point it was decided that the office was needed to host hiring day for the cohort before ours, so there was no class yesterday and we'll do SedentaryRecord on Monday of next week. I told myself I would get something educational done just the same (App Academy is providing value added in the form of guidance, connections, and a working environment, but if you're a long-time reader of An Algorithmic Lucidity, then you know that I know that the ultimate responsibility for internalizing knowledge must rest on individuals, not institutions), but I'm sorry to report that some of the more frivolous distractions of the internet (as well as a science-fiction novel that I purchased Thursday night on a whim at the bookstore inside the library in the city, which I had not set foot in since I think the March of 'aught-ten) proved too tempting that day. But fear not, dear reader!—for today and tomorrow are an entirely different story, in which your faithful correspondent will no doubt make tremendous progress in his quest for true knowledge of the nature of web development, as well as related matters of concern, like who would win in a fight between the MySQL dolphin, the Postgres elephant (PostgreSQLephant?), and the bird that the SQLite feather was taken from.

Sunday 6 October 2013— Yesterday and today I looked at the instructions for the project scheduled for tomorrow which I've been calling SedentaryRecord and started working on a Python version (including tests), which I've been calling SerpentineRecord. Why? Because ... because I can. And because even though this is a Ruby/Rails course, I've been toying with the idea of preferentially shooting for Python/Django jobs when this is over. My thought is that Ruby and Python are filling the same niche in programming-language space, so that in the long term, it's only worth specializing in one of them: really mastering a tool (not just the basic syntax, which is easy, but the technical minutia and ecosystem and everything) is costly, so you want to allocate your finite amount of effort into mastering an orthogonal set of tools, rather than many tools that do mostly the same things. So if I will ultimately have to choose, I'm inclined to go with my first love, Python, even if that's only an arbitrary artifact of what I happened to learn first. Is that wrong? Is it petty of me to care about the merely cosmetic issue of syntactic whitespace versus that execrable word end, even while Ruby's blocks are suffused with grace and power whereas Python's lambda statement is deliberately crippled precisely because of whitespace considerations?

I don't know. But in any case, my money is on the dolphin.

App Academy Diary, Week Two

Monday 23 September 2013— I rewrote most of the tic-tac-toe game yesterday; information-theoretically speaking, the board state is only 9 lg 3 ≈ 14.26 bits, but for better or for worse, I resisted the temptation to represent it as a two-character string. Still (still!) didn't get the AI working, though. Today was our first assessment: way too easy, I thought; we were given about an hour, and I finished in under half that. Then we had a lecture/Q&A period which I thought was too long, which covered the solutions to the assessment and default hash values. Why does anyone think lectures are a good idea? I'll confess to hanging out in the back and reading a little bit from A Farewell to Alms, which I bought on a whim on Saturday at Half-Price Books (which is a nice store, although you have to wonder whose idea it was to stock so many copies of Elliptic Partial Differential Equations and Quasiconformal Mappings in the Plane). At lunch I bought coffee and food at Starbucks and spent a little more time trying to debug the tic-tac-toe AI—still to no avail, but I'll get there eventually! (Tic-tac-toe itself is dross, but it's really important to get minimax right, because it should generalize to other games without too much trouble, and we're doing chess later this week.) Speaking of games on grids, today's project was to clone Minesweeper. I worked with Jeff Fiddler, who is the Jeff from Nevada (and not the other Jeff who tried to teach math in high schools but was frustrated with the overemphasis on standardized tests). It went really well; we used pretty Unicode symbols and even got around to implementing a cursor interface (which is way better than making the user enter coordinates)!

Wednesday 25 September 2013— Yesterday and today I wrote chess with Nathan Holland! Also, it turns out that the criminal scum who steal entire bicycles are not above stealing individual wheels, either.

Our Chess

Thursday 26 September 2013— Today's exercise was to write checkers, alone (contrast to the pair programming methodology of previous days). I ... used structs to represent the checkers and moves? I like structs?

My Checkers

Saturday 28 September 2013— Yesterday was about testing. Novice programmers test their programs by running them and seeing if they give the expected results, which might be okay when your program is small and no one actually uses it, but then what happens when you wake up one day and you're in charge of maintaining a twenty-thousand-line application that people really depend on?

Enter automated testing. By writing code to test code, developers can save time and be confident that recent changes haven't broken existing functionality! (At this point a pedant smugly inquires whether this implies the necessity of writing tests for the tests, and tests for the test-testing tests, and so on ad infinitum. This arguably doesn't deserve a reply, but is in any case easily answered by the observation that we expect tests to be much simpler than the code which is their subject; it takes less information to specify what is expected of a procedure than it does to specify the details of the procedure itself.) In test-driven development, the practice is actually to write the tests first.

I paired with A. J. Gregory; after some simple exercises, our major task of the day was to write a five-card-draw poker game in the test-driven development style. I will confess that this did not go as successfully as the projects of previous days. Perhaps the art of factorizing the idea of a program into informative tests takes more than a day to learn? Or maybe we were succumbing to tiredness at the end of a very educational week, this fatigue being only a very minor sin characteristic of being human, for which we may yet be forgiven? I can't say. (Yet.)

Sunday 29 September 2013— Dear reader, suppose you're on a quest to write the Great American Web Application—maybe the latest, greatest dog-sharing site or something; I don't know. Your app is going to need some way to persistently store data—your users' screennames, emails, hashes of their passwords (use bcrypt!), their dogs to share, &c. This data isn't really part of your application proper, so it goes in a special separate file called a database, but it is that which your application operates on and fundamentally exists for the sole purpose of curating, so your app needs some way of talking to the database and asking it questions, like "Hey, Database! User #97109 wants to be friends with User #89012; write that down, huh?" or, "My dearest friend Database, when you have a moment, could you please tell me which dogs User #98471 has available to share?" But this is mere anthropomorphism; what protocol do you actually use to get your code to talk to the database? If only there were some standard vocabulary for asking questions of the database ... some sort of—systematic questioning lexicon ...

Right, so today I successfully installed MySQL after some troubleshooting effort (it turned out that I needed to apt-get the mysql-server metapackage, and not mysql-server-core-5.5), and got acquainted with it at the command-line. Data is organized into tables of columns and rows, like maybe we have a ponies table with columns for pony_id, name and pony_type, and one of the rows is 2 | Twilight Sparkle | unicorn, and if we want to update Twilight's type we say, "UPDATE ponies SET pony_type = 'alicorn princess' WHERE pony_id = 2" and if we want to just look at the earth ponies we say, "SELECT * FROM ponies WHERE pony_type = 'earth pony'".

App Academy Diary, Week One

Monday 16 September 2013— For the next couple months, I'm going to be engrossed in an intensive web development course offered by App Academy; it's pretty great! Part of the routine is to write end-of-day blogposts describing what we've learned; I guess we were "supposed" to start a Tumblr specifically for these, but that's dumb because I already have a blog, so I think I'll just put my updates here (updating the post throughout the week). Today was the first day! App Academy puts a lot of focus on pair programming: you have two people at a workstation; only the "driver" types, while the "navigator" offers direction (and then you switch roles). Today I was paired with Chris Evans, who is a nice guy who knows way more math than me! Today our task was a bunch of fairly straightfoward Ruby exercises: monkeypatch the Array class to do this-and-such, make a playable Tower of Hanoi game, that sort of thing. The most challenging one was part 15 of Test First Ruby: write a method that accepts integers and returns a string describing the number in words (so e.g. 259123 becomes "two hundred fifty nine thousand one hundred twenty three"). Chris and I finished the most important stuff on time and started working on the bonus project about solving mazes, but we didn't get too far with that in the time remaining.

Tuesday 17 September 2013— Lecture/Q&A ran to 1035 today, which I thought was way too long, but at least I learned about how to use #tap to build up an array. Today I was paired with Josh Foster, who is a nice guy who has been working as a business analyst for a few years! We did some more Ruby exercises, still rather straightforward (I expect most of the value of the course to come in later weeks, as we learn about SQL, Rails, &c., of which I know almost nothing). Our tic-tac-toe game (with a dumb AI) took a while to debug.

Wednesday 18 September 2013— I was a few minutes late today because a train ahead of the train that I was on had mechanical troubles! Today I paired with Jen Hamon, who is awesome and used to study geoscience! We implemented the guessing games Mastermind and Hangman, and then started working on A* search (picking up with the code about mazes that I started with Chris on Monday), also taking a detour to investigate some curious behavior exhibited by Ruby hashes with arrays as keys.

Friday 20 September 2013— Yesterday's themes were Procs and recursion. I paired with Ben Hass; our most challenging exercise was Word Chains: find a way to mutate a dictionary word into another of the same length by changing one letter at a time, with all the intermediaries also being valid words (e.g., duck to unprintable to funk to fund). The prompt even included suggestions ("Grow a new set, new_words, by calling adjacent_words on each of the words in current_words," &c.), but our implementation wasn't behaving quite right; the TA Flarnie Marchan pointed out that we were wrongfully discarding some of the discovered words (the idea of a queue was mentioned). On the evening train, I thought more about this and realized that the problem is really just a standard breadth-first search; I rewrote a much cleaner Word Chains after I got home. Graph search (breadth- and depth-first) was also today's theme; I paired with Kenny Chandrasekera. The first part of the day went smoothly, but we had more difficulty with the task of writing a better (in fact, unbeatable) AI for Tuesday's tic-tac-toe game. We first tried negamax, at my suggestion (I was familiar with the problem from having done basically the same thing in Python last year), but didn't get it right; then we switched to an approach involving building up the game tree explicitly, but didn't finish. (The entire tic-tac-toe program is such terrible code that I might just rewrite the whole thing this weekend.)

All Vows

"Avinu Malkeinu, we have sinned against you! Avinu Malkeinu, forgive us, bless us, grant us atonement!"

"Why do you bother? You're not a child. You've studied the history of our world. You should know that there's no one to grant you atonement."

"You don't know that! Science doesn't know everything. You can't prove that there's no Higher Power."

"As you say. But if there is a Higher Power, It clearly hasn't concerned Itself with the operation of the moral law."

"In this world."

"Yes, in this world. But surely it is this world that we must concerned with, for if there is a next world, we are too ignorant to speak of it."

"That is why it is also a teaching of my people that this is also a time for us to forgive each other for the wrongs we have committed in the past year, as well as seeking reconciliation with haShem."

"And you anticipate the same thing being necessary next year?"

"I don't understand. How could it not be necessary?"

"'Knock, knock.'"

Engineering Selection

This whole business of being alive used to seem so much simpler and less morally ambiguous before I realized that the strong do what they can and the weak suffer what they must, that it has always been thus and could not have been otherwise. The other day I was reading Luke Muehlhauser's interview with Steve Hsu, and Hsu says:

Let me add that, in my opinion, each society has to decide for itself (e.g. through democratic process) whether it wants to legalize or forbid activities that amount to genetic engineering. Intelligent people can reasonably disagree as to whether such activity is wise.

There was once a time in my youth when I would have objected with principled transhumanist/libertarian fervor against the suggestion that the glorious potential of designer babies might be suppressed by the tyranny of the majority.

I don't have (those kinds of) principles anymore. Nor faith that freedom to enhance will inevitably turn out to be for the best. These days, my thoughts are more attuned to practical concerns. Oh, I'm sure he's just saying that because it sounds nice and deferential to contemporary political sensibilities and he doesn't want to catch any more flak than he does already. Obviously, the societies than forbid it are just going to get crushed under the boot of history.

Think about it. The arrival of Europeans in North America didn't go very well for the people who were already here—and that was just a matter of mere guns, germs, and steel (in Jared Diamond's immortal phrase). What happens to our precious concept of democratic process when someone has the option to mass-produce von Neumann-level intellects to design the next generation of superguns, ultragerms, and adamantium-unobtanium alloy?

True Inclusiveness

"Even after racism, sexism, and speciesism have been eradicated, the work of social justice won't be done. We still live in a viciously existence-biased Society, which cruelly disregards the interests of possible creatures just because they happen to not have been created yet!"

"'Creatures'?—I see you're still mired in the insidious grip of of organism privilege! What about all the possible qualia-bearing processes like orgasmium or paperclip-manufacturing nanoware, which don't factorize into distinct entities? My friend, I say there will be no justice until Society's sphere of moral concern extends to all possible computations in inverse proportion to their complexity!"

Strategy

"Oh, I'm so nervous! What if I ... ? What if they ... ? Oh, what ever shall I do?"

"I keep telling you, man, you're making things way too complicated. Just think about what outcome you want, predict which behaviors will lead to which outcomes, and then perform the corresponding behavior."

"That's it?"

"That's it."

Quotations II

Just keep telling yourself: if they haven't started questioning what society tells them yet, then maybe they are not the one for you.

—"Pick-up Lines for Feminists" by Lesley Kartali

So, so what
I'm still a rock star
I got my rock moves
And I don't need you
And guess what
I'm having more fun
And now that we're done
I'm gonna show you tonight
I'm alright
I'm just fine

—"So What" by Pink

The cheaper people are to model, the larger the groups that can be modeled well enough to cooperate with them.

Michael Vassar

Lyrics to the Song About Having Sinned

I'm going to do it the dark way
I'm going to do it in my way
I'm going to quietly sulk
And write things on the wall
And always be lonely

I will try to do my share
Sorting papers in my lair
But don't ask me to come play
'Cause I'll ask you to go away

I'm going to go on with living
Observing, loving, and giving
And I will never know joy
Nor being annoyed
Knowing that I've sinned
Knowing that I've sinned

I'm going to do it the dark way
I'm going to do it in my way
I'm going to make myself pure
With my act and my word
Frozen in my controlling

I will ruminate and try to figure out the humans' nature
And I'm looking for what's right
No matter if it is what I'd like

I'm never going to have a boyfriend
I'll always talk about the end
I will walk through halls
And pass through walls
Knowing that I've sinned
Knowing that I've sinned