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

Sup email client keybindings and filters

Lately I’ve been playing with Sup, a geeky console-based email client written in Ruby. I’ve used it enough to understand it and settle in a bit, but unfortunately also enough to realize that it’s probably not right for me. Along the way, though, I’ve done some work with keybindings and message filters that I’d like to share with you.

Before I get to that, though, a brief review of Sup. What first attracted me to Sup was the fact that it’s written in Ruby (with fairly clean code, from what I’ve seen), and has a fairly extensive system of hooks for customizing and extending the client behavior (the hooks are also written in Ruby). Also, it has a nice label-based filing system and powerful search utilities (a la Gmail), rather than the tired old folders metaphor. It runs in the console and is entirely keyboard driven, the workflow is pretty quick and easy, and you compose messages in the text editor of your choice (emacs, vim, etc.).

Those are the strong points, for me. Unfortunately, there are a number of issues that made me decide to look elsewhere. Foremost is the console-based interface using Curses, which holds it back in a variety of ways. One issue I ran into was that there’s no way to define keybindings that use the Alt key; Curses simply doesn’t support that. Sup also doesn’t seem to be able to render non-Latin characters, which is occasionally an issue for me. And naturally, being console-based, modern luxuries like HTML mail and previews of attached images are out of the question.

So, Sup turns out not to be my cup of tea after all. But, maybe it is yours, so I’ll share the fruits of my brief foray.

  • The first obstacle was the fact that Sup, like many Unix-style “mail user agents”, has no facilities for the actual fetching or sending of email over a network. Instead, it leverages programs like fetchmail, offlineimap, and sendmail to handle those things. This Unix-style mail system was something I had no prior experience in, so I had a lot to learn. After a lot of research and a fair bit of frustration, my advice is to forget the traditional fetchmail and sendmail, and instead use getmail and msmtp. They are a lot simpler to set up, and do everything most people need.

  • After I got my email imported into Sup, I wanted to change some key bindings to be more comfortable. In particular, being an Emacs user, I am used to Ctrl-n/Ctrl-p to move the cursor up and down lines, while Sup defaults to the vi-style hjkl bindings (which make no sense for me, using the Dvorak keyboard layout). Unfortunately, I could find very little documentation about how to change the keybindings, other than the fact that there was a “keybindings.rb” hook that I could write… if I knew what to write in it.

    Undeterred, I dove into the source code and learned all about the keybindings system. Then, I turned that knowledge into a comprehensive CustomizingKeys wiki page, so that the next guy wouldn’t have to dig through the code like I did. That was a fun afternoon project.

  • Next, I realized I needed a system to filter my incoming mail, automatically apply appropriate labels, and so on. Sup doesn’t have a filtering system like that built in, but it’s fairly straightforward to create one by taking advantage of Sup’s hook system. There is some documentation about this on the AutoAddLabelsToNewMessages wiki page, but as I started writing my filters, I began to realize that, although writing ruby code for every filter gives you a lot of flexibility and power, it also involves a lot of redundant code and is not very easy to read or maintain.

    So, I started writing my own filter system, which loads rules from a YAML file (see the example filters file). I’ve posted the result to my sup-filters repository on GitHub. Actually, what I’ve posted there is even more polished and better documented than what I used myself. Even after I had decided I wasn’t going to use Sup myself, I spent a couple days cleaning it up for other people, to call it a job well done. That’s Just How I Roll ™.

Anyway, if you use Sup, I hope you will find this stuff useful. As for myself, I will miss Sup’s labels and easy searching, but it’s time to continue my quest for a well-fitting email client. Next on my list to try is Wanderlust. If you have any recommendations for other clients to try, leave a comment!

Nice-FFI 0.4 released

Nice-FFI 0.4 is now available. You can install the new version with gem install nice-ffi, as usual. Please note that Nice-FFI is still not considered API-stable, so if you aren’t willing to update your code when a new version comes out, you shouldn’t use it until version 1.0.

Version 0.4 fixes several major bugs related to finding and loading dynamic libraries:

  • PathSet now properly expands globs (“*”) in file and directory names, like it was supposed to.
  • PathSet now works even when a directory path has no trailing separator (“/” or “\”).
  • Fixed a typo which caused NameError when using load_library with the default paths.

