Archive for November, 2011

Kindle Fire

November 17, 2011

Fire!For the first time in my life, I seem to be the first person I’ve talked to to have the latest electronic toy, one of these. It doesn’t have the enormous coolness factor of something shiny and made by Apple, but still.

Overall I’m loving it. I’m using it more as an extra-portable and convenient web-browser/time-waster than as a reader and Amazon-content-delivery system (its obvious purpose), more cheap-and-small iPad than expensive Kindle. Which was pretty much my plan. It works great for that. It even works for some things I honestly didn’t expect it to, like reading powerpoint presentations (I wasn’t surprised so much that it tried as that it succeeded).

Of course there are some annoying things about it. Many would (I assume) apply to any mobile touch-screen toy—typing is painful, mobile websites are missing bits I take for granted (e.g. formatting in gmail). Some (many? most?) android apps don’t seem to be available in the amazon appstore—that is probably changing even as I write.

But the single most annoying thing is something I had expected to be trivial. I had figured it would be trivial to download a free ebook—from Project Gutenberg, say—and start reading it immediately. Not so! You can download a .mobi file, and then it just sits there refusing to be read. The quickest way I’ve found to get the demmed things to import is to

  • open QuickOffice
  • Documents/Downloads
  • Hold your finger down on the file, and pick “Send” when the menu comes up
  • Email it to your kindle account
  • Wait a while. Wait some more.

Isn’t there a better way to do this? If not, for the love of heaven why?*

On the subject of free ebooks, I’d like to give a shoutout to someone calling herself Cthulhuchick for digitizing the complete works of H. P. Lovecraft and making them available in a nice free edition. Also for picking a great nom d’internet.

* Maybe I’ll answer my own question: Amazon has no interest in my reading stuff I didn’t buy from them.

Out of Bembo

November 15, 2011

I just got a copy of Out of Oz from the library, and the first thing I notice is that the typeface is back to the Truesdell of the original Wicked, rather than the always lovely but comparatively bourgeois and anodyne Bembo of Son of a Witch and A Lion Among Men. I hope this means the book is as weird as the first one was.

In Other News, Sun to Rise in East

November 15, 2011

In June 2010, Daniel Klein published a gratuitously silly piece in the Wall Street Journal’s gratuitously silly op-ed section, purporting to show that liberals are stupider than conservatives and libertarians, at least in terms of basic economics. This occasioned some amount of delight among conservatives and libertarians—vide Veronique de Rugy in the reliably obnoxious National Review Online (to be fair, not all conservative pundits fell for it). The “methodology” Klein relied on centered around a series of agree-or-disagree statements, things like “Third World workers working for American companies overseas are being exploited” and “Minimum wage laws raise unemployment,” most of which I would call at best “arguable,” all of which are pretty clearly politically charged in that they challenged various liberal positions, and all of whose “correct” answers were on the conservative/liberal sides of various issues. So, surprise! liberals did worse on the “do I agree with the conservative/liberaltarian author” test than conservatives and liberaltarian.1

To his (relative) credit, Klein eventually realized the problem, and he did a similar exercise with questions slanted the other way (“gun-control laws fail to reduce people’s access to guns”). To what should be no one’s surprise, this time he found that conservatives were the stupid ones. Read about it in the current Atlantic. Klein now thinks what both surveys demonstrate is “myside bias.” Really!

I feel a little sorry for Zeljka Buturovic, Klein’s (possibly more academic) collaborator. According to Klein’s Atlantic article, her goal wasn’t to prove anything about economic literacy, but rather to “[explore] the possibility that ideological differences stem more from differences in people’s beliefs about how the world works than from differences in their basic values.” There might be something to that, although I don’t know how to sort out the causality there (and I haven’t read the journal articles). Since she wasn’t the one who wrote either the WSJ or Atlantic articles, I don’t want to tar her with the same brush. Sorry, Zeljka!

Oh, another annoying thing. The questions and “correct” answers are reported in the most confusing way imaginable. From the Atlantic, citing the questions with the canonically incorrect answers in quotes:

Here’s what we came up with, again with the incorrect response in parentheses: a dollar means more to a poor person than it does to a rich person (disagree); making abortion illegal would increase the number of black-market abortions (disagree); legalizing drugs would give more wealth and power to street gangs and organized crime (agree); drug prohibition fails to reduce people’s access to drugs (agree); gun-control laws fail to reduce people’s access to guns (agree); by participating in the marketplace in the United States, immigrants reduce the economic well-being of American citizens (agree); …

So how many negatives to I have to wade through to figure out what an enlightened person thinks of gun control laws? I’m pretty sure Klein thinks they reduce access to guns (I think that too), but that’s more because that’s what you would ask if your goal is to prove conservatives are wrong than from trying to cancel out the “fail to” and the “incorrect response in parentheses.”


1. For what it’s worth, on the original set of questions I would probably have mostly given the “conservative” answers, but only if “it depends” wasn’t an option, and only if I had inferred the context that would be generally implied from the fact that someone was asking about that particular set of things and using that particular phrasing.


November 13, 2011

I’ve been looking at node.js, the server-side (more general than that, really) javascript execution environment. My gut reaction is that I like it–I like it a lot. But I think it will take some serious investigation to determine whether it’s ready for an industrial-strength application.

Now some details, aimed at node-n00bs such as myself. Anyone who would like to point out how badly I’ve gotten things wrong, feel free!

First, it’s important to know that node.js is architected to solve a specific problem, to wit, scalability in the presence of lots of concurrent access. The usual way something like apache/php handles concurrency is to spawn a thread for each server request. But threads have overhead, and there’s only so far you can push that before you have to buy more servers.

