Posts Tagged ‘lisp’

Arithmetic

Thursday, May 8th, 2008

Just when I was beginning to think that maybe Ruby’s slight edge in readability made up for its big loss in consistency, I needed to use rational numbers:

  • Ruby: Rational(3,5)
  • Lisp: 3/5

Languages like Ruby and C are basically infix for arithmetic, and prefix for everything else.  For a web app (like most apps, come to think of it), I pretty much never do anything more than the most trivial arithmetic.  And here, in the one place where I do need something as complex as fractions(!), Ruby forces me to use prefix notation — which even Lisp, the prefix-notation king, doesn’t require.  And not just prefix notation, but spelling out the name of the numeric type I want.

This seems just so deeply, thoroughly wrong.

Pseudo-English

Thursday, April 17th, 2008

So I came across a feature to implement whose description read “X% of the time, do Y”.  I thought for a second, and then wrote:

class Numeric
  def percent_of_the_time
    yield if rand(100) < self
  end
end

This works great: 15.percent_of_the_time {puts "hello, world"}.

(My unit testing friends are probably freaking out over monkey-patching core classes to be nondeterministic.  Good!)

Then I got to wondering: why can’t I do this in Lisp?  In Arc some things are callable which normally aren’t, but that seems a bit too much like magic to me, and I’m not sure it’s easily extensible to this case.

The problem with making something pseudo-English is that you need to put the noun first, and in Lisp the verb always comes first.

The solution is more obvious than I’d thought: use a library like curly-infix, and then just write a normal function.  Thus, in Lisp, it can be as simple as:

{15 percent-of-the-time (format t "hello, world")}

The only gotcha is that this looks suspiciously like a single-dispatch method call, but if you’re using CLOS generic functions, it’s not.

On cultural differences between languages

Thursday, January 17th, 2008

While trying to figure out how to get MysqlAdapter to do something, it occurred to me one big difference between Ruby (which I’m relatively new to) and Lisp (which I’ve played with for years).

Where Lispers use hooks, Rubyists use monkeypatching.

It’s not a technical difference, because you can monkeypatch in Lisp and you can use hooks in Ruby. Maybe it’s a question of maturity: programmers don’t want to add hooks that won’t get used, and so only add them lazily.  It certainly seems true that older Lisp code is more likely to have more hooks: Common Lisp itself has a million hooks, and Emacs, says the jargon file, “is all hooks”.  Maybe it’s natural selection: Lisp libraries either end up with lots of hooks, or dead.

The Ruby way has advantages and disadvantages.  On the plus side, a young project doesn’t have to guess what people might want to extend.  On the downside, well, it’s monkey-patching.

(For example, the problem that inspired this post led me to monkey-patching a private method.  It looks like you can monkey-patch a private method, but you can’t call ’super’ in it, because super is private. Gah.  And ActiveRecord has basically no hooks.)

Even Zed Shaw, flamester extraordinaire, hates it.  Monkey-patching is ghetto.

What I really want is a hybrid Lisp/Ruby solution: CLOS qualifiers in Ruby.  A qualifier is a keyword you pass to defmethod — :before or :after or :around — which causes it to supplement, rather than replace, the (unqualified) method definition that already exists. It’s like hooks everywhere for free.

That is, I want to be able to say:

class MysqlAdapter
  def :after connect
    execute("SET SESSION sql_mode='ANSI'")
  end
end

(Now somebody is going to write me some super-twisted Ruby code to allow exactly that, and it’s going to be like monkey-patching but 10 times worse because it’ll be implemented as one giant monkey-patch.  Thanks, no.)

But in plain old Ruby, what’s the solution?  If you write a library, it needs hooks — especially if you’re part of a big framework, like ActiveRecord is.  And if you design a programming language, it should make allowing hooks virtually free for people writing libraries.