A Rubyist’s Impressions of Common Lisp

It has been nearly 6 months since I dove into Common Lisp. I have been studying and/or using Common Lisp almost every day, working on Ambienome and related code. So, I wanted to take some time to document my observations, feelings, and impressions of Common Lisp at this time. Be advised that this is a fairly long post, even though I have trimmed out a lot of details and examples to keep it from growing even longer. (Apparently I have a lot of impressions!)

I have approached CL from nearly 8 years of programming in Ruby. I mention this because my experience with Ruby has certainly colored my impressions of CL, and many of my observations are about how CL compares to Ruby. Continue reading A Rubyist’s Impressions of Common Lisp

Snippet: Range#compare

Here’s a little idea that popped into my head for enhancing the Range class in Ruby:

1
2
3
4
5
6
7
8
9
10
11
class Range
  def compare( value )
    if member?( value )
      0
    elsif value <= self.begin
      -1
    elsif value >= self.end
      1
    end
  end
end

Then you can perform broad comparisons, like so:

1
2
3
4
5
6
7
8
9
10
def try_compare( x, r=(1..10) )
  case r.compare x
  when -1
    "#{x} is below the range #{r}"
  when 1
    "#{x} is above the range #{r}"
  when 0
    "#{x} is inside the range #{r}"
  end
end

Example:

1
2
3
4
5
6
>> try_compare( 3 )
"3 is inside the range 1..10"
>> try_compare( -1 )
"-1 is below the range 1..10"
>> try_compare( 11 )
"11 is above the range 1..10"

I haven’t decided whether this is useful, or just daft.

Testing the Git Waters

Apparently, Git is the new hotness, and Github is liquid hotness concentrate, with pulp. Or, so I hear. Rails monkeys seem to like it, anyway. ;)

You can blame Piotr for bringing it to my attention, and then radiant-comments for giving me an excuse to dip my foot in.

I did some browsing online, and it seemed pretty neat (yay for branching), but I wasn’t quite grokking the process. Luckily, I had some old PeepCode credits lying around, so I took a look at their Git tutorial screencast. The three main things I got out of the screencast were:

  1. Learned about the ‘tree’ utility for *nix. (Huh, never knew about that one before! Handy.)
  2. Got a better handle on how you do stuff with Git. Branching, fetching, rolling over and playing dead, etc. (Arf arf.)
  3. Learned that you can work on Subversion repositories using Git!

For now, I’m just getting my feet wet by hacking on the comments extension for Radiant CMS. Once I get the hang of it, I might try using git-svn to work on Rubygame in its Subversion repo. And maybe, just maybe, if that works out well, I’ll consider migrating Rubygame’s repo to Git / Github. Maybe.

By the way, did you know that Rubygame has almost 1000 commits in its Subversion repository, dating back to December 4, 2004? (Hrmm, 1000 commits sounds more impressive when it’s not spread out over 3½ years. How does 325 commits since Rubygame 2.2.0, December 19, 2007, sound? Sounds like progress to me.)

Anyway, it’s at revision 995 right now. I’ll probably do some sort of commemorative post when I commit #1000. Y’know, because I’m all sentimental, and stuff.

RDoc C parser needs improvement

I don’t think I’ve mentioned here how frustrating RDoc’s C parser can be. It’s almost up there with SDL_mixer on the headache-o-meter, I swear.

I’ll admit, the idea of automatically generating documentation from the code structure and comments in the source code is neat. And RDoc does a pretty good job of figuring out the structure of Ruby code. It’s pretty smart at that, and it can figure out which class is located under which module, and which class in the parent of which subclass, and which mixin is included in which class, etc.

But it’s not so great at figuring that stuff out in the code for extensions written in C, like Rubygame.

Partly that’s because it’s a harder task to tease the meaning out of the C code. It’s also partly because the C parser doesn’t have as many users (and thus fewer eyes for looking, and fewer hands for patching).

Whatever the reason, the C parser is a lot less polished than its Ruby-parsing counterpart. It’s able to handle simple things decently: defining a module, defining a class, defining methods under that class, etc. But for more complex scenarios, it fails.

And it’s fine that it can’t figure out complicated stuff on its own. It wouldn’t be reasonable to expect RDoc to handle every strange scenario perfectly. The problem I have is that there’s very little you can do to help RDoc generate the correct documentation, except trying to avoid situations that it doesn’t understand. (Designing code around the deficiencies of the documentation program? It’s insane, but I have to admit I’ve done it in several places in Rubygame in the past.)

