Archive for January, 2008

Voter fraud (or suppression, whichever) in the Supreme Court

January 9, 2008

Lyle Denniston’s commentary on today’s oral argument in the Indiana voter ID case reminds me of Dahlia Lithwick’s take on yesterday’s lethal injection argument: neither the lawyers nor the Justices are willing to admit what the cases are really about. This sort of thing makes me cynical of the Supreme Court (and of our justice system in general): what sounds like high-minded legal theory is really a thin mask for a political brawl.

I expect the voter-suppressing Indianans to win 5-4, probably with Justice Kennedy writing a lofty and condescending opinion (à la Gonzales v. Carhart) in which he concludes that the “minor inconvenience to a small percentage of voters” is as nothing compared to the magisterial necessity of mercilessly rooting out poor urban Democratic fraudulent votes. Bah. I miss Sandra Day O’Connor.

[And just as I was about to hit “Publish,” I see Dahlia Lithwick’s witty analysis, full of her customary snark and bile. I ♥ you, Dahlia!]

UPDATE: My gal Dahlia and Emily Bazelon talk about this at Slate V. Sandy Levinson comments here.

After the NH primary

January 9, 2008

What pleases me most about yesterday’s NH Democratic primary is how wrong the polls were, and how confused the pundits are now.  I don’t think one can safely ignore borderline-offensive (and over-the-borderline-silly) theories of what went wrong; polls and pundits just suck is all the explanation I really need.

I am also pleased that there are real races in both parties, for pure entertainment value.  Politics is a lot easier to take if you look at it as entertainment.

For the record: I will happily vote for either Hillary or Obama, with a mild preference for Hillary (which could change).  I despise McCain less than I despise Romney (and the rest of the Republicans), so I guess I’m glad he won his primary.  OTOH, I think McCain would probably be the strongest Republican in the general election, so maybe I don’t want him to get the nomination.  OTOOH, that’s an “electability” argument, a sort of contrapositive to what got us Kerry last election (what were we thinking?), so I’ll settle on “glad McCain won.”

Obanamics–I like it

January 8, 2008

This pleases me. Excerpt:

Senator Obama’s ideas, on the other hand, draw heavily on behavioral economics, a left-leaning academic movement that has challenged traditional neoclassical economics over the last few decades. Behavioral economists consider an abiding faith in rationality to be wishful thinking. To Mr. Obama, a simpler program — one less likely to confuse people — is often a smarter program.

Spellchecking in python

January 7, 2008

FWIW, here’s the script I threw together to extract the wordlist I mentioned in the previous post:

#! /usr/bin/env python2.5

from __future__ import with_statement

import os
import re
import sys

from optparse import OptionParser

def worditer(wordsin, dict = None):
    r = re.compile(r'[#&]')
    if dict:
        cmd = 'aspell -a --lang=%s' % dict
    else:
        cmd = 'aspell -a'
    i, o = os.popen2(cmd)
    # skip first line
    o.readline()
    for w in wordsin:
        if w:
            i.write(w + '\n')
            i.flush()
            result = o.readline()
            if result and result != '\n':
                o.readline()
                if r.match(result):
                    # add the word for this session
                    i.write('@%s\n' % w)
                    yield w

def dowords(wordsin, outstr, dict):
    for w in worditer(wordsin, dict):
        outstr.write(w + '\n')

def filewordsiter(filenames):
    regex = re.compile(r'\W*')
    for fname in filenames:
        with open(fname) as f:
            for line in f:
                for w in regex.split(line):
                    yield w

def dofiles(filenames, outstream, dict):
    dowords(filewordsiter(filenames), outstream, dict)

def main():
    parser = OptionParser()
    parser.add_option('-d', '--dict', dest = 'dict',
                        help = 'Dictionary to use')
    parser.add_option('-o', '--out', dest = 'outfile',
                        help = 'Output file, stdout if none')
    options, filenames = parser.parse_args()
    if options.outfile:
        outstr = open(options.outfile, "w")
    else:
        outstr = sys.stdout
    dofiles(filenames, outstr, options.dict)

if __name__ == '__main__':
    main()

Precious Bane

January 7, 2008

<MILD SPOILER ALERT>

