Archive for the ‘Ruby’ Category

I hope it’s not, like, a trademark of Nintendo or something

Friday, June 20th, 2008

Current project: Picross in Ruby, using Korundum and such. Which is so much better than using C++ directly. <3

However, note to me and anyone else using it: Qt::MainWindow#central_widget= doesn’t work. You have to use #setCentralWidget or #set_central_widget, or whatever, otherwise it’ll overlap with the other parts of the window like the menu bar and so on. Knowing this in advance would’ve saved about an hour of futile debugging. :( (Obviously this goes for KDE::MainWindow and KDE::XmlGuiWindow as well.)

On the other hand, the fact that it automatically translates ruby_style_identifiers to qtStyleIdentifiers is pretty cool, even though I suppose in the grand scheme of things it’s about as important as bracketing styles…

Update: some screenshots to show what I mean.

set_central_widget central_widget=
Right Wrong
Good Arg

Automatic method forwarding in Ruby

Wednesday, November 21st, 2007

Warning for googlers: this post is probably not useful. I wasn’t that good at Ruby metaprogramming when I wrote this post. (The obvious followup question is why I wrote it in the first place. I have no idea.)


I’m implementing a Tree in Ruby for an Euler problem (I don’t think I’m quite good enough to attempt it in Haskell yet). Yes I know there’s probably several in the standard libraries, but that’s cheating.

Anyway, a lot of the methods, like size, each, and so on are easiest implemented as recursive methods of the nodes. Meaning they’re all just calling say @root.size, and nothing else. This is not on.

One of the best things about Ruby is that you can just define new methods for any class, at any time, and moreover you can do this automatically using instance_eval and friends. So this was just dying for a forward_to method which takes a list of names, and forwards those methods to some member or other. The first form is thus1:

module ForwardTo
    def forward_to mem, *meths
        meths.each do |meth|
            instance_eval "def #{meth}; @#{mem}.send :#{meth}; end"
        end
    end
end

Obviously this doesn’t allow arguments or blocks to be passed, making all kinds of things impossible, but notably each, which takes both (it has an argument specifying the order of traversal), and was the whole point. Luckily this is easily solved, by adding *args and &block. Also for some reason I forgot about %<> quoting2 the first time around, so this iteration is a lot more readable.

module ForwardTo
    def forward_to mem, meths
        meths.each do |meth|
            instance_eval %<
                def #{meth}(args, &block)
                    @#{mem}.send :#{meth}, *args, &block
                end
            >
        end
    end
end

end end end end end end end end end… Anyway, you probably already know that send doesn’t honour method visibility, so we could be accidentally calling private methods. So I changed it to —

— And then, just a second ago when writing this, I came to my senses and realised that I’m in an eval so I don’t have to mess around with this sort of thing: I can just have @#{mem}.#{meth} in the string instead. Also, I put the method in Object instead because it’s small and unlikely to mess things up, and it saves a call to include.

class Object
    def forward_to mem, meths
        meths.each do |meth|
            instance_eval %<
                def #{meth}(args, &block)
                    @#{mem}.#{meth}(*args, &block)
                end
            >
        end
    end
end

There is still a big problem with this, though. You will probably want to put it in the class body, along with things like attr_accessor:

class Foo
    @mem = []
    # ...
    forward_to :mem, :each, :size
end

… which will not work. The ‘instance’ that instance_eval sees is the instance of Class; in other words, this will add class methods each and size. Which will forward to instance variables. Useful, I know. The workaround I’m using at the moment is to put forward_to calls into initialize. I’ll fix it properly when I find the name of the method that does what I mean.

Update: There’s a not-very-well-hidden method called class_eval, which… does exactly what you’d expect. So you can use that instead of instance_eval and then forward_to can be used in exactly the same way as the attr_* methods. (There’s also a module_eval, incidentally.)


  1. Actually the first iteration was some godawful mess with method_missing, but let’s not go there. 

  2. Which the syntax highlighter can’t cope with, so I’ll not highlight the snippets which use it.