Posts Tagged ‘ruby’

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.

imenu for Ruby

Tuesday, April 22nd, 2008

If you use ruby-mode, you need to add

(imenu-add-to-menubar "iRuby")

to your .emacs right now.

This adds a menu to the menubar, titled “iRuby”, which lists all the classes and methods.  When you select one, it jumps to that point in the file. If you are a keyboard junkie, you can run M-x imenu and get keyboard completion on any of these.

The downsides of this are:

  • it doesn’t update automatically: you need to choose the “*Rescan*” menuitem
  • it does only simple regexp-based parsing, nests instead of putting more than 25 items in the menu, and various other slightly-annoying things

I started a project, iruby-mode, to be what I was looking for, but since I figured out a 1-line way to get me 85% or 90% of the way there, I have much less incentive to work on this.

ruby-mode.el regexp bug

Tuesday, April 22nd, 2008

ruby-mode.el has a nasty bug: sometimes it won’t recognize the end of a string, so you end up with half your file colored the weird string-color.  Of course, it’s very annoying.

Today, I discovered the cause of this: it happens when your string ends with a “?” and there’s a “‘” earlier in the string.  ruby-mode thinks the ?” is a character literal.  You know, that feature of Ruby which has been used exactly twice in the history of Ruby programming.  *facepalm*

The fix is easy, assuming you never use character literals: open up ruby-mode.el and scroll down to about line 1019:

	  ;; $' $" $` .... are variables
	  ;; ?' ?" ?` are ascii codes
	  ("\\(^\\|[^\\\\]\\)\\(\\\\\\\\\\)*[?$]\\([#\"'`]\\)" 3 (1 . nil))
	  ;; regexps
	  ("\\(^\\|[=(,~?:;]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"

Comment out the line that ends (1 . nil)). Recompile the .elc, if you have such a file.

If anybody wants to come up with a fix for this that works for both string and character literals, be my guest. I’m not going to spend any time tweaking 15 lines of Emacs Lisp regexps for some feature I never use.

Thanks to Phil Hagelberg for inspiring me to fix this.

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.

Fixed an evil bug; two things I learned

Monday, April 7th, 2008

1. link_to_remote’s :update parameter is the box to put the new object in, not the box to replace

2. If you stupidly have more than one element in your DOM with the same ID (see #1), and ask for it by ID, Firefox 2 takes the last one; Firefox 3, Safari, and Opera all take the first one.

Not knowing these facts can make debugging AJAX code in Rails seriously unfun.  It’s one thing when IE6 screws up your webpage, but when Firefox 2 doesn’t do what you want, it’s like it’s mocking you.

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.