I’ve now read Precious Bane, and as I mentioned before, I’m shocked to find that I loved it. It’s not what I generally think of as my cup of tea. I like historical novels as much as the next guy, if not more, but I tend to prefer them less rustic and more ironic and subversive. At the very least I like a sea battle or two. Subjects like, oh, illiterate farmers destroyed by singleminded obsessive ambition, and their harelipped sisters finding love through adversity, tend not to interest me so much.

Obviously what makes PB so riveting is the writing. I have no idea whether Mary Webb got early-19th-century Shropshire dialect right, but it hardly matters, it’s completely convincing to early-21st-century me. PB sucks you in linguistically the way some of Anthony Burgess‘s books (A Clockwork Orange, A Dead Man in Deptford) do. [Good Lord, I just compared Mrs Webb to Anthony Burgess, and Precious Bane to A Clockwork Orange; have I lost my senses?]

Atmosphere is more than dialect, of course, and there’s much else right in PB‘s atmosphere. I particularly liked the almost-medieval worldview of the Shropshire yeomen, steeped equally in the Bible and in old country superstition.

Yes, I can see how the whole thing cries out for parody, but really, the best subjects for parody are often great in themselves.

Addendum number one: the BBC made a movie of Precious Bane starring what must be a very well cast young Clive Owen and Janet McTeer; unfortunately, despite having been shown on Masterpiece Theatre it seems not to be available here.

Addendum number two: I ran the text of PB through a spell-checker; the results (unfiltered for proper names, mild variant spellings, and the like, and with no thought given to contractions and the occasional funky diacritic) are here.

Django, AJAX, Scriptaculous

January 7, 2008

I looked a little at Scriptaculous this weekend.  I like it–it seems easy to use, and nice and concise.  It’s more focussed on glitzy effects (and I mean that in a good way) and less on widgets than the much larger DOJO; it also struck me (quite possibly wrongly, I’m just at the poking around stage) as easier to figure out and use.  Both effects and AJAX requests are wrapped pretty nicely; you have to write very little code to use them.

Unlike DOJO it does pollute the global js namespace a bit (as mentioned here); that might be annoying for people planning to use more of their own js than I’m ever likely to.

Here‘s what appears to be a nice scriptaculous-in-django tutorial, not that I’ve gone through it in any detail.

There seems to have been much debate in Django circles about whether to “include AJAX” in Django, which would (I assume) mean bundling a toolkit and providing a set of tags that wrap it, a la Rails and Scriptaculous.  The Django developers are reluctant to do that, not wanting to commit to a toolkit, and pointing out that there’s really not that much to wrap.  Now that I at least know what they’re talking about, I can sorta see their point.  Which doesn’t mean a some rails-like toolkit-wrapping tags wouldn’t be nice.
I’m working (in a slow and desultory fashion) on something where I might actually make some use of this stuff; so maybe I’ll be able to form an informed opinion in a few weeks.

Respect My Religion, Infidels

January 4, 2008

I’m with Eugene Volokh: this UN resolution (if that link doesn’t work, try this one) is… pretty bad. Professor Volokh doesn’t specifically mention a provision (point 10) I find particularly obnoxious:

[The General Assembly] Emphasizes that everyone has the right to freedom of expression, which should be exercised with responsibility and may therefore be subject to limitations as provided by law and necessary for respect of the rights or reputations of others, protection of national security or of public order, public health or morals and respect for religions and beliefs;

I for one do not want legal restrictions on my freedom of expression, especially for the protection of public morals. Fortunately, since this is just a UN General Assembly resolution mostly made of pap, I imagine it will have no actual effect.

Now I’m all for respecting other people’s religions–no, wait, I’m not! I want the right to make fun of other people’s religions, especially if they are, for example, Scientologists or Madonna-style pseudo-Kabbalists (and by all means, make fun of my religion too, if you can figure out what it is. I can’t!). What I am all for is allowing people to practice whatever religion they want, no matter how stupid, as long as it doesn’t involve violence and general infringement of people’s rights (what rights are those? TBD, but to include, I don’t know, the right not to be stoned to death for dishonoring your family by getting raped).

