Wednesday, April 22, 2009

Are you sure you want to navigate away from this page?

Scenario: you've been tasked with creating a simple web-based time-sheet application, so employees can log what percentage of their time is devoted to which project. Now, this hardly qualifies as "Bioinformatics," a domain claimed by both your job title and personal aspirations, but it's a small company and they pay your rent.

So you build the little beasty, and your cube-neighbor sits down to fill out a time-sheet. She spends 7 minutes selecting options and punching in percentages, and then realizes she wants to trim one field from 15% to 10%, clicks her mouse 4 pixels too far to the right putting the page, and not the text input, into focus, and hits Backspace -- equivalent to the back button.

There go her 7 tedious minutes of form-filling -- this app isn't sophisticated enough to autosave a draft in real-time, after all.

Enter the onbeforeunload function.

I've borrowed from this guy a bit, but here's the code:
var confirm_exit = true;

window.onbeforeunload = function() {
if( confirm_exit )
return "";
return; };

$(document).ready( function() {
$("#id_theform").submit( function() { confirm_exit = false; } );
} );
Originally, I'd planned to skip the ugly global variable and simply re-bind the onbeforeunload function, but apparently you can't rebind like that.

Friday, April 10, 2009

A Beginner's Guide to Hating iMovie '08

Thank you, Apple. This is pretty much my first experience editing footage into a "movie," and with iMovie '08, you've made the process slow, painful, and constrained. What's more, I was lucky enough to get my computer weeks before the release of iMovie '09, so any of your stunning omissions fixed in the subsequent version will cost me $100. No thanks.

First off, titles. Adding chapter titles is a pretty common use for iMovie, I would think, but clips cut from one Project and pasted in another are stripped of their title. Thanks.

Oh, but wait: "chapter titles?" What's a chapter? iMovie isn't really meant to create movies for later burning onto a DVD -- who would ever want to distribute a DVD? So very 2003! The only way I've found to separate footage into chapters for iDVD is to put each chapter into its own Project. Annoying.

Thursday, April 9, 2009

The perils of laziness

I've begun cargo culting my way into Haskell, in the hopes that I'll eventually grasp such mathematical mysteries as anamorphisms. In the mean time, I'd like to write some code that actually works.

To this end, I've written a program to digest the C. elegans transcriptome in silico, then check the resulting fragments against data from a mass spectroscopy experiment (Multidimensional Protein Identification Technology --"MudPIT"--if you're curious). I use regular expressions to break up the protein sequences, store the fragments in a big Data.Map, and then test my MudPIT fragments against the Map.

I've greatly simplified my function to be a simple list-to-map conversion -- which would be stupid, since Data.Mat.fromList does this quite well -- but the real function involves plenty of off-topic complexity, so here's the svelt form:
  add_frags (i:l) m =
let m' = M.insert i () m in
add_frags l $! m'
add_frags [] m = m
The important part is the $!, in bold. Given some function f and parameter x, f $! x is equivalent to x `seq` f x; the seq function, meanwhile, forces the evaluation of the first thunk. So f $! x applies f to x AFTER x HAS BEEN EVALUATED.

Without that forced evaluation, ghc will simply add more thunks to the stack until the stack is blown ... hours after the run has begun. You can pretty easily imagine this as a series of substitutions, which is exactly what we're talking about:
  import qualified Data.Map as M
m = M.empty
add_frags ["ACDEF","GHI","KLMNO","PQRST",...] m
-> M.insert "ABCDEF" () (add_frags ["GHI","KLMNO","PQRST",...] m)
-> M.insert "ABCDEF" () (M.insert "GHI" () (add_frags ["KLMNO","PQRST",...] m))
And off the stack grows, until pop.