node.js has pretty much the opposite philosophy. The buzzwords you see are “asynchronous” and “event-driven” or just “evented”—its central element is a single-threaded event loop. But that doesn’t tell you much about why it’s a good idea. I found a much more revealing tagline here: “everything runs in parallel, except your code.”

The idea is that in a typical (non-trivial) server request most of the processing time is taken up in things like database or filesystem access, henceforth referred to generically (and not always completely correctly) as “IO.” Those are things that either don’t take a lot of CPU cycles, or at least are already in their own threads or processes. If the thread running those IO operations waits for them to complete, it will be sitting idle; in a single-threaded event loop that means it will block anything waiting for it. So in a single-threaded event loop, you don’t wait! IO operations in node.js don’t return their data directly; instead, they accept callbacks to process the results when they’re ready. Those callbacks are themselves processed in the event loop.

The callback functions themselves should all be lightweight, so that tens of thousands of them can be executed per second. They palm off all the hard work to “IO functions,” black boxes that may in turn add more callbacks. The node.js API, and good node.js plugin modules, are structured to make it positively difficult to do anything that blocks.

Here’s a “hello world” webserver, straight from the node.js front page, that responds to any request with, er, “hello world”:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, "");

The guts of that there–the argument to http.createServer–is the callback that gets called from the event loop whenever the server fires the “request” event (you don’t see the event loop yourself; you just add callbacks for events, and they are called from the event loop). It does the actual responding by calling methods on res, a ServerResponse object.

Of course a real response will be more complicated (starting with url-parsing, which I’ll ignore completely). Traditionally that might look something like

http.createServer(function (req, res) {
  var data = do_some_io_operation(req);
  var output = do_some_more_processing(data);
  res.writeHead(200, {'Content-Type': 'text/html'});
}).listen(1337, "");

But those two function calls, if they do anything IO-ish or otherwise nontrivial, are not kosher node.js. This should be something like this:

http.createServer(function (req, res) {
  do_some_io_operation(req, function(data) {
    do_some_more_processing(data, function(output) {
      res.writeHead(200, {'Content-Type': 'text/html'});
}).listen(1337, "");

What happens on a request is:

  • The handler calls do_some_io_operation, which registers a callback and fires off whatever the operation is. It–and the handler–return immediately, and processing can move on to anything that’s waiting in the event queue.
  • When the io operation completes, the first inner callback gets executed. That calls do_some_more_processing, which registers yet another callback, starts whatever it starts, and returns.
  • When THAT finishes, the inner callback finally takes all the data it now has available and finishes responding to the request.

Database access might look something like this (not real code, but it might be close, modulo error handling)

http.createServer(function (req, res) {
  dbase.connect('tcp://whateverdbase@localhost/whatever', function(connection) {
    var query = connection.query('SELECT * FROM some_table');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    query.on('row', function(row) {
      res.write('<p>' + row + '</p>');
    query.on('end', function(row) {
      res.end('Hello World\n');
}).listen(1337, "");

Connecting to the dbase is an IO operation, and since everything depends on that almost the whole response function is inside a callback. Setting up the query as I have it here doesn’t necessarily do anything immediately, so it does NOT need to take a callback, but that would be an alternative API. However, you do have to wait for the results of the query, so it gets callbacks for its “row” and “end” events.

I rather like this functional quasi-continuation-passing style of programming, mostly because I like finding out the abstruse theoretical concepts turn out to be useful for real. It might get a bit messy in real examples, though. At the very least I wonder if it would call for a different indentation style .

[And I have a “solution” for that. Or at least something that’s kept me happily occupied for the last couple of days. More on it later, if I ever get around to it.]

The fact that this is all in javascript has a few real advantages. Javascript is halfway to being a functional language, and is thus well suited to this style of programming. But it’s not Lisp or Haskell, so existing programmers don’t have to rewire their brains to use it. (I love Haskell, but I can’t imagine trying to find and manage a team to write a Real Product with it.) Indeed, any web programmer will already be fluent in javascript, and used to working with callbacks, if not quite to the pervasive level that node.js requires.

Using the same language on the client and server is a nice benefit, too. It makes it easy to share code between the two sides, something that can be useful (caveat: writing javascript that will work properly in a browser and inside node.js is NOT completely trivial, but it’s usually not that difficult either). And it’s nice for us programmers to avoid the annoying context switches between languages. Going from javascript to python, for example, I am forever forgetting to put quotes around dictionary keys.

And compared to other dynamic languages, javascript on google’s V8 engine, which node uses, is really fast. For “pure” stuff, just function calls and for loops and the like, it appears to be more in the C/C++ range than the Python/Ruby/php range.

Now for the downsides. Actually, for all I know there aren’t any prohibitive ones! But node.js is still relatively new, and I although I think the core is relatively stable the general ecosystem isn’t. There are lots and lots of modules for doing various things, but in this sort of open-source world it’s really difficult to know what you can trust. In the Perl world, for example, I’ve seen CPAN hailed as the greatest thing since sliced bread, but I’ve seen a lot of crap there, and sorting through it can be a real cost.

node.js itself is quite low-level, lower-level even than php. Someone needs to encapsulate even simple things like (e.g.) gathering get and especially post data into dictionaries of query values and data (not that that’s hard, but it does need to happen). There are some embryonic higher-level frameworks—Express looks very promising, and at least does that post-data processing—I am fairly certain there’s nothing anywhere near as mature and trustworthy as Ruby on Rails or Django (or, if you like that sort of thing).

And conceptually not everyone agrees that eventing is the way to handle concurrency. There are lots of partisans of Erlang and the aforementioned Haskell and even of traditional threading who beg to differ. I’m a bit out of my depth here, so can’t comment usefully.