No one has a right not to be offended, about religion or anything else. Yes, the world would be a better place if everyone respected everyone else, and lived by the rule, “Don’t be a jerk.” But that’s not going to happen, and no amount of laws–let alone UN resolutions–will make it so. In the real world, we often can only make progress by pissing each other off, and that’s OK. If the UN really wants to make us all more understanding and tolerant of each other (not the real motivation behind this resolution, I think; see below), then it should encourage free and open discussion, not legislate (or whatever the UN does) what we can discuss.

Note that this resolution was pushed by Pervez Musharraf, perhaps in an effort to get some political mileage out of that Danish cartoon fiasco. I guess that didn’t work out so well.

George MacDonald Fraser, RIP

January 4, 2008

I am deeply saddened to learn that George MacDonald Fraser, author of the Flashman novels, has died.

The Flashman books are the best historical novels I’ve ever read (*). For those who don’t know, Flashman was the school bully in Tom Brown’s Schooldays, expelled from Rugby for drunkenness, much to the reader’s edification. The conceit of the Fraser’s books is that after being expelled, Flashman–still a bully, a coward, a cad, a compulsive womanizer, a liar, a cheat, and generally an all-around rotter–joined the army, and went on to be involved in every interesting event of the Victorian era, many of which (the charge of the Light Brigade, Little Bighorn, etc) he survived either by surrendering or running away. Needless to say he lived to a ripe old age, hailed as a hero: mostly because those who knew what he really was tended to end up dead.

The books are meticulously researched, extraordinarily well-written, and tremendously entertaining. Historical novels tend to be dry and stilted, even more so than contemporary novels. Writing believable dialog is difficult (at least, to judge from how few people do it well), and writing believable dialog in an approximation of another era’s idiom especially so. Fraser did it brilliantly. Very few authors can conjure up such period atmosphere so convincingly.

If Fraser became a little too sympathetic to Flashman as the series went on, well, that’s a quibble. The third, fourth, and fifth books are the best of the series (IMHO), but read ’em all.

Alas, now we’ll never know how Flashy lost the battle of Gettysburg for the Confederacy, or to what use Grant or Lee (it could have been either) put his striking resemblance to JEB Stuart.

(*) The very first historical novel, which runs through the Biblical books of I and II Samuel, is good too, but that’s another story.

Caucus Fever! The Aftermath

January 4, 2008

Huckabee and Obama–just as I would have predicted at, um, 4:30 or so yesterday afternoon. My thoughts and predictions:

  • Huckabee won’t get the nomination. The caucus results overstate his support and appeal–he’s got a strong base of fervent supporters, drawn from conservative evangelicals, who once fired up are more likely than just plain unexcited folks to turn up for a caucus. In a real election the evangelicals won’t be that overrepresented. Also, as I said, the shadowy cabal that runs the Republican party can’t abide Huckabee.
  • Not that I have much of a clue who will get it, though. I’d bet on Romney, mostly because as far as I can tell the Republican bosses hate McCain too. I’m still desperately trying to assume Giuliani doesn’t have a chance.
  • Also, Romney is still all chiseled and handsome, and that counts for a lot. Paula Poundstone, whom we saw a year and a bit ago, kinda nailed it:

    Paula: “How about Mitt Romney? Is he going to be President, or what? He’s so handsome and Presidential I think he’s going to make it.”

    Audience [a Paula Poundstone audience in Cambridge, MA, will contain very few Republicans. Lots of lesbians, though] : ” Noooo!”

    Paula: “No, no, really! We’re just not that smart! So you’re fucked.”

  • For the Democrats, geez, I don’t know. My money’s still on Hillary, with her steely nerve and political machine. Heck, this could help her, if she can exploit the “now I’m the plucky underdog” storyline (OK, a bit of a stretch for Hillary). It sorta depends on whether The Media decide to go a little easy now that she’s not invulnerable, or to kick her while she’s down.

Gosh, but The Onion has the most intelligent political commentary of any major media outlet (yes, those are all old, but still).

Django and AJAX

January 3, 2008

The other day I fiddled a tiny bit with AJAX in Django (is that a nerdly way to spend New Year’s Day, or what?). I have no use at all for it now, but (i) I might someday, and (ii) it’s cool.

