April 13, 2008

I lead a typical, boring life

~ $ history|awk '{a[$2]++} END{for(i in a){printf "%5d\t%s\n ",a[i],i}}'|sort -rn|head
   285	hg
   51	script/server
    32	cd
    17	rm
    15	ls
    10	rake
     8	vi
     8	ps
     8	mate
     8	cap

April 1, 2008

A Modest Syntax Proposal: RBXML

Ruby is a wonderful language, but its syntax has some shortcomings. Inspired by Perl, the syntax of Ruby requires many special cases and is difficult to parse by anything but a full Ruby interpreter. We seek to fix this issue with a new, unambiguous syntax for Ruby: RBXML.

"Business Reporting and XML go hand in hand. I plan to convert Ruport to RBXML as soon as I can!"
-- Gregory Brown, Ruby Reports maintainer

Consider the following Ruby code. While it is certainly concise, it achieves this goal through use of obscure symbols such as . and |. This makes it difficult to read, and more importantly, difficult to parse by machine.

class Integer
  def factorial
    (1..self).inject(1) {|p, x| p*x}
  end
end

Rubyists talk a lot about metaprogramming, but how are you supposed to introspect on a language like that? Some projects try to work around these limitations by letting Ruby code introspect on itself; however, the result can be unwieldy. Why reinvent the wheel when XML has been around for years? Consider the much more regular and understandable syntax in RBXML:

<class name="Integer">
  <def name="factorial">
    <method-call>
      <name>inject</name>
      <receiver>
        <range exclude-end="false">
          <start>
            <integer>1</integer>
          </start>
          <end>self</end>
        </range>
      </receiver>
      <argument>
        <integer>1</integer>
      </argument>
      <block>
        <parameter name="p" />
        <parameter name="x" />
        <code>
          <method-call>
            <name>*</name>
            <receiver>p</receiver>
            <argument>x</argument>
          </method-call>
        </code>
      </block>
    </method-call>
  </def>
</class>

Just as languages in the Lisp family represent their parse trees with s-expressions, this regular syntax represents the parse tree directly, with only a small bit of XML parsing. Rubyists now have the advantage of not having an extra layer of syntax between them and their concepts.

But it doesn't stop there. We can add some simple syntactic sugar to condense our code further without making it significantly less readable. With a simple application of "duck typing," we infer a value of 1 from the string "1", thus eliminating the need for complex type annotations such as <integer>1</integer>. This principle can be applied to the <parameter> tag as well, using the well-known grammatical trick of a "comma splice". Here is the result:

<class name="Integer">
  <def name="factorial">
    <method-call name="inject" arguments="1"> <!-- quack! -->
      <receiver>
        <range exclude-end="false" start="1" end="self" />
      </receiver>
      <block parameters="p,x">
        <code>
          <method-call name="*" receiver="p" arguments="x" />
        </code>
      </block>
    </method-call>
  </def>
</class>