What I’d really like to do, is give meaningful hints to RDoc, to help it understand what’s going on. For example, consider this C code, which I’ve recently written in the Surface class to make it include the NamedResource mixin:

rb_include_module( cSurface,
  rb_const_get(mRubygame, rb_intern("NamedResource")) );

RDoc’s parser will not have a clue what’s going on here, and that’s understandable. But if there was a way to tell RDoc, “Hey, the Surface class includes Rubygame::NamedResource”, it wouldn’t need to figure out what the code means. I’d have more control over the documentation that’s generated, and the output would be more meaningful and useful to the reader. Everybody would be shiny and happy.

Unfortunately, I don’t think I have the time to learn RDoc’s inner workings well enough to patch it to do such a thing. (Heck, I don’t even have as much time to dedicate to Rubygame as I’d like.)

So my options right now are:

  1. Jump through some hoops and pretend to define the NamedResource module again in a place that RDoc will remember it in this scope.
  2. Write the module inclusion code in Ruby (and thus split my class definition across two files in two different languages).
  3. Write a dummy sourcefile in Ruby with the documentation (this is what Chipmunk does).
  4. Just put a note in the class documentation for Surface, mentioning that it includes the module.

I started using #1 years ago to make RDoc to correctly place all the classes inside the Rubygame module. But since it’s not as important that RDoc know about the relationship between Surface and NamedResource, I’ll probably end up using #4.

Besides the deficiencies in the C parser, there are some other things about RDoc (and automated documentation extraction in general) which displease me, but I’ve already wasted enough time ranting for one day. ;)

Emacs: ruby-electric-return

I’ve made a patch to improve the ruby-electric-mode for Emacs. If you use Emacs to edit Ruby code, please try it out and tell me what you think!

I’ve created a patch to the ruby-electric-mode for Emacs, which makes pressing return after certain keywords automatically
insert an “end” statement, just like pressing space does.

So, if you type this:

  begin

when you press return, it will become:

  begin

  end

It will put the cursor on the line between “begin” and “end” and automatically indent, so you can
start typing more code right away!

It will work with the other keywords that electric-space does, too. For example, when writing RSpec, you can type:

  it "should be empty" do

and then press return, it will insert the “end” for you.

Before, you would have to press space and then return, which seemed unnatural to me. However, I have made
ruby-electric-return smart enough not to work against you if you have the habit of doing space and then return: it will
only insert the “end” if you press return with the cursor directly after the keyword.

Also, I added a customizable variable, “ruby-electric-return”, which can be used to disable this feature if
you don’t like it. I made it on by default, but I won’t be offended if you change the patch (line 7) to make it off
by default instead.

I welcome any suggestions or comments.

Rant: BetterNestedSet (than a nail in your skull)

I’ve been tinkering around with ApeDoctor, my to-be API documentation application running on Rails. The core class of ApeDoctor is the Amodule, a representation of a Ruby module/class. (It’s Amodule because the class name Module was taken, of course!) And since Ruby modules can have other modules or classes under them, I had a hierarchy/tree/nested set on my hands.

My first instinct was to use acts_as_tree. Ah, simple, naïve AAT. The logical choice for a beginning Rails developer, and it worked quite well for my humble purposes. Vague warnings on the web of AAT inefficiency didn’t bother me much; I anticipate having fewer than 20 nodes in the tree, and most of the branches quite shallow.

But then a friend recommended BetterNestedSet. Wow, BetterNestedSet! It has the word “Better” right in the name, so it must be really good, right?

Well, after struggling for days to get BNS to meet my simple needs, I find myself asking, “Better than what, someone driving a nail into your skull with a hammer?” I’ve found it extremely awkward to use; I’ve had to jump through more hoops than a show dog, and my best result is barely acceptable.

First of all, you can’t set parent_id, like you do with acts_as_tree. If you try, BNS will bark at you. Instead, you have to use the move_to_child_of method so than BNS can work its behind-the-scenes nested set voodoo.

That doesn’t sound so bad. Maybe change a few lines of code, and it’s working, right? Well, there’s a catch: you can only call move_to_child_of after the record has been created in the database.

