<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:evan_tech</id>
  <title>evan_tech</title>
  <subtitle>Evan writes about technology</subtitle>
  <author>
    <name>Evan Martin</name>
  </author>
  <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/"/>
  <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom"/>
  <updated>2009-07-11T07:44:07Z</updated>
  <lj:journal userid="1095289" username="evan_tech" type="community"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://community.livejournal.com/evan_tech/data/atom" title="evan_tech"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:267433</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/267433.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=267433"/>
    <title>stallman and free software</title>
    <published>2009-07-11T07:44:07Z</published>
    <updated>2009-07-11T07:44:07Z</updated>
    <category term="free software"/>
    <content type="html">Criticisms or calls for respect of Richard Stallman seem to miss the real importance of the man.  People focus on gcc or emacs or the GNU stack, which have certainly been great works; or his more recent GNU/Linux posturing or interviews, which seem to me desperate and nearly pathetic; but these lose the greater context.&lt;br /&gt;&lt;br /&gt;I once read the argument that Chomsky -- whether you agree or disagree with his ideas -- serves a useful purpose in delimiting a boundary of the debate.  By being "radical", he allows for others to have positions that are more moderate versions of his without themselves getting pegged as radicals.  Stallman served the analogous role for free software at a time when it was just not done (the GNU announcement was 1983; Wikipedia says the first nearly free BSD came out in 1991, and the Debian Manifesto was 1993).  It'd be excessive to attribute Mozilla  or the Free Culture movement just one person but he definitely planted the seed.&lt;br /&gt;&lt;br /&gt;In part due to Stallman's influence, today we're not limited to arguing over the relatively minor difference of which megacorp (Microsoft? Apple? mine?) we'd like to license our computers from, but rather whether in a non-zero-sum game like software there are actually &lt;em&gt;moral&lt;/em&gt; arguments to be had about sharing beyond simply applying capitalism.&lt;br /&gt;&lt;br /&gt;Do I believe in or use the GPL?  No, not anymore.  But I do believe in free software, and still have a healthy respect for what came before.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:267075</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/267075.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=267075"/>
    <title>pubsubhubbub</title>
    <published>2009-07-10T01:51:50Z</published>
    <updated>2009-07-10T01:52:23Z</updated>
    <category term="go read"/>
    <content type="html">I'd like to draw your attention to bradfitz and Brett's &lt;a href="http://code.google.com/p/pubsubhubbub/"&gt;pubsubhubbub&lt;/a&gt;, a protocol for distributing real-time updates.&lt;br /&gt;&lt;br /&gt;It feels very bradfitzy to me: it is simple, decentralized, seems obvious in retrospect, and pays careful attention to an incremental migration path from existing technology (here, people who provide static feeds with the expectation of clients polling).&lt;br /&gt;&lt;br /&gt;The slides are brief and to the point.  Give 'em a glance.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:266982</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/266982.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=266982"/>
    <title>"operating system"</title>
    <published>2009-07-08T06:32:03Z</published>
    <updated>2009-07-08T06:33:01Z</updated>
    <category term="chromium"/>
    <content type="html">&lt;a href="http://googleblog.blogspot.com/2009/07/introducing-google-chrome-os.html"&gt;Suddenly&lt;/a&gt;, developing a browser for my marginal operating system seems more important, huh?&lt;br /&gt;&lt;br /&gt;(No, I can't answer any questions, except to note this future is different than the one &lt;a href="http://community.livejournal.com/evan_tech/266172.html"&gt;I imagined&lt;/a&gt;.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:266698</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/266698.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=266698"/>
    <title>sweetcode's fate</title>
    <published>2009-06-30T05:36:04Z</published>
    <updated>2009-06-30T05:38:24Z</updated>
    <content type="html">I finally cornered Dan -- the guy who ran &lt;a href="http://web.archive.org/web/*/http://sweetcode.org"&gt;sweetcode&lt;/a&gt; -- at a party and told him that I and many others mourn its passing.  He seemed surprised.&lt;br /&gt;&lt;br /&gt;He told me spent literally hours a day collecting the tidbits that made sweetcode what it was.  Since the purpose was to bring things to you that &lt;em&gt;weren't&lt;/em&gt; well-known, the normal avenues (hearing from a friend, seeing on a news site) weren't useful.  He had to give it up once he got a real job.&lt;br /&gt;&lt;br /&gt;We proceeded to discuss why current news aggregation approaches fail (what I'm interested in is &lt;em&gt;good things I haven't heard about before&lt;/em&gt;, regardless of the date, while news uses "happened recently" as an heuristic  for that), whether a platonic ideal of good exists for the sort of information sweetcode presented, and, y'know, Kaa's law and I got sad about sweetcode all over again.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:266383</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/266383.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=266383"/>
    <title>using git with svnsync</title>
    <published>2009-06-20T17:37:58Z</published>
    <updated>2009-06-20T17:37:58Z</updated>
    <category term="chromium"/>
    <category term="git"/>
    <content type="html">&lt;tt&gt;git.chromium.org&lt;/tt&gt; is a &lt;tt&gt;git-svn&lt;/tt&gt; mirror of the canonical SVN repository.  It works like this: the SVN server pushes out, with svnsync, a mirror to another machine.  That machine then has a cron job that runs git-svn against the local svnsync'd repo.  (Part of this design was so this mirror machine doesn't have any access to the writable repo.)&lt;br /&gt;&lt;br /&gt;By the way, there's info &lt;a href="http://code.google.com/p/chromium/wiki/UsingGit"&gt;on our wiki&lt;/a&gt; about how to set up git-svn such that you can fetch with a fast &lt;code&gt;git fetch&lt;/code&gt; from the mirror while still using the slow SVN server when it's time to commit.&lt;br /&gt;&lt;br /&gt;This has been working fine for quite a while but I noticed that occasionally (rarely) it was getting the proper commit data but the author wrong.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;$ echo $(git rev-list --author=chrome-bot origin | wc -l) $(git rev-list origin | wc -l)&lt;br /&gt;86 14624&lt;/tt&gt;&lt;br /&gt;Half a percent of commits.&lt;br /&gt;&lt;br /&gt;I asked around and the best guess is this surprising gotcha:  SVN commits aren't atomic.  :(&lt;br /&gt;The author metadata is a separate property of a commit and so it's possible for my mirror to grab a commit before the author data has synced over.&lt;br /&gt;&lt;br /&gt;What's the fix?  svnsync puts a lock in the repo before syncing.  Right now I check the lock.  To be correct I'd need to grab the svnsync lock myself while I'm doing my copy.  Another option is to rewind and try again whenever I see a bad commit get mirrored, but git-svn doesn't really like having history rewound without clobbering its metadata and I can't let it just rebuild its metadata from the commit history for complicated reasons outside the scope of this post.&lt;br /&gt;&lt;br /&gt;In summary, now I have this git repo that has the wrong authors in some commits.  Fixing it would require rebuilding history from the earliest instance of the problem, invalidating everyone else's copies.  I haven't done it since I'm not convinced it's too important.  Now that I look at the logs, it seems to have gotten much worse recently...</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:266172</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/266172.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=266172"/>
    <title>browser future</title>
    <published>2009-06-14T23:37:41Z</published>
    <updated>2009-06-15T01:07:11Z</updated>
    <content type="html">&lt;p&gt;Since I think about browsers all day here are some thoughts on the