With a special syntax (Integer#factorial) familiar to all Ruby coders, we can eliminate the <class> tag that is really just a holdover from Ruby's original syntax. The <block> tag also now contains a superfluous <code> tag, which we can remove. In addition, the range/exclude-end parameter can be omitted and sensibly defaults to false. This tightens up the RBXML even more:

<def name="Integer#factorial">
  <method-call name="inject" arguments="1">
    <receiver>
      <range start="1" end="self" />
    </receiver>
    <block parameters="p,x">
      <method-call name="*" receiver="p" arguments="x" />
    </block>
  </method-call>
</def>

Some community members have expressed the feeling that some Ruby syntax is "intuitive." As a transition aid for such people, we offer a compromise syntax. The code attribute will interpret code according to Ruby's old syntax rules, hopefully easing the transition to the new RBXML syntax:

<def name="Integer#factorial">
  <method-call name="inject" arguments="1">
    <receiver code="1..self" />
    <block code="|p, x| p * x" />
  </method-call>
</def>

However, users should be cautioned that the code attribute spins up a new Ruby interpreter process for every invocation, and thus should be used sparingly. It may be more efficient to use the <code> tag at the toplevel, as all toplevel blocks are evaluated within one Ruby interpreter. This code should perform almost as well as current versions of MRI:

<code>
<![CDATA[
  class Integer
    def factorial
      (1..self).inject(1) {|p, x| p*x}
    end
  end
]]>
</code>

RBXML is still under development. Unfortunately, we are unable to do a public release at this point, on the advice of our legal team. We hope to release the 1.0 version by April 1, 2009.

March 4, 2008

stealing from arc

Paul Graham's Arc language has been causing a commotion in the Lisp and web application communities. One of the stand-out features of Arc is its tidy syntax for simple anonymous functions. In Arc, the increment function can be expressed thus, using square brackets:

[+ 1 _]
Compare this to Common Lisp's completely readable, but less-than-fun, syntax for the same function:
(lambda (x) (+ x 1))

Arc's implementation of the bracket syntax is in brackets.scm, written by Eli Barzilay. Using Eli's Scheme code as a guide, I wrote the following Common Lisp reader macro:

(defun square-bracket-reader (stream char)
  (declare (ignore char))
  `(lambda (&optional _ __)
    (declare (ignorable _ __)) ; don't warn about unused variables
    ,(read-delimited-list #\] stream t)))

(defun use-square-bracket-readtable ()
  ; Install #'square-bracket-reader as a reader macro for [
  (set-macro-character #\[ #'square-bracket-reader)
  
  ; Make ] behave like ) to the reader so that [+ 1 _] works,
  ; not just [+ 1 _ ].
  (set-macro-character #\] (get-macro-character #\) nil)))

Usage is very simple:

CL-USER> (use-square-bracket-readtable)
T
CL-USER> ([+ 1 _] 10)
11
CL-USER> ([+ _ __] 1 2)
3

September 29, 2007

The Cover

Advanced Rails officially has a zebra. Thanks to everyone who gave feedback on the original, especially to Jim Kane for his suggestion of a tagline which it appears we are going to use.

advancedrails_cover.jpg

August 31, 2007

The Limits of Search

An interesting perspective on generalized search, with an informal but convincing conjecture on fundamental limitations to search problems. (In a word, TANSTAAFL.) To wit:

If you’re going to find a needle in a haystack, then you’ve got to expend at least some computational effort sifting through the hay.

The author ties it in with computational complexity theory and the age-old question of whether P = NP:

Many people — even computer scientists — don’t appreciate just how profound the consequences would be if P=NP. They think it’s about scheduling airline flights better, or packing more boxes in your truck. Of course, it is about those things — but the point is that you can have a set of boxes such that if you could pack them into your truck, then you would also have proved the Riemann Hypothesis!

He postulates that these fundamental limitations constrain not only classical but also quantum computing, railing against the modern conception of quantum computers as generalized massively parallel solvers. All in all, quite an interesting perspective. Nothing fundamentally profound or groundbreaking here, but it all makes sense.

August 30, 2007

Ambition

Ambition by Chris Wanstrath is not only the coolest thing in Ruby since ruby-inline, it is also one of the best examples of practical functional programming that I have ever seen. Go check it out and be enlightened.

August 25, 2007

Metric Spaces

Fascinating paper on vp-trees, useful for generalized BSP indexing over metric spaces. Like a kd-tree but more flexible and abstract, and more useful on non-Euclidean distance metrics. I've been thinking about using vp-trees over a Levenshtein-distance metric space for some code complexity assessments--seems to have better performance than either a kd-tree, and more generality than a bk-tree.

June 25, 2007

Amazon

I'm on Amazon now. I guess I do exist, after all.

April 20, 2007

Lisp from Rails

Rails-RLisp

The Rails-RLisp plugin is a bridge from Rails to Tomasz Wegrzanowski's RLisp language. Using this plugin, any files with an .rl extension will be compiled as RLisp instead of Ruby. These files can be weaved into your Rails app where you would normally use Ruby files.

Rails-RLisp is available from svn://svn.madriska.com/plugins/rlisp.

The plugin hacks Rails's Dependencies mechanism to autoload .rl files where needed.

.rl files will be compiled into Ruby files of the same name, with an .rlc (Ruby Lisp Compiled) extension. Files will automatically be recompiled if the corresponding .rl file is changed.

Example

1. Install the plugin:

$ script/plugin install svn://svn.madriska.com/plugins/rlisp

2. Create a test file, app/models/lisp_test.rl:

(defclass LispTest)
(class LispTest
  (method hello (name) 
    (print (+ "Hello, " [name to_s])))
  (method fib (x)
    (if (== x 0) 
      1
      (* x [self fib (- x 1)]))))

3. Test the class loading:

$ script/console 
Loading development environment.
>> LispTest.new.fib 12
=> 479001600
>> LispTest.new.hello "world"
Hello, world
=> nil

References

  1. RLisp Home Page
  2. Compiler for RLisp

March 27, 2007

Dvorak

Never thought it would happen, but I finally switched to the Dvorak keyboard layout. I've been wanting to switch for years, but there is never a good time for a programmer to have to re-learn how to type.

It wasn't nearly as bad as I expected. For a few days, it was utterly frustrating not to be able to communicate with a computer. The sacred bond between a developer and his tools had been broken. Oh, and I switched on a writing day. Probably not the smartest idea, but whatever.

I've been at it for about 2.5 weeks, and I'm at maybe 80% of my QWERTY speed. It's true what they say -- Dvorak is a lot more comfortable, and I didn't even have RSI symptoms before. August Dvorak, my future tendons thank you.

The worst part is retraining my vi fingers. Years of muscle memory obliterated.