Oh. Hmm. Okay, maybe we’ll just use an after_save callback to call it. Aha, Catch 22: you have to store the id of the parent object somewhere, so that you can retrieve it in the callback, but you can’t put it in parent_id, even temporarily, because BNS forbids it.

So maybe we can store it in another instance variable, maybe name it @new_parent or such, and then use that in the callback. That’s workable. You’ll have to go through some hoops in your view and controller to support it. The lovely scaffold you generated, with a field for setting parent_id, is broken by BNS, but we can just change that to set new_parent instead…

Except that passing a hash of attributes (like the params in your controller’s create action, made with the form values) will only set attributes that map directly onto a database column. So Rails won’t set our @new_parent attribute from the params. But you can fake it by doing:

@amodule = Amodule.new(params[:amodule])
@amodule.new_parent = params[:amodule][:new_parent]

Okay, we’re getting somewhere! It seems to work, everything is going great…

Unless you want to, say, do validation involving the parent. In my case, I wanted to make sure that sibling modules had unique names, but not be fussy about having the same name as a module under a different parent. The natural way to express that would be:

validates_uniqueness_of :name, :scope => :parent_id

But that won’t work with BNS, because parent_id won’t be set at validation time – it only gets set after the record has been saved. And you can’t change the scope to use :new_parent, our temporary attribute, because that’s not what the database column is called. So you’re left to write your own makeshift uniqueness validation:

def validate
    same = Amodule.find(:all,
                       :conditions => {
                         :name => self.name,
                         :parent_id => @new_parent
                       })

    same.each do |mod|
      if( mod == self )
        errors.add(:name, "already exists under this parent")
      end
    end
end

Congratulations, you now have an awkward, makeshift, hackish nested set model. Wasn’t that so much better than using acts_as_tree? At least it’ll be nice and efficient… well, except for inserting, moving, or deleting nodes, which require practically the entire table to be rewritten.

Conclusion: BetterNestedSet was a major pain in the ass, is completely unnecessary for my modest purposes, wasted days of my life, and above all soured my feelings towards Rails and this project. But I’m sure the friend that suggested it meant well, so I won’t drive a nail into his skull to thank him.

</rant>

Looking at Rails

I picked up “Agile Web Development with Rails” yesterday. Despite using ruby for over 3 years, I have not up until this point put any concentrated effort into learning and using Rails. I’ve been running (or rolling, as it were) through the tutorial, an online bookstore app.

By and large, the impression I have so far of Rails is that it’s very convenient. It seems like Rails has built-in just about anything you’d want to do—at least, in the limited domain of database-driven web applications.

As I learn more and more about Rails, I can’t help contrasting it with Rubygame. It has been somewhat humbling, but also motivating.

There are rather different design philosophies at play between the two projects; of particular interest is Rails’ notion of favoring “convention over configuration”. In Rails, it’s extremely simple to do things, as long as you follow the conventions that are in place; if you want to do something outside of the conventions, it takes a bit more work.

Rubygame, on the other hand, tries not to make any assumptions about how it will be used (or, so I tell myself). I want to encourage out-of-the-ordinary applications; I hope to see some really cool and weird applications coming out of it. As a result, there’s no assumption that you will want to make a tile-based game, or an RPG game, or will want to use images loaded from files, etc. It’s open-ended.

Rails has a well-defined and highly-encouraged structure to it. Rubygame lets you build your own structure (or forces you to, depending on how you look at it).

There is a definite appeal to the structured approach of Rails: everything has its place, and it doesn’t take much guesswork to figure out where that should be. With Rubygame, you have to decide for yourself.

So, should Rubygame be more structured? Should it assume that you’re going to organize your code in certain ways; that you will need certain types of classes and objects and elements?

Perhaps this is a spurious comparison. Rails is a framework—Rubygame is a library. Someone could build a structured framework using Rubygame, but I’m not sure it’s appropriate for Rubygame itself to enforce structure. Still, there may be some aspects or qualities of Rails that would be useful in the context of Rubygame.

It’s certainly something to think about.

Picking apart Rubygems and Rake

I’m prepping for the 2.0.1 release of rubygame, which includes a number of bug fixes and improvements under the hood, especially in the way method arguments are processed in C methods. All the code is ready and waiting to be packaged up, but I’m tinkering with the Rakefile to make it play well with Rubygems, especially on win32 platforms.