future.  &lt;a name="cutid1"&gt;&lt;/a&gt;As always, I'm biased towards the Linux ecosystem, so in
some sense this post could be considered a response to the question
that came up recently in the Gnome world, which was roughly "What
next?  We've written all this GUI software but nobody really cares
anymore."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Background: HTML as the new display protocol&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;X11 is a remote display protocol.  It can do some pretty cool tricks
but it is also terrible for latent (aka "anything but a short wire")
connections, as nearly everything you do involves round trips.  To fix
this you want to be able to put more smarts into the low-latency piece
of hardware you're locally interacting with.  Many people have tried
to improve this but they've mostly failed.  (NX is pretty sweet but
there's still not enough smarts client-side.)&lt;/p&gt;

&lt;p&gt;In the meantime the world has evolved, for better or for worse, into a
remote display protocol called HTML.  (There are many interesting
reasons for that, but they are beyond the scope of this post.)  From
the X11 perspective, HTML involves a loadable DSL for interface
description, another for sandboxed execution, a well-understood and
cacheable networking protocol, and a install base larger than anything
before seen.  It's not the system anyone would have designed if we
were starting over but it's what we've got, and it continues to evolve
rapidly.  Any future platform that wants their own API will need to
support the web one anyway -- witness the annoyingness of developing for
Android/iPhone versus the the Palm phone as an example of embracing
this.&lt;/p&gt;

