Code completion for dynamic languages

2007-02-02, , , Comments

Here’s an interesting article in which Huw Collingbourne describes his frustration with trying to program a smart code completion system for Visual Studio. The problem being, the code in question is Ruby. One particularly juicy quotation reads:

Ruby is a so-called “dynamic” language, which is a polite way of saying that it’s hugely unpredictable.

He goes on to explain:

A Ruby program is so dynamic that you can never be sure what it is up to from one moment to the next. To take a simple example, when you write some stand-alone functions into the editor, those functions get bound into the base class of the entire Ruby class hierarchy. That means that every single Ruby class automatically “inherits” them - and the IntelliSense system is expected to know about it!

Despite overtly grumbling about dynamic languages, the author does a good job of promoting them. Software is supposed to be soft and dynamic languages help keep it that way. Everything is open. Everything can be queried. Everything can be adapted.

Emacs Python mode

My preferred IDE is emacs — whatever language I’m using. It has a particularly nice Python integration. Here’s how it works:

  • Pull up a full-screen window
  • Split the window vertically
  • Use one side for the code you’re working on
  • Use the other side to run an interpreted Python session
  • Switch sides as desired

I continually select regions of code to execute. I continually step into the interpreter and use the Python help command to get help on modules and functions — including the ones I’m creating right now. I rework a function in one window then exercise it in the other. I sketch experimental code, run it, rub it out.

Collingbourne says:

Creating real IntelliSense is much harder. The only way to do it properly is to analyse the code much as the Ruby interpreter itself does. The big difference is that the interpreter only goes into operation when a program is complete …

He spots the answer in one sentence — to do it properly, you do have to hook into the interpreter and its powers of reflection — then misses the point in the next. You just have to run the interpreter alongside the code you’re developing, like emacs Python mode does.

A cheat’s guide to code-completion

Collingbourne also exposes some code-completion systems as “cheats”.

Some code-completion systems solve this problem in a cunning way - they cheat. Instead of working out what type of object x is at any given moment, taking into account all the difficult stuff such as its scope, inheritance and context, they work alphabetically. If someone enters a dot followed by the letters “my”, they drop down a list of names such as “my_method”, “my_othermethod” and “my_random_guess” whether or not those methods have anything to do with the object in question.

Well, I’m happy to cheat using emacs in this way. The ALT-/ combination uses alphabetic completion and I use it more than any other key sequence, whatever document I’m working on. More often than not, it does the right thing. As usual, simple solutions are better.