Brief summary, for n00bs like me. The “usual” way a browser communicates with a server is to send HttpRequests, to which the server responds with some response, generally a whole page of HTML which the browser loads. Loading a whole page, though, is inefficient if the browser only wants to change its existing page a little, and doesn’t need much new data to do it. So the point of AJAX is to ask only for the new data, and update the page in place. Also, the browser doesn’t need to wait for the data to come back. Instead, it can supply a callback function to do the updating whenever the data is available.

For a better example than mine of how this works in Django, see this.

It turns out to be a lot simpler than I had expected–I think I’ve spent more time writing about it than actually doing it. By using a javascript toolkit you can avoid the more disgusting details. I used Dojo, although really for my quick test it didn’t matter at all; I just needed the “xhrGET” function, an equivalent of which would be in any toolkit.

[What, by the way, should one look for in a js toolkit? I have very little idea.]

As an exercise, I rewrote the search results page from my music website, so that the search results would be updated in place in the “onchange” method of the search box. That’s a pretty silly use of AJAX, actually, and I won’t be putting it in the real site, but it served as practice.

So what to do? The existing page is is rendered by a search_results view, which finds all the objects (of models Work, Author, and Collection) that match the search criteria (passed in GET data), and renders them to a template. To AJAXify that, I added an onchange handler to the search input, which sends and XML request to retrieve the new search results, supplying a callback to update the page. The URL those requests go to is just the existing search page’s URL, with “xhr” added to the GET data. I could have created a new URL/view for that, but the existing one already did almost exactly what this needs; see below. In a more typical case, I think the same strategy would also work, but more logic in the view would be dependent on the type of the request.

I had to do very little to the view. The AJAX request is expected to return just the “guts” of the page–the lists of matches–which can be done just by using a different template.

It may be more typical, and in some ways is preferable, for AJAX requests to return not html but data in json format. In this case, that would require javascript code to attach the data to the html, which would duplicate the existing template code in a nasty way. Maybe there is some clever way to avoid that code duplication…

Anyway, here’s the code:

def search_results(request):
    works = []
    people = []
    collections = []
    searchwords = ""
    try:
        searchwords = request.GET['searchwords']
        works = utils.searchfields(Work, searchwords)
        people = utils.searchfields(Author, searchwords)
        collections = utils.searchfields(Collection, searchwords)
    except KeyError:
        pass

    if request.has_key('xhr'):
        templatename = 'music/searchresults.html'
    else:
        templatename = 'music/search.html'

    return render_to_response(
            templatename,
            { 'searchwords' : searchwords,
              'works' : works,
              'people' : people,
              'collections' : collections })

The template needed more work. First, of course, it needs a js function to respond to fire off the AJAX request. That I cribbed from the DOJO documentation. Then, to avoid code duplication, I refactored the page a bit. I abstracted the html code that displays the search results out into its own tag, used in the view function above, and put the tag inside a new div. The tag is just a simple inclusion/context tag, using the same template as the view above used for xhr requests. On a normal HTTP request the tag is rendered using the data passed in from the view function; on an AJAX/xhr request the view function generates exactly the same html as the tag does initially (if given the same searchwords), and the callback shoves it into the div. And that’s pretty much it. The code:

{% extends "music/base.html" %}
{% block scripts %}
<script type="text/javascript"
    src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"></script%gt;
<script type="text/javascript">
    function updateajax() {
      dojo.xhrGet( {
        url: "?searchwords=" + dojo.byId("searchwords").value + ";xhr",
        handleAs: "text",

        timeout: 5000, // Time in milliseconds

        load: function(response, ioArgs) {
          dojo.byId("searchresults").innerHTML = response;
          return response;
        },

        error: function(response, ioArgs) {
          console.error("HTTP status code: ", ioArgs.xhr.status);
          return response;
          }
        });
      }
</script>
{% endblock %}

{% block content_search %}
{% simple_search '/music/search/' searchwords %}
{% endblock %}

{% block content %}
<h2>Search Results</h2>
<div>
    {% searchresults %}
</div>
<script type="text/javascript">
    dojo.byId("searchwords").onchange = updateajax
</script>
{% endblock %}

Some thoughts on What I Learned From This to follow.