&lt;p&gt;Most of the software I use today runs in part on my machine and in
part on other peoples' machines, and cloud computing hyperbole aside I
expect this difference to only get blurrier.  I used to scoff at the
concept of "web applications" but consider that even relatively
mundane websites like LiveJournal really are software -- without LJ's
servers doing it for me it, the generation of my friends page would
necessarily happen in code on my machine.  One of the reasons I
decided to work on Chrome was when I realized the only windowed apps I
used anymore were terminals and browsers, and terminals more or less
dead-ended evolutionarily with the original xterm (I have much more to
say about that, actually, but it's for another time).&lt;/p&gt;

&lt;p&gt;Software like &lt;a href="http://code.google.com/webtoolkit/"&gt;GWT&lt;/a&gt; can be thought of as a toolkit (like GTK/Qt) in
this world; existing apps are written to something analagous to xcb but stuff like &lt;a href="http://www.youtube.com/watch?v=v_UyVmITiYQ"&gt;Wave&lt;/a&gt;
shows how things might work in the future.  (I don't especially want to write Java, but conceptually GWT is in the right place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thesis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So here's a thesis: Chrome comes with a few almost orthogonal goals
behind it -- tabs as processes, some novel* UI bits -- which are a
good step but can't go far enough due to the ecosystem it runs in.&lt;/p&gt;

&lt;p&gt;People still think of browsers as applications, but their modern use
is more as a runtime coupled with a random assortment of retrofitted
system-level services.  In part this is because there is no other
route for third-party application developers on the Other Platforms to
"upload" themselves into system-level services, which is where I think
the free software world has an opportunity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Processes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The elevation (or you could say "recognition") of web applications as
things your operating system can help schedule and protect from one
another is an old idea, and surely many browsers in the future will do
as we've done, but even in today's browsers the web processes are
still driven by a fragile "browser process" that is the single point
of failure.  For example, the network stack all lives in the
privileged frontend process, so any bug in the HTTP stack sidesteps
the sandboxing and takes out all tabs simultaneously.&lt;/p&gt;

&lt;p&gt;Why do networking bugs affect the UI?  Why do downloads stop when when
I close the last visible window?  Ultimately it's because you have a
hodgepodge of services (including high-privilege inputs like access to
the mouse and keyboard mixed with untrusted network inputs) in a
single place: the browser process.  Researchers have even called it
the "&lt;a href="http://www.google.com/search?q=browser+kernel"&gt;browser kernel&lt;/a&gt;", in fact.  (One sad reason for the single
monolithic process is so people don't complain more when they look at
the process list in task manager.  Another is that application vendors
like Google aren't allowed to provide system services, while OS
vendors like Microsoft aren't incented (or sometimes allowed) to integrate such services.)&lt;/p&gt;

&lt;p&gt;HTTP, viewed as system-wide remote display protocol, shouldn't be
implemented at the application level.  Why don't other tools like
&lt;code&gt;wget&lt;/code&gt; know how to use my cookies implicitly?  Or even simpler: my
proxy settings?  Cookies are credentials much like my user id; Unix
apps have a builtin for the former (&lt;code&gt;getuid()&lt;/code&gt;) but the web equivalent
is considered an application-level problem (&lt;code&gt;wget --load-cookies
~/.mozilla/firefox/mumble/etc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;MacOS and Windows have approached this problem by making HTTP fetching
and proxy settings system libraries; however, by virtue of being owned
by the OS distributor and closed-source it leaves you at the mercy of
their bugs and limitations.  (We measured an improvement in page-load
performance across our (opted-in-to-measurements) user
base when we switched off the Windows HTTP stack.)  And the ease of
integration is still too lacking; your favorite programming language
of the month is still poorly reimplementing HTTP without integrating
with my cookie store.&lt;/p&gt;

&lt;p&gt;What I'd like: a &lt;a href="http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs#.2Fnet"&gt;network service&lt;/a&gt; that would offload HTTP
interaction from applications.  Applications could hand off jobs like
"download this file" to the service, which would live beyond a given
browser session and allow me to centrally control bandwidth, caching,
proxies, limit/resue TCP connections to a particular host, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why do we have tabs?  Because window management has failed.  As one
commenter put it, on a modern machine we now have running native apps
in a strip of buttons across the bottom of the screen and a list of
running web apps in a strip of buttons across the top of a special
browser window.  On my laptop, with a tiling window manager, I have a
tab for each X11 app I'm running and then one tab containing the
Chrome tab strip within it.&lt;/p&gt;

&lt;p&gt;One spiffy Chrome feature is that when you tear a tab off a window you
can drag it to hot zones on the screen that will relayout your browser
windows side by side.  But these sorts of behaviors don't belong as
application behavior; they're only forced there because the window
management the system provides isn't adequate.  (I believe Windows 7
introduces some features like this.)&lt;/p&gt;

&lt;p&gt;What I'd like: It'd be a pretty small patch to Chrome to change the
call to "open in new tab": rather than opening a new tab, it'd open a
new window along with some extra hints (in the the window manager
sense) about the relationship between this new window and the one that
already exists.  (Browsers have interesting logic related to whether
new tabs appear rightmost or next to the current one, based on the
interaction you've done.)  My window manager is then responsible for
what it's always done: managing windows, and I get to use the existing
set of keys for swapping tabs, closing windows, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think the free software world is uniquely situated for these kinds of
changes, because only there do we have enough control over our
computers to be able to switch out fundamental pieces like these.  (I
tried and gave up on OS X due to frustrations over window management.)&lt;/p&gt;

&lt;p&gt;On the other hand, it's wasted breath to post about this since I don't
have time to implement any of it.  And I've been sitting on this post
for a month so I may as well publish it before I forget about it.&lt;/p&gt;

&lt;p&gt;* Before anyone starts on it: very few ideas are "new"; selection,
   combination, and execution are relevant.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:265805</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/265805.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=265805"/>
    <title>TODO</title>
    <published>2009-06-14T22:58:49Z</published>
    <updated>2009-06-14T22:58:49Z</updated>
    <content type="html">I am pathetically behind on email -- I see I've failed to ack patches to at least four of my projects, and I noticed another has been forked (a good thing! though I should probably just give them ownership).&lt;br /&gt;&lt;br /&gt;I suspect the fundamental problem is it's more fun to start something than finish it.  If you have been trying to get a hold of me, please re-ping me if I don't respond in a day or two.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:265610</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/265610.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=265610"/>
    <title>deb/rpm diffing tools</title>
    <published>2009-05-01T16:39:21Z</published>
    <updated>2009-05-01T16:39:21Z</updated>
    <category term="chromium"/>
    <category term="fourth wall"/>
    <category term="linux"/>
    <content type="html">Dear Linux hackers,&lt;br /&gt;&lt;br /&gt;Chrome tends to push minor updates (often security) pretty frequently.  We'd like to operate as a good member of the Linux ecosystem and just offer an apt/yum/etc. archive, but it seems unlikely to me that people will accept pulling a new 20mb binary package every few days.&lt;br /&gt;&lt;br /&gt;One idea I've idly had is that we could provide deltas, ideally ones that would reconstruct the normal packages you'd get if you went through the slow path.  For example, it could look at which package version you currently have installed, then combine the diff with the files you currently have installed to regenerate the files that would be in the newer package, and then construct the package from there and hand that off to dpkg/rpm.  I've heard about such tools existing but my Googling is failing me.  Do you have any links?  Do you have any friends I could ask?&lt;br /&gt;&lt;br /&gt;(For comparison, Firefox uses its own autoupdate system on Linux if you haven't installed it via a distributor, which is actually pretty reasonable when you consider the above.  But this also requires that the running binary have write access over its own files, which more or less means it needs to be installed in your home directory.  This is one of the reasons (aside from the fact Microsoft also recommends it) that Chrome on Windows installs into the Windows equivalent of your home directory.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:265443</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/265443.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=265443"/>
    <title>my very own flash vulnerability</title>
    <published>2009-05-01T15:17:46Z</published>
    <updated>2009-05-01T15:17:46Z</updated>
    <category term="hacking"/>
    <content type="html">&lt;a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-0521"&gt;CVE-2009-0521&lt;/a&gt; was actually me: I was poking around trying to make Flash not crash on Linux Chromium and noticed something wasn't quite right.  I had just thought it odd; Tavis, the reporter, recognized it as a security problem.&lt;br /&gt;&lt;br /&gt;(I really don't intend to post this much security-related stuff.  I believe it's just coincidental that I've had a lot lately.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:265155</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/265155.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=265155"/>
    <title>jaunty upgrade</title>
    <published>2009-04-29T16:59:44Z</published>
    <updated>2009-04-29T20:14:26Z</updated>
    <category term="free software"/>
    <category term="ubuntu"/>
    <content type="html">Upgraded to Ubuntu Jaunty.&lt;ul&gt;&lt;li&gt;X hung with garbage on the screen after rebooting.  Booted into "restore mode" (I forget the exact name), it gave me a text-based dialog where I could say X was broken.  Picking that made it spew --help output to the console and redisplay the dialog, but the fix held.&lt;/li&gt;&lt;li&gt;Have new notifications display.&lt;/li&gt;&lt;li&gt;Volume buttons &lt;a href="https://bugs.launchpad.net/ubuntu/+source/hotkey-setup/+bug/364127"&gt;no longer work&lt;/a&gt;. (I'm on an X60.)&lt;/li&gt;&lt;li&gt;Turning my wireless on via the hardware switch again makes it auto-find wireless access points.  This worked a few releases ago, then broke more recently, and now it's back to fixed.&lt;/li&gt;&lt;li&gt;Turning compositing on in X made everything very slow.  (Despite this being an Intel chipset?  Maybe related to above recovery problems?)&lt;/li&gt;&lt;li&gt;Suspend worked for me once or twice but it hasn't come back from suspend twice now so I guess it still doesn't work.  It hasn't worked for so long that waiting another year to see if the next release helps is familiar territory.&lt;/li&gt;&lt;li&gt;I still can't figure out how to tell gnome what window manager I want.  It's changed so many times over the years that none of the four methods I could find online worked.&lt;/li&gt;&lt;/ul&gt;I appreciate that releasing software this big is hard, and some of that is hardware issues, that part of the Linux social contract is that it's up to me to roll up my shirt sleeves and fix some of this stuff, etc.  So I'll summarize by just saying that for me personally, the upgrade was a waste of time.&lt;br /&gt;&lt;br /&gt;I'm considering doing a fresh reinstall in the hopes that I have cruft in &lt;code&gt;/etc/acpi&lt;/code&gt; or whatever to help with the suspend thing.  I was pretty excited the first time it came back from suspend.&lt;br /&gt;&lt;br /&gt;(PS: We set up a Fedora 11 box at work for testing Chromium against different compiler/libraries/etc.  They use ext4 by default and managed to get a nonbootably corrupt disk within a few days.  I'd suggest avoiding ext4 for now -- it's been fine since we reinstalled with ext3.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:264791</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/264791.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=264791"/>
    <title>freetype bugs</title>
    <published>2009-04-18T03:38:07Z</published>
    <updated>2009-04-18T03:38:46Z</updated>
    <category term="hacking"/>
    <content type="html">Since we were &lt;a href="http://community.livejournal.com/evan_tech/263952.html"&gt;just talking about font parsing bugs&lt;/a&gt;: &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=491384"&gt;four more integer overflows in FreeType&lt;/a&gt;.  Note the reporter (mentioned in the changelogs).  Also note, consistent with what &lt;span class='ljuser  ljuser-name_ajaxxx' lj:user='ajaxxx' style='white-space: nowrap;'&gt;&lt;a href='http://ajaxxx.livejournal.com/profile'&gt;&lt;img src='http://l-stat.livejournal.com/img/userinfo.gif' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;' /&gt;&lt;/a&gt;&lt;a href='http://ajaxxx.livejournal.com/'&gt;&lt;b&gt;ajaxxx&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; had remarked,  that the exploits against FreeType historically have not been against the bytecode but simpler parts like the metrics.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:264532</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/264532.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=264532"/>
    <title>presentation, teaching</title>
    <published>2009-04-17T23:03:22Z</published>
    <updated>2009-04-17T23:03:22Z</updated>
    <content type="html">I gave a presentation at work today.  I hope I didn't say too many things that were false.&lt;br /&gt;&lt;br /&gt;I found I became much more confident speaking in front of a group of people by TAing CS classes in college.  (The responsibility was typically to do about an hour a week before class as well as help with assignments.)  Not only do you learn material &lt;em&gt;really&lt;/em&gt; well when you have 30 people's worth of questions about it, I also had a good time of it.  Some of my favorite student feedback:&lt;ol&gt;&lt;li&gt;&lt;i&gt;in response to me telling my section that I do not require attendance and that I would fight requests to do any pop-quiz like behavior&lt;/i&gt;:&lt;br /&gt;"I love you."&lt;/li&gt;&lt;li&gt;&lt;i&gt;at the end of the semester, anonymous feedback&lt;/i&gt;:&lt;br /&gt;"He didn't shave a lot of the time."&lt;/li&gt;&lt;/ol&gt;I'm still pretty nervous when talking before a group, but during this last talk I even managed to not talk fast.&lt;br /&gt;&lt;br /&gt;I feel like I got lucky with the TAing thing; I wish it had been emphasized more in school.  Knowing what I know now I definitely would've traded off taking one fewer class for teaching once.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:264244</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/264244.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=264244"/>
    <title>security bugs</title>
    <published>2009-04-16T19:51:14Z</published>
    <updated>2009-04-16T19:51:14Z</updated>
    <category term="hacking"/>
    <content type="html">&lt;a href="http://seclists.org/fulldisclosure/2009/Apr/0129.html"&gt;http://seclists.org/fulldisclosure/2009/Apr/0129.html&lt;/a&gt;:&lt;blockquote&gt;VIII. DISCLOSURE TIMELINE &lt;br /&gt;06/28/2006 - Initial Contact &lt;br /&gt;06/29/2006 - PoC Requested &lt;br /&gt;06/29/2006 - PoC Sent &lt;br /&gt;10/05/2006 - Vendor Status Update &lt;br /&gt;01/24/2007 - Vendor Status Update &lt;br /&gt;02/12/2008 - Vendor Status Update &lt;br /&gt;03/31/2009 - CVE Assigned &lt;br /&gt;04/14/2009 - Coordinated Public Disclosure&lt;/blockquote&gt;That's a loooong time to sit on a bug.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:263952</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/263952.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=263952"/>
    <title>opentype condom</title>
    <published>2009-04-10T01:28:57Z</published>
    <updated>2009-04-10T01:28:57Z</updated>
    <category term="friends"/>
    <content type="html">&lt;a href="http://github.com/agl/otc/tree/master"&gt;http://github.com/agl/otc/tree/master&lt;/a&gt;:&lt;blockquote&gt;The CSS font-face property is great for web typography. Having to use images in order to get the correct typeface is a great sadness; one should be able to use vectors.&lt;br /&gt;&lt;br /&gt;However, the TrueType renderers on many platforms have never been part of the attack surface before and putting them on the front line is a scary proposition. Esp on platforms like Windows where it's a closed-source blob running with high privilege.&lt;br /&gt;&lt;br /&gt;Thus, the OpenType Condom (OTC) is designed to parse and serialise OpenType files, validating them and sanitising them as it goes. Most significantly, it removes hinting bytes from the files as it processes.&lt;/blockquote&gt;See also &lt;a href="http://neugierig.org/software/chromium/notes/2009/01/web-fonts.html"&gt;my discussion of the terror of web fonts&lt;/a&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:263681</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/263681.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=263681"/>
    <title>rolling back</title>
    <published>2009-04-08T17:38:07Z</published>
    <updated>2009-04-08T17:39:00Z</updated>
    <category term="git"/>
    <content type="html">&lt;code&gt;git revert &amp;lt;HASH&amp;gt;&lt;/code&gt; undoes a commit: it commits the inverse of the change done by that commit.  Concretely, it's just like a cherry-pick but with a backwards commit.  (In git's implementation, the two are implemented by the same file.)  How's it work?&lt;br /&gt;&lt;br /&gt;The conceptually-simplest way to roll back is to apply an inverse patch, something like:&lt;br /&gt;&lt;code&gt;git diff HASH HASH^ | patch&lt;/code&gt;&lt;br /&gt;but that does not work quite right in the presence of complicated operations, like deletes or adds.  And if there are conflicts it'd be nice if all of that conflicting information known to git, so it could assist with running merge tools.*&lt;br /&gt;&lt;br /&gt;Instead, consider a tree like this, where newer commits are on the right:&lt;br /&gt;&lt;code&gt;...---A---B---...---HEAD&lt;/code&gt;&lt;br /&gt;Suppose B is the commit we don't want anymore.&lt;br /&gt;&lt;br /&gt;Conceptually, you want to go from the state in B back to the state in A, but with all of the stuff in the middle up to HEAD still kept around.  Imagine you had created a new branch off of B that contained the state of the world in A, like this:&lt;pre&gt;A---B---...---HEAD
     \
      A&lt;/pre&gt;In that world, the rollback would just be merging that branch into HEAD.&lt;br /&gt;&lt;br /&gt;To do this without creating branches, you can just directly run the merge command, which takes a base branch and a set of other branches to merge.&lt;br /&gt;&lt;code&gt;git merge-recursive B -- HEAD A&lt;/code&gt;&lt;br /&gt;That says: "using B as the reference, merge as if HEAD and A were our interesting branches.".&lt;br /&gt;&lt;br /&gt;More commonly, you've got the hash of a single interesting commit so it's instead:&lt;br /&gt;&lt;code&gt;git merge-recursive H -- HEAD H^&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(Note: I'm not certain this is exactly correct; it depends on whether merge-recursive actually looks at the relationship between the branches for doing the merge.  I wonder if it may be more correct to use &lt;code&gt;git read-tree -m A B HEAD&lt;/code&gt; to read in all three trees into the index and then use &lt;code&gt;git merge-index&lt;/code&gt; but both of those are plumbing commands I don't fully understand.)&lt;br /&gt;&lt;br /&gt;* You could use &lt;code&gt;git apply&lt;/code&gt; instead of patch to help with that, but that is not the subject of this post.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:263426</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/263426.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=263426"/>
    <title>pre3d, a javascript 3d rendering engine</title>
    <published>2009-03-27T13:46:33Z</published>
    <updated>2009-03-27T13:46:33Z</updated>
    <category term="go read"/>
    <category term="free software"/>
    <content type="html">If you looked at &lt;a href="http://www.chromeexperiments.com/"&gt;Chrome Experiments&lt;/a&gt;, you might have seen &lt;a href="http://www.chromeexperiments.com/detail/monster/"&gt;Dean's Monster demo&lt;/a&gt;.  He's now published the &lt;a href="http://deanm.github.com/pre3d/"&gt;source for pre3d, his 3d engine for JavaScript&lt;/a&gt;.  It also does texture mapping, which I guess isn't used in any of the demos.  Since he works with the v8 team it's likely it will be pretty zippy compared to other approaches.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:263314</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/263314.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=263314"/>
    <title>startup time</title>
    <published>2009-03-05T16:51:39Z</published>
    <updated>2009-03-05T16:51:39Z</updated>
    <content type="html">A: Knock knock.&lt;br /&gt;B: Who's there?&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;A: Java!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(stolen from a reddit thread, though I don't remember the link)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:262983</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/262983.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=262983"/>
    <title>using control.applicative</title>
    <published>2009-02-28T22:35:27Z</published>
    <updated>2009-02-28T22:37:45Z</updated>
    <category term="haskell"/>
    <content type="html">&lt;p&gt;A post in three sections, each a step of evolution beyond the last.  Contrast with &lt;a href="http://www.willamette.edu/~fruehr/haskell/evolution.html"&gt;The Evolution of a Haskell Programmer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's a situation that comes up decently frequently.  Say you have some
monadic operation that gives you back a basic type.  Actually, let me
make it concrete so it's easier to follow.  Say you have a parsec parser
that parses an integer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_int :: Parser Int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Deep elsewhere in your code, you have some data type that you'd like to
stuff the result of that parse into.  E.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;data Expr = EInt Int | EString String  -- etc
p_expr :: Parser Expr
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the question is: how do you use &lt;code&gt;p_int&lt;/code&gt; within &lt;code&gt;p_expr&lt;/code&gt;, converting
the output?  Let's start with the obvious way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = do i &amp;lt;- p_int       -- parse an int
            return (EInt i)  -- wrap it in EInt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But it's so verbose!  You can shorten by going point-free with the
monad operators:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = p_int &amp;gt;&amp;gt;= return . EInt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But it always feels like golf to me when I see that in code; you may
as well just do the do-expression in one line in only seven more
characters:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = do x &amp;lt;- p_int; return (EInt x)
&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;
&lt;p&gt;On the other hand, it does feel redundant to give the integer a name
just to throw it away.  The more experienced Haskell hacker knows about &lt;code&gt;Control.Monad&lt;/code&gt;, which
provides some operators to work with monads.  Notably, there's
&lt;code&gt;liftM&lt;/code&gt; (parens added for clarity):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;liftM :: (Monad m) =&amp;gt; (a -&amp;gt; b) -&amp;gt; (m a -&amp;gt; m b)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That "lifts" a plain function to a function that works on monad values,
so our running example can become:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = liftM EInt p_int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can we do better?  From reading other code I picked up that the
prelude's &lt;code&gt;fmap&lt;/code&gt;, which is &lt;code&gt;map&lt;/code&gt; over the &lt;code&gt;Functor&lt;/code&gt; type class, is the
same as &lt;code&gt;liftM&lt;/code&gt; for a monad.  It feels a bit golfy but not so bad:
conceptually you're mapping &lt;code&gt;EInt&lt;/code&gt; over the result of the parse (but
only if it's succesful):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = fmap EInt p_Int
&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;
&lt;p&gt;But recently I gained a newfound understanding of
&lt;code&gt;Control.Applicative&lt;/code&gt; and found something better.  From their docs,
Applicative is "a structure intermediate between a functor and a
monad: it provides pure expressions and sequencing, but no binding."&lt;/p&gt;

&lt;p&gt;To keep it straight, here's a table with increasing abstraction as you
go downwards.  (Note the types of the columns aren't exactly the same,
but maybe it illustrates the point.)&lt;/p&gt;

&lt;table border="1"&gt;
&lt;tr&gt;&lt;th&gt;Typeclass&lt;/th&gt;&lt;th&gt;bring value in&lt;/th&gt;&lt;th&gt;primary operation&lt;/th&gt;&lt;th&gt;helpers&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Monad&lt;/td&gt;&lt;td&gt;&lt;tt&gt;return&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;tt&gt;&amp;gt;&amp;gt;=&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;tt&gt;liftM&lt;/tt&gt;, &lt;tt&gt;ap&lt;/tt&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Applicative&lt;/td&gt;&lt;td&gt;&lt;tt&gt;pure&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;tt&gt;&amp;lt;*&amp;gt;&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;tt&gt;&amp;lt;$&amp;gt;&lt;/tt&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Functor&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Conceptually, &lt;code&gt;Applicative&lt;/code&gt; lets you bring values in and combine values,
but doesn't let you get back at the values.  It suits the parser example
just fine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = pure EInt &amp;lt;*&amp;gt; p_int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That is, &lt;code&gt;pure&lt;/code&gt; brings the whole function into &lt;code&gt;Applicative&lt;/code&gt; and then

&lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt; is normal Haskell composition (normally just written with
whitespace or &lt;code&gt;$&lt;/code&gt;) within &lt;code&gt;Applicative&lt;/code&gt;.  But there's a helper
operator that's just for this sort of thing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(&amp;lt;$&amp;gt;) :: Functor f =&amp;gt; (a -&amp;gt; b) -&amp;gt; f (a -&amp;gt; b)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You'll note it's the same signature as &lt;code&gt;liftM&lt;/code&gt;, but in usage it's quite
clear:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;p_expr = EInt &amp;lt;$&amp;gt; p_int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The name is analagous to the &lt;code&gt;$&lt;/code&gt; operator but the brackets indicate
within Applicative.  You can read that as "apply &lt;code&gt;EInt&lt;/code&gt; to &lt;code&gt;p_int&lt;/code&gt;,
but within &lt;code&gt;Applicative&lt;/code&gt;".  Succinct and clear.&lt;/p&gt;

&lt;p&gt;The nice thing about &lt;code&gt;Applicative&lt;/code&gt; (and sort of the point of it) as
compared to monads is that you don't have this continual diving in and
out of the monad; you just lift everything in and then combine.
Contrast these two binary expressions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;add x y = x + y
normal_expression = add int_1 int_2
applicative_expr  = add &amp;lt;$&amp;gt; p_int &amp;lt;*&amp;gt; p_int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt; (equivalently &lt;code&gt;ap&lt;/code&gt; for monads) is there to let you to do further
composition on the right, all within &lt;code&gt;Applicative&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, note that all of this isn't specific to this parser problem;
you can use these functions just as well with other monads (like IO)
and also to other places involving functors:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(+1) &amp;lt;$&amp;gt; [1, 2, 3]
-- equivalent to map (+1) [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See also &lt;a href="http://en.wikibooks.org/wiki/Perl_6_Programming/Meta_Operators"&gt;Perl 6 meta-operators&lt;/a&gt;, which is this sort of thing done at the syntax level.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:262809</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/262809.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=262809"/>
    <title>seeking intern for chrome linux</title>
    <published>2009-02-26T01:54:46Z</published>
    <updated>2009-02-26T01:54:46Z</updated>
    <content type="html">&lt;a href="http://ponderer.org/summer_intern"&gt;Tony, my officemate, is looking for an intern&lt;/a&gt; to join us hacking on Chromium (Chrome) and Linux this summer.  Gtk hackers, X hackers, sandbox hackers, WebKit hackers, browser hackers especially welcome.  Strong C++ required, open source credz preferred.  Mail me at evan at chromium.org.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:262518</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/262518.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=262518"/>
    <title>mime sniffing</title>
    <published>2009-02-12T05:19:03Z</published>
    <updated>2009-02-12T05:22:18Z</updated>
    <content type="html">I post about (in part) the &lt;a href="http://neugierig.org/software/chromium/notes/2009/01/mime-sniffing.html"&gt;ancient IE mime sniffing hole over on Chromium Notes&lt;/a&gt;, and ten days later a &lt;a href="http://www.reddit.com/r/technology/comments/7wj9f/internet_explorer_executes_code_in_pictures/"&gt;600-reddit-vote article shows up&lt;/a&gt; on the same subject.  Coincidence?  You decide!&lt;br /&gt;&lt;br /&gt;(Unfortunately, the defenses proposed in the article are not sufficient for protecting your site.  I leave figuring out why to you.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:262357</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/262357.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=262357"/>
    <title>zippers</title>
    <published>2009-02-02T02:33:42Z</published>
    <updated>2009-02-02T02:33:42Z</updated>
    <category term="haskell"/>
    <content type="html">&lt;p&gt;&lt;a href="http://www.haskell.org/haskellwiki/Zipper"&gt;Zippers&lt;/a&gt;: there are plenty of docs, so here's some random
notes instead.  (The &lt;a href="http://www.st.cs.uni-sb.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf"&gt;original paper&lt;/a&gt; is in ML and quite
readable.)  Zippers are a fine example of the sort of progressive
generalization that people play with in Haskell; my &lt;a href="http://sigfpe.blogspot.com/"&gt;favorite blog at
the moment&lt;/a&gt; is filled with interesting math along those lines.&lt;/p&gt;

&lt;p&gt;I think the first zipper I encountered, before I knew the term, was in
reading a Brainfuck implementation written in O'Caml.  Brainfuck's
model is basically a Turing machine, where you have a focal point on
a tape and you can move around on the tape and do operations based on
the focal point.&lt;/p&gt;

&lt;p&gt;The question is: how do you represent this tape data structure with
immutable data structures?  If you use a list and an offset, examining
the focal point is O(n) (to walk down the list to the offset) and
modifications are O(n) (to rebuild the list).  The solution, which
seemed novel enough to me at the time that its obviousness now doesn't
dissuade me from describing it for you, is to represent the tape as
three parts: cells to the left of you, your current cell, and cells
to the right.  The trick is that on both sides, the nearest cell is at
the front of the list; in some sense the left cell list is backwards.&lt;/p&gt;

&lt;p&gt;Now stepping by one cell is O(1): you just pop the top of the relevant
side list off and stuff your previous focal point as the new top on
the other side.  What I didn't fully appreciate at the time is that
this is also gentle with memory.  You're only popping/adding from the
front of a list, so the remainder of the cell lists are constant and
shared.  Each step is destructuring one cons cell and creating one new
one.&lt;/p&gt;

&lt;p&gt;So whatever, you might say.  You have jump through hoops to get
functional data structures and it's a waste of time.  Here's where
it hopefully gets interesting or at least more complicated.&lt;/p&gt;

&lt;p&gt;This idea, called a zipper, can be generalized: your cursor is a pair of
the current point along with context representing the remainder of the
data structure arranged such that nearby movements are small steps.
(In the Brainfuck example the context is the cell lists.)&lt;/p&gt;

&lt;p&gt;Most examples discuss movement on a tree.  Your current point is an
unmodified subtree, and your context is a pointer to the subtree's
parent along with the rest of the parent's children (the children
other than your current point).  &lt;a href="http://en.wikibooks.org/wiki/Haskell/Zippers"&gt;This otherwise kind of useless
Wikibook article&lt;/a&gt; has a nice picture about halfway down
visualizing it, where your pointer kinda "grabs" the tree and "lifts
it up" so it hangs around that point, which is a nice structural
metaphor.  In terms of memory, it's sorta like the list zipper in that
most of the tree is left alone and can be shared during movement; all
the zipper added is a reversed path back to the root.&lt;/p&gt;

&lt;p&gt;What struck me recently is that with a tree zipper you've stepped around
the problem of parent pointers in a tree while still allowing movement
in any direction.  The zipper here is effectively just building a
stack of parent pointers as you walk down the tree and popping the
stack to walk up, which is the sort of trick you've likely used
(or at least could have invented) in an
imperative programming context to conserve memory while allowing arbitrary tree
navigation.&lt;/p&gt;

&lt;p&gt;This is again all nice enough -- two related concepts that do similar
tricks with data structures -- except it can be generalized even
further.  A zipper can be defined for any data structure
systematically by computing the derivative (in the calculus sense,
kinda) of its data type!  What's the use?  Even the guy who discovered
it isn't sure: "While this connection seems unlikely to be a mere
coincidence, it is perhaps surprising to find a use for the laws of
the infinitesimal calculus in such a discrete setting."  More research
is warranted, I guess.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:262074</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/262074.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=262074"/>
    <title>inbox out of control</title>
    <published>2009-01-31T18:03:58Z</published>
    <updated>2009-01-31T18:03:58Z</updated>
    <content type="html">I am critically behind on my inbox, to the point where I believe there are five patches for various bits of software of mine hidden under the mass of email.&lt;br /&gt;&lt;br /&gt;For example: someone took my &lt;a href="http://neugierig.org/software/arabic/"&gt;Arabic transliteration JS thingy&lt;/a&gt; and made &lt;a href="http://www.node.pk/urdu/"&gt;an equivalent system for Urdu&lt;/a&gt;.  He politely had asked me about the license of my code and that question sat unanswered for weeks.&lt;br /&gt;&lt;br /&gt;Today I solve this.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:261649</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/261649.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=261649"/>
    <title>adventures in search optimization</title>
    <published>2009-01-25T04:11:33Z</published>
    <updated>2009-01-25T04:37:37Z</updated>
    <category term="git"/>
    <content type="html">At work we heavily use a tool for rapidly searching the codebase with regexps.  (I believe it's the same engine behind Google Code Search.)  But it isn't as helpful when your index is stale, which happens more often when your code churns rapidly (as Chromium does -- ~50 commits a day by us and ~50 more commits a day from WebKit).  I had been idly thinking about making some sort of full-text indexing system for working with my own code that was smart about watching for file modifications, building generations of indexes, etc.  It sounded like a fun project.&lt;br /&gt;&lt;br /&gt;Then I just chatted with Matt a bit about it and realized I was thinking about it wrong.  His first thought was that there shouldn't be that much data involved here and I should be able to just do a brute-force scan.&lt;br /&gt;&lt;br /&gt;But there's too much data, I protested.  To start with, &lt;tt&gt;find&lt;/tt&gt; across my tree with a cold disk takes tens of seconds to even enumerate all the files (over 200,000).  And Visual Studio's "find in files" is also super-slow, supporting my intuition.  But upon second glance that number is immediately suspicious as way too many files -- because it's including all sorts of files I don't care about!  As far as source goes it's only around 10,000 source files and under 50mb of data.&lt;br /&gt;&lt;br /&gt;So what's faster?  Git knows which files are in the repo.  (A great trick for finding files by name more quickly than using &lt;tt&gt;find&lt;/tt&gt; is &lt;tt&gt;git ls-files &amp;lt;pattern&amp;gt;&lt;/tt&gt;.)  Then I just want to limit my grep to source files.  I had thought &lt;tt&gt;git grep&lt;/tt&gt; didn't let you specify a filename pattern (which is why I was fooling around with find and grep in the first place) but after rereading the source I see I overlooked it in the man page; something like &lt;tt&gt;git grep foo -- *.cc *.h&lt;/tt&gt; does exactly what I wanted.  It's easy enough to stuff in a one-liner shell script so &lt;tt&gt;git gs foo&lt;/tt&gt; quickly searches my code.&lt;br /&gt;&lt;br /&gt;On a cold disk (after flushing the cache), it takes ~11s on my laptop.  But as soon as the disk is warm (and it's only 50mb of data to keep around anyway) it's 0.35s, which is plenty fast.  I note that whoever wrote the grep support for git was clever enough to shell out to grep (unless your combination of passed-in flags prevents it), because &lt;a href="http://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/"&gt;you are unlikely to beat grep&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(PS/update: it turns out that M-x vc-git-grep hooks all this into the existing Emacs grep support, complete with shorthand for specifying "file extensions that look like C++ source or headers".  I am humbled.)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:261466</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/261466.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=261466"/>
    <title>megaupload captcha</title>
    <published>2009-01-24T20:29:46Z</published>
    <updated>2009-01-24T20:29:46Z</updated>
    <category term="project"/>
    <content type="html">Someone make a &lt;a href="http://ejohn.org/blog/ocr-and-neural-nets-in-javascript/"&gt;Javascript-based captcha cracker for megaupload&lt;/a&gt;.  It's strange to see those captchas again because I idly myself wrote a captcha-cracker for the same site.  I don't think I ever announced it here because there wasn't any real application for it; I was just playing around.&lt;br /&gt;&lt;br /&gt;According to &lt;a href="http://neugierig.org/software/darcs/browse/?r=yoink;a=summary"&gt;the repo history&lt;/a&gt; it was two years ago, and the &lt;a href="http://neugierig.org/software/darcs/browse/?r=yoink;a=headblob;f=/notes"&gt;notes&lt;/a&gt; indicate how far I went before losing interest.  As I recall their captcha image was quite weak, but you also needed to be able to interpret Javascript and &lt;a href="http://neugierig.org/software/darcs/browse/?r=yoink;a=headblob;f=/jsinterp/fakedom.js"&gt;fake out the DOM&lt;/a&gt; to skip a timed countdown.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:evan_tech:261214</id>
    <author>
      <email>evan@livejournal.com</email>
      <name>Evan Martin</name>
    </author>
    <lj:poster user="evan" userid="1571"/>
    <link rel="alternate" type="text/html" href="http://community.livejournal.com/evan_tech/261214.html"/>
    <link rel="self" type="text/xml" href="http://community.livejournal.com/evan_tech/data/atom/?itemid=261214"/>
    <title>emacs</title>
    <published>2009-01-23T04:47:07Z</published>
    <updated>2009-01-23T05:49:51Z</updated>
    <category term="fourth wall"/>
    <content type="html">I've been using vim for a very long time -- over ten years -- but over those years I've envied more and more the way emacs integrates other software.  So a few months ago I switched.  I don't see it as the religious issue that many people make it out to be, so the only real hurdle was taking the time to read the manuals.&lt;br /&gt;&lt;br /&gt;It turns out switching is surprisingly not that painful; any competent user of a Unix is already familiar with the basic emacs keybindings because shells use them too.  People have historically complained about emacs being bloated but it was bloated on computers of the 80s; it's tiny compared to even simple Java or web-based software today.  I have found my mind has "vi mode" and "other editor" mode, so I keep hitting emacs keybindings in Firefox or Visual Studio.&lt;br /&gt;&lt;br /&gt;For comparison (eclipse/emulator are the Android development tools):&lt;pre&gt; 8916 martine   20   0  717m 181m  33m S    0  9.0   0:57.65 eclipse
 9005 martine   20   0  280m 137m  23m S    0  6.8   1:06.25 firefox
 9788 martine   20   0  162m 115m 5416 S    2  5.7   2:13.31 emulator
11260 martine   20   0 32632  19m 9068 S    0  1.0   0:00.52 emacs&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What I like:&lt;ul&gt;&lt;li&gt;ediff is great.  I had previously used meld but meld is buggy and underpowered.&lt;/li&gt;&lt;li&gt;I use the Python, Haskell, and R integration all the time.  It's so convenient to have a REPL that works within your editor.  It's pretty much the reason I switched.  Type some Haskell code, hit C-C C-l, and your cursor is in a buffer with your code loaded.&lt;/li&gt;&lt;li&gt;The buffer management concept makes a lot of sense.  The way you switch between buffers with C-x b matches my workflow well.&lt;/li&gt;&lt;li&gt;&lt;a href="http://zagadka.vm.bytemark.co.uk/magit/"&gt;magit&lt;/a&gt; made my work on improving the git UI effectively obsolete.  (But it's really slow for some reason...)&lt;/li&gt;&lt;li&gt;"C-h a" is a useful way to interface with a huge interface surface&lt;/li&gt;&lt;li&gt;The vim scripting language is an abomination and I refused to learn it.  I've already made a tiny function in emacs lisp for composing entries for &lt;a href="http://neugierig.org/software/chromium/notes/"&gt;my blog software&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;What I don't like:&lt;ul&gt;&lt;li&gt;I believe the basic editing key bindings are just not the way I operate.  I made a point of &lt;em&gt;not&lt;/em&gt; using viper because it produces the uncanny valley effect, where it's close enough to vi that you get frustrated by esoteric keys not working, and instead forced myself to learn the emacs way before I start changing things.  But now I'm again considering trying viper.&lt;/li&gt;&lt;li&gt;Undo.  I get how it's intended to work but it never quite feels right.  Could be learned through more experience, maybe.&lt;/li&gt;&lt;li&gt;I feel like the different programing modes have different keys do needlessly different things.  I understand that a unified UI is contrary to the point of a software system defined by its customizability, but that makes it hard for me to get an intuition for the natural way things ought to work.  For example, why doesn't C-h m show me the Haskell-mode specific keybindings while it does in other modes?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I get the feeling there are tons of customization tricks that people use that I'm missing.  So please, tell me your emacs tips!&lt;br /&gt;&lt;br /&gt;One of the big things I've been wanting is making it so when I load up code under the Chromium directory my editor configures itself with the appropriate defaults (e.g., .h files are C++, and M-x compile should run SCons from the proper directory).  I saw some project local variables scripts on the emacs wiki but I couldn't get them to work right, probably because I'm missing understanding.</content>
  </entry>
</feed>