In the 2.0.0 release, there were some snags supporting win32 users. The precompiled binaries were packaged up in gems so users wouldn’t have to compile rubygame for themselves (this is more of an issue on win32 than on linux, which has the GNU C compiler available as a general rule). Unfortunately, the gem didn’t work correctly for all users: despite the precompiled binaries being present, the Rakefile didn’t think they had been compiled, and would throw a fit when it was unable to compile them for itself.

The problem seems to be that some ruby installations on win32 expect dynamic libraries to have the .so extension (in *nix fashion), while others expect .dll (in win32 fashion). The libraries in the rubygame gem end with .so, but the Rakefile takes its hints from the ruby installation’s config: on some systems, it would be looking for .dll instead!

My first thought, then, was to have the Rakefile rename the libraries at install-time to conform to the system’s expectations. Even though they have the .so extension, the libraries are win32-style DLLs inside, so I don’t expect ruby to get confused when it tries to load them (it seems to ignore the extension anyway).

But here’s the catch: when using rubygems, the install task isn’t run. I had read online somewhere that rubygems expects the Rakefile for compiled ruby extension to respond to two tasks: extension (for compiling) and install (for installing to the appropriate directory). It turns out, though, that it presently only uses the extension task. (This I discovered only after rummaging through the source code for rubygems last night.)

Fortunately, this is not a big problem, because I can prepend a fix_filenames task as a dependency of the extension task, right before the build task (which compiles the libraries if doesn’t see that they have already been compiled):

1
2
3
4
5
6
7
8
9
10
11
12

desc "(Called when installing via Rubygems)"
task :extension => [:fix_filenames, :build]

task :fix_filenames do
  Rake::Task[:install_ext].prerequisites.each do |prereq|
    prereq = prereq.ext('so')
    if File.exist? prereq
      mv prereq prereq.ext(DLEXT)
    end
  end
end

This takes each of the prerequisites to the install_ext task (each prereq is a String pathname to a compiled library file), checks whether the file exists with a .so extension, and if so, renames it to the system extension for dynamic libraries (DLEXT is derived from Config::CONFIG[‘DLEXT’]).

Let’s see if that does the trick.


UPDATE: One more tweak is needed to the fix_filenames task, because the mv command will complain if the source and destination are the same, which causes the task to fail on systems which actually *do* use .so, like Linux. Here’s a corrected version:

1
2
3
4
5
6
7
8
9
10
11

task :fix_filenames do
  unless DLEXT == 'so'
    Rake::Task[:install_ext].prerequisites.each do |prereq|
      prereq = prereq.ext('so')
      if File.exist? prereq
        mv prereq prereq.ext(DLEXT)
      end
    end
  end
end

Ramble: Curves Roadblock

I’ve been pounding my head against the wall over these Bézier curves for the past couple days. For a change of pace, I’m going to pound my head against this blog instead, and hope that something useful falls out.

The overall challenge is to preserve the apparent position of an object (i.e. the character) along the curve while dragging one of the handles.

Currently, the character’s position is defined between 0.0 and 1.0, representing how far along the entire curve he is (0.5 being halfway around; for a closed curve, 0.0 and 1.0 are at the same location).

The character should seem to stick to a point on the curve, moving as that point moves. This means that the character’s actual position along the curve needs to be adjusted to compensate for the change in overall curve length.

Without such adjustment, the character will seem to slide along the curve, even if the curve is being modified somewhere else (because the curve’s overall length will change).

One possible solution would be to modify how the character defines its position. If it were defined as the position 0.0 to 1.0 along an individual segment, then modifying other segments would not affect the character’s position. More, modifying the segment that the character is on would cause the character to move along with the segment as it’s stretched/squashed. Problems solved.

(Even better than defining 0.0 to 1.0 along a segment, would be to define 0.0 to L, the length of the segment. This will make it easier to have the character seem to move at a constant speed.)

This somewhat complicates the way the character’s true position is defined, because it will have to remember which segment it is on, and find out what the next segment is when it walks off of the current one. This can be accomplished by having each segment remember the previous and next segments in the chair (i.e. linked list of segments).

This entails a substantial rearranging of how the curve system is currently defined. Much of the power and responsibility of th Curve class will be shifted off to other classes, especially Segment.