Now I have two problems

I'm converting one of my websites from Ruby on Rails to Clojure in my spare time. I stupidly put a bunch of RoR-style links inline into certain bits of plaintext content, so in my DB there are a bunch of text fields with <%= link_to ... %> in the middle.

It was easy to fix with a regex though:

(defn clean [txt]
  (re-gsub #"<%=\s*link_to\s+(\"[^\"]+\"|'[^']+')\s*(?:,\s*'([^']+)'\s*)?(?:,\s*image_path\(['\"]([^'\"]+)['\"]\)\s*)?(?:,\s*:controller\s*=>\s*(?::(\S+)|['\"]([^\"']+)['\"])\s*)?(?:,\s*:action\s*=>\s*(?::(\S+)|['\"]([^\"']+)['\"])\s*)?(?:,\s*:id\s*=>\s*(?:(\d+)|:(\S+)|['\"]([^\"']+)['\"])\s*)?\s*%>"
           (fn [[_ s & parts]] (let [href (str-join "/" (filter identity parts))]
                           (str "<a href=\"/" href "\">" (re-gsub #"^[\"']|[\"']$" "" s) "</a>")))
           txt))

And by easy, I mean not easy.

Note to self, try something other than a regex next time.

Note to self, don't bury some framework's funky-syntax DSL in the middle of plaintext content. Next time use HTML or do the conversion from DSL to HTML early rather than late.

Silly how two years ago I thought I'd be using Ruby for that site forever.

September 25, 2009 @ 4:02 PM PDT
Cateogory: Programming

Force Google Chromium to have a normal title bar in KDE

KDE is awesome largely because KWin is awesome. If I had to name one reason I gave up using Gnome and moved to KDE, it'd be KWin.

Some programs (for example, Songbird, aTunes, Google Chrom(e|ium)) try to manage their own windows in silly ways like hiding their title bars and window borders, or fiddling with how they appear in pagers or task managers / application lists, or trying to manage their own sizes and positions. KWin lets you override and force sane preferences upon such programs.

Chromium for Linux is nice enough to give you an option to "Use system title bar and borders" if you right-click the top. But this only changes how Chrome looks; it doesn't make the KWin title bar and borders appear.

Why would you want KWin title bar and borders? Because by default, Chromium's self-managed title bar only gives you Windowsy options like minimize/maximize/close. It doesn't give you Linuxy options like double-clicking the title bar to window-shade the window, or right-clicking the title bar to get the KDE menu to send it between desktops or make it Always on Top, and such goodness. If I wanted gimped up window management I'd go use Windows 95.

September 18, 2009 @ 6:58 PM PDT
Cateogory: Linux

No accounting for taste

Somehow my post from yesterday about Church numerals in Clojure hit the front page of Reddit briefly. I don't understand why. It wasn't that interesting. It was an interesting topic, but there are other sites with better information about the topic. (Even Wikipedia has more/better info. This one is nice too in spite of being C#.)

I think it's because it was submitted to Reddit with a vague and inflammatory title about brain explosions, and people click links without thinking too much about what they're doing. Even programmers do, I guess.

My blog got around 14,000 visits yesterday, which is not much these days, but a lot by the standards of my tiny blog. If you added up everyone I ever had a conversation with in real life, would it be 14,000 people? I doubt it. Kind of crazy.

I run three websites out of one JVM/Clojure instance on my lowly VPS server and it didn't crash, so I'm kind of happy about that. I've crashed from lesser loads than that in the past. So either my programming is getting better, or my new host is better than my old one, or it was dumb luck.

All of my data is persisted in Tokyo Cabinet nowadays but mostly it's read from caches in Clojure refs, so maybe that helped a bit too. Maybe. Who knows? I know nothing about scaling websites. Slashdot would reduce this site to a puddle of goo.

In any case I appreciate the opportunity to blather about things and have people listen.

September 17, 2009 @ 5:20 PM PDT
Cateogory: Rants

Church Numerals in Clojure

Church Numerals are a way of encoding natural numbers using lambda expressions. A number n is represented by a function that composes another function f around its argument x, n times. So:

0 ≡ λf.λx. x
1 ≡ λf.λx. f x
2 ≡ λf.λx. f (f x)
...

These can be implemented very easily in Lisps and other languages with first-class functions. In Clojure, this would be:

0 ≡ (fn [f] (fn [x] x))
1 ≡ (fn [f] (fn [x] (f x)))
2 ≡ (fn [f] (fn [x] (f (f x))))
...

The insane thing is that you can do arithmetic on these things using nothing but more anonymous functions. It's lambdas all the way down.

Once you understand this, your brain will explode, and hopefully little bits of it will land next to the remnants of my own brain to keep it company.

So based on the Wikipedia article, here are some functions that convert numbers to and from Church encoding, and then some functions to do basic arithmetic on Church numerals. I understand this down to exp (via lots of pencil and paper expansions) but I gave up understanding at pred.

(defn church
  "Convert a natural number to a Church numeral."
  [n]
  (loop [n n, acc (fn [f] (fn [x] x))]
    (if (zero? n)
      acc
      (recur (dec n)
             (fn [f]
               (fn [x]
                 (f ((acc f) x))))))))

(defn unchurch
  "Convert a Church numeral to a plain integer."
  [n]
  ((n inc) 0))


(def plus
     (fn [m]
       (fn [n]
         (fn [f]
           (fn [x]
             ((m f) ((n f) x)))))))

(def mult 
     (fn [m]
       (fn [n]
         (fn [f]
          (n (m f))))))

(def exp
     (fn [m]
       (fn [n]
         (n m))))

(defn pred [n]
  (fn [f]
    (fn [x]
      (((n (fn [g]
             (fn [h]
               (h (g f)))))
        (fn [u] x))
       (fn [u] u)))))

(def sub
     (fn [m]
       (fn [n]
         ((n pred) m))))

(def is-zero?
     (fn [n]
       ((n (fn [x] 'FALSE)) 'TRUE)))

And this somehow actually works:

user> (unchurch (fn [f] (fn [x] (f (f (f (f (f (f (f x))))))))))
7
user> (unchurch (church 7))
7
user> (unchurch ((plus (church 2)) (church 3)))
5
user> (unchurch ((mult (church 2)) (church 3)))
6
user> (unchurch ((exp (church 2)) (church 3)))
8
user> (unchurch ((sub (church 7)) (church 3)))
4
user> (is-zero? (church 0))
TRUE
user> (is-zero? (church 7))
FALSE

This is the kind of thing I wish I'd studied more in college. I covered some cool stuff, some small amount of theory of computation and whatnot, but not nearly enough of this. Not enough functional programming, not enough Lispy goodness.

A lot of people say all programmers should learn assembler language so you understand what's happening at a low level. But shouldn't it be just as important to learn lambda calculus? It's another kind of low level, a very important one at that.

September 15, 2009 @ 7:14 PM PDT
Cateogory: Programming

Flash: I hate you

If there's a version of Flash on Linux that does not crash my browser multiple times per hour, I'd love to know where I can get it.

When I want to browse more than 2 or 3 movies on Youtube at once, I switch over to Opera, because at least when Flash crashes in Opera, it just turns into a black box and Opera keeps going. Firefox on the other hand shuts down entirely.

But sometimes Flash even manages to crash my X server. That takes real talent. Flash cannot possibly die fast enough. We've been dealing with this atrocity for over a decade now.

September 12, 2009 @ 8:16 AM PDT
Cateogory: Linux

Plamsa + Ruby = Ouch

I wrote my first KDE4 plasmoid the other day. I can't release it because it's essentially a clone of something you aren't allowed to copy (maybe I can replace him with a penguin and release it that way though).

But I need to rewrite it first anyways, because I did it using the Ruby bindings for Qt4 and Plasma, and wow it's painful. It has a 50/50 shot of even initializing at any given point. When it does initialize, it has about a 1 on 8 chance of immediately crashing Plasma. And some things I just can't get to work at all, e.g. setting a default size or resizing the applet programmatically; X-Plasma-DefaultSize in the metadata is supposed to do it but it does nothing. And it's not just my system (using KDE 4.3), because I tried it on a Kubuntu machine using stable KDE 4.2 and had the same problems.

The other snag is that the documentation of the Plasma API is buried so deep on the KDE site that I don't even know how I found it. Here it is for those who care (and for my own future reference). I hit lots of dead links on the KDE site on the way there.

Next step is to rewrite the plasmoid in Python or C++ I guess.

September 08, 2009 @ 4:34 PM PDT
Cateogory: Programming
Tags: KDE, Ruby, Plasma

Review: Coders at Work

Recently I received a preview copy of Peter Seibel's newest book, Coders at Work.

This is a wonderful book if you are a programmer and care at all about the art, craft, and/or science of programming. If there is any wisdom to be had in this fledgling field of ours, this book contains buckets of it.

The book consists entirely of long interviews with some big names in the world of programming: Donald Knuth, Ken Thompson, Jamie Zawinski, Guy Steele, Peter Norvig, the list goes on. There are also some names I wasn't quite so familiar with (but maybe should have been), like Brad Fitzpatrick, the inventor of Livejournal.

But everyone interviewed for the book has produced some grand, successful project in their time. These are tried-and-true, battle-tested programmers and in this book they share their war stories and advice.

September 08, 2009 @ 11:47 AM PDT
Cateogory: Book Reviews

Spriting and learning

In the mid-1990's I was really into Nintendo games, as was everyone. My favorite was the original NES Final Fantasy. Sometime in my teens I got my first computer, and I decided it would be cool if I had some sprites of that game on my computer.

Before

My first computer ran at 640x480 with 16 colors. I had Windows 3.1 and the most sophisticated image manipulation program around was MS Paint. How could I get sprites into my computer? Well, I had a strategy guide for the game, with blurry photos of all of the enemies, so I just opened up MS Paint, zoomed waaaaaaaay in, and drew all of the sprites pixel-by-pixel. Insane? Maybe, but it's a fun kind of insane.

This took about a year of off-and-on work, but in the end I had something I thought was great. I still have the file:

FF1

September 07, 2009 @ 6:57 AM PDT
Cateogory: Programming

searchpairpos

How did I live this long without knowing about searchpairpos() in Vim? I hate when I write a clumsy, slow reimplementation of something that already exists as a standard function.

The only bad thing about Vim and Emacs both is that the feature list is about a mile and a half long (and that's a bad thing only in the sense of being an overwhelming amount of good things).

I have read almost the entire Vim manual at this point but there are corners that remain unexplored, and sometimes they contain treasure. One thing I love doing is answering Vim questions on Stack Overflow because most of the time I don't know the answer right off the bat, and so looking it up or figuring it out teaches me something new.

Emacs is another story... Emacs remains a mystery to me in many ways, in spite of having used it for about a year now. I very much plan to read the whole Emacs manual. I've already read parts of it but I seem to have barely made a dent. There are things I know should be simple to do or that there are already built-in options for, but I don't know how to do them.

  • How do I kill a word and also kill the whitespace immediately after it so it yanks properly later?
  • When I kill-whole-line and paste that line elesewhere, I lose a newline and screw up indenting. Sometimes it works how I expect and sometimes it doesn't.
  • There are so many things I can do in Vim but can't in Emacs... marks, multiple registers, abbreviations, sensibly configured per-filetype indentation.

etc. etc. I know there are ways to do these things once I have time to just sit down and read the darned manual. And learn elisp's syntax and semantics (which can't be harder than learning Vim script). My ~/.vimrc is currently twice as long as my ~/.emacs, which says a lot.

On a related note, I'm in the process of putting my Vim and Emacs configs on github.

August 20, 2009 @ 7:39 AM PDT
Cateogory: Programming
Tags: Emacs, Vim

ATH-AD700 Review

Recently I got my ATH-AD700 headphones. I've been FAR more excited than anyone has a right to be, waiting for these things to show up, like Christmas in August. Sweet, sweet anticipation. It was well worth the wait.

The only other headphones I have to compare these with are my Grado SR80's (which have really seen better days) and some Shure "noise-cancelling" earbuds which are nice but are not comparable to either. So I'll compare the AD700 to the SR80's. ATH-AD700's are pictured left, Grado SR80's are right.

Headphones Headphones

(Note: Nowhere in this article shall I refer to anything as "cans". I reserve the right to retain some level of self-righteous, snobbish disdain for the audiophile community.)

This post is related to Audiophail
August 17, 2009 @ 5:10 PM PDT
Cateogory: Hardware