You can get Nice-FFI:

Please send bug reports and feature requests to the issue tracker on Github.

Nice-FFI 0.3 (and 0.2)

I’ve just released a new version of Nice-FFI, my convenience library for Ruby FFI libraries. You can install the new version with gem install nice-ffi, as usual. Please note that Nice-FFI is still not considered API-stable, so if you aren’t willing to update your code when a new version comes out, you shouldn’t use it until version 1.0.

Version 0.3 has a few changes:

  • The default PathSet has a less restrictive filename search pattern, so it is better at detecting libraries.
  • Struct.new can now accept FFI::Buffers. Buffers are like MemoryPointers, but with improved performance on JRuby in some situations.
  • Struct.new will now create a Buffer instead of a MemoryPointer when you create a new struct instance by value from an array, hash, bytestring, or another struct.

Also, since I never posted an announcement for 0.2, here are the changes for that version:

  • Added automatic memory management to the Struct class, if you define a “release” class method. It can be disabled per-instance by passing :autorelease => false to MyStruct.new.
  • Added new OpaqueStruct class. This class is useful for when the struct layout is not declared in the C library header. It also features automatic memory management like Struct.
  • Added Struct.typed_pointer, as a convenient alternative to TypedPointer.new(MyStruct). You can also pass :autorelease => false to disable memory management for all structs created via that TypedPointer, which is useful when using the TypedPointer as a function return type.
  • Structs can now be dumped to a bytestring (Struct#to_bytes), and also created from a bytestring (by passing a String to Struct.new).
  • Revamped the PathSet class. It now has separate patterns for paths (directories to search) and files (filename patterns), to be more flexible and easy to customize (e.g. you can add a new directory without caring about the filename pattern).
  • Removed Pathset#<< and Pathset#>>. Use append and prepend instead.
  • Renamed Library::DEFAULT_PATHS to PathSet::DEFAULT.
  • Added Library.optional, for when you want to continue loading the library even if a certain function or variable doesn’t exist in the library (e.g. because it’s not defined in old versions). It takes a code block, and will rescue and emit a warning if there is a FFI load error.
  • Also added Library.opt_func, which is the same as doing attach_function within an optional block.
  • Added some convenience aliases in Library: func = attach_function, var = attach_variable.
  • Nice-FFI no longer depends on the “need” library. We don’t need no stinking need!

You can get Nice-FFI:

Please send bug reports and feature requests to the issue tracker on Github.

Nice-FFI 0.1

I’m pleased to announce a small helper library I’ve created, Nice-FFI. It sits on top of Ruby-FFI and makes certain things easier and more convenient. Nice-FFI started out as helper classes I made for Ruby-SDL-FFI (which is coming soon), but I decided to generalize it and make it its own library so that other people might get some benefit from it.

Even though it’s still young, Nice-FFI already has some useful features:

  • With NiceFFI::Library, it’s easy to find libraries on all platforms. You can use e.g. load_library('SDL') (instead of ffi_lib) to look in platform-specific places. E.g. on Linux, it would first look for “/usr/local/lib/libSDL.so”, while on Windows it would look for “C:\windows\sys32\SDL.dll”. Linux (and BSD), Mac, and Windows each have a good selection of default search paths already, and it’s easy to add, remove, or change them using the NiceFFI::PathSet class.
  • With NiceFFI::Struct, struct classes automatically get accessor methods for their members, just by calling layout. E.g. layout :x, :int, :y, :int gives you #x, #x=, #y, and #y= for free. You can control which members get accessors using the read_only and hidden module methods.
  • If a struct member or function return value is a pointer to a struct, you can use NiceFFI::TypedPointer( MyStructClass ) instead of :pointer to get auto-wrapping. So, instead of returning a Pointer, a function would return a MyStructClass instance that holds the pointer.
  • New struct instances can be easily created “from scratch”, e.g. MyStructClass.new( :x => 1, :y => 2 ). You can initialize from a Hash, Array, another instance, or a pointer as usual. Struct attributes can also be dumped to a Hash or Array. And, structs have a nice #to_s method to show you the values of its members, for debugging.

All of the features are described in detail, with examples, in the docs (see especially docs/usage.rdoc, in addition to the class and method docs).

Nice-FFI is still young, though. So while I’d love for people to play around with it and give me feedback (and patches!), it’s probably not quite ready for prime time yet. It’s still under development, so the API may change suddenly. But if you are willing to tweak your code from time to time, I think you’ll find Nice-FFI to be very helpful. (Otherwise, just wait until 1.0, when the API stabilizes.)

You can get Nice-FFI:

Please send bug reports and feature requests to the issue tracker on Github.

Droplet Post-Mortem

This is a look back at last weekend’s RubyWeekend #3 game contest and the process of developing my entry, Droplet. You can read more post-mortems from the contest in the Rubygame forums.

What went right:

  • I’m really happy with how the plants grow and change and move. I think I got the rustling to be pretty convincing, almost like it’s using a physics engine, even though it’s just some sine waves.
  • I think the overall polish level is high, even if the “gameplay” is a bit limited.
  • I’m glad I settled on the concept I did. I love making stuff like this, and the competition was a great motivator.

What went wrong:

  • It took me the whole first day (8 hours) to come up with a concept. (This is typical for me, actually.)
  • I spent the next two days just making the plant system…
  • I didn’t manage to work in any real gameplay. It could probably be a pretty cool puzzle game if I invested some more time.
  • Nobody likes my toy. Boo hoo hoo! … Just kidding. :P

What I learned:

  • I learned a bit of how to use Gamebox. But I didn’t learn it very well or thoroughly, because I was in a hurry.
  • I discovered how cool Garage Band is, although I didn’t end up using it.
  • After the contest, I learned how to record video and audio in Linux using the aptly-named RecordMyDesktop, so that I could record a video of Droplet in action. I need to figure out how to convert it to a format that YouTube supports, though.
  • I learned how utterly irresponsible I can be, participating in a game contest on a whim when I had work deadlines coming up… but it all turned out well in the end, so that’s okay! I have yet again avoided needing to learn a life lesson about personal responsibility. \o/

What I would do differently:

  • Use a different system for drawing the plants. Probably image-based sprites that are scaled and rotated, instead of using drawing primitives. Then I could have gotten more visually interesting trees with less time-consuming coding.
  • Use OpenGL. I think this game could have benefited quite a bit from OpenGL (or even better, OpenVG). The graphics would have been a lot smoother, I could have had more separate branches per tree, and the code would have been simpler to write, even without an image-based sprite approach.
  • Probably not use Gamebox. I’m not saying Gamebox is bad, but it felt a bit restrictive and limited, and trying to learn a new framework while I was in a hurry wasn’t the best idea. More about Gamebox below.

On working with Gamebox:

Gamebox is interesting, and much more mature than its version number (0.0.6 as of this writing) might lead you to believe. The game contest helped flush out several bugs and shortcomings, but Shawn has been super-fast to fix them. I’m sure it will polish up very nicely as he gets feedback from more people.

In general, I am wary of frameworks. Certainly, Rails puts a bad taste in my mouth these days (despite my positive initial reactions two years ago). I tend to find frameworks restrictive, and would much rather be handed a set of building blocks to assemble. For one thing, a framework makes assumptions about what shape I want the final result to have. And I find that many frameworks assume more than they should, and make it too difficult to do things the framework creator didn’t anticipate.

Gamebox suffers from this a little bit, but not nearly as much as Rails does. This is evidenced by the fact that even an unorthodox game like Droplet could be made with it. For instance, a more rigid flamework would not have been able to handle the game objects being arranged radially or having no set appearance. There were some things that I had to work around, though:

  • At the time I wrote Droplet, Levels did not have access to the InputManager, so I had to attach the event hooks to an actor instead. Shawn fixed the issue a day or two after Droplet was finished, though.
  • Gamebox did not support the MouseMotion event type. Shawn fixed this during the contest, though, so I was able to use it. (Thanks, Shawn!)
  • There is no clean way to set the window title. I had to work around this by setting it in Level#draw.
  • Gamebox’s sound support is geared towards fire-and-forget playback, whereas Droplet required the ability to play a sound in a loop and constantly adjust the volume level. Shawn will probably have this fixed within 5 minutes of reading this, though. ;)

There were a few other things that felt like work-arounds to me, but which I think I could have done better if I were more familiar with Gamebox, especially its Behaviors system.

Would I use Gamebox again? Sure! Especially for more conventional games, Gamebox is a great way to get a head start on your game. Even weird stuff like Droplet can be accomodated without a great deal of trouble. And at the rate Shawn is improving it, I’m certain Gamebox will soon be one of the most kickass game frameworks around.

… at least until Rebirth comes out. >;)

Droplet

Screenshot

I’m pleased to present my entry to the RubyWeekend #3 game competition: Droplet. From the README:

Droplet is a small musical toy created by John Croisant in 72 hours over the weekend of June 26-28, 2009 for the third RubyWeekend game creation competition.

The theme of the competition was “A Tiny World”. The inspiration for Droplet comes from photographs that people have commonly described as “tiny worlds”: droplets of water, and the small plants and fungi that grow underfoot.

Initially, Droplet was going to feature both plants and creatures interacting in their tiny droplet world, but I abandoned plans for the creatures due to time constraints. So, what’s left is abstract, rainbow colored plants that sing when you tickle them!

Enjoy!

The controls are simple:

  • Left click anywhere on the edge of the droplet (the large circle) to plant a seed. The seed will gradually grow into a tree-like plant of a random color.
  • Move the mouse cursor around near a grown plant to tickle it and make it sing. The faster and longer you tickle, the louder it sings. The sound each plant produces is randomly chosen from the “data/sounds/” directory.
  • Right click the trunk of a plant to remove it.
  • Click “Help / Credits” to view controls help and game credits.
  • Press Escape to quit the game.

To run Droplet, you will need Ruby 1.8.6 (1.9 might work), Rubygame 2.5.2 (with SDL_gfx, SDL_image, and SDL_mixer support), and Gamebox 0.0.4.

Droplet – End of Day 3

Screenshot

What’s working:

  • Plants have a limited number of generations, so they don’t start to slow everything down.
  • Plant colors, branch length, and various other attributes are randomized per plant for more variety.
  • You can rustle the plants by moving your mouse cursor around them. This makes them wave back and forth for a while, and will eventually make them “sing” louder.
  • I made a custom method for drawing branches, which is a bit faster than draw_line_s, and anti-aliased, but not as roundy at the ends.

What’s not:

  • The algorithm for calculating how much you rustled a plant is a bit dodgy.
  • Still no sound. I’m definitely adding that tomorrow, though. I’ve got a few chime sound loops prepared, and I’ll make some wind/pad loops too.
  • I decided not to use Garage Band due to time constraints and because I wasn’t sure about licensing (since I’d just be making short samples). I’m using some nice chimes and pads from freesound.org instead.
  • I need to a title and instructions and credits in the side bar.
  • Maybe add a way to kill plants that you don’t want anymore?

All in all, though, it’s coming together well. 16 hours left.

Droplet – End of Day 2

A quickie progress update and screenshot of my RubyWeekend game, Droplet.

Screenshot

What’s working:

  • You can click to make a new plant at the nearest point on the circle.
  • The plants grow a bit when you press spacebar.
  • The plants grow and create new branches based on rules.

What’s not:

  • The plants are ignoring their color rules.
  • The plants are “leaning”.
  • The plants are jaggy and slow to draw (when complex). I’ll probably have to stop using Gamebox’s “thick line” method (draw_line_s), and either use regular lines (maybe antialiased) or roll my own code to draw branches. OpenGL would be really nice right now…
  • The plant rules are a bit simplistic and rigid.
  • No sound yet.

The contest period is nearly half over (39:30 hours left as of this writing). I’m going to try to fix the color and leaning issues, then head to bed. The focus tomorrow will be on sound/music.

Update 03:52: Fixed the color and leaning issues. Both were just stupid little mistakes. Here’s an updated screenshot:

Screenshot