Check out my
new game!

jlongster

Why use Gambit Scheme for application development?

July 19, 2009

I have recently been writing Objective-C FFIs for Gambit Scheme, so the timing of mikelevins' post was perfect. I'm glad others are discovering Gambit's coolness, and how easy it makes it to integrate with other systems!

Some of the comments raised a few concerns. First, what are the benefits of integrating Scheme when you'll still have to write a good bit of your application on Objective-C? Second, isn't an FFI like Python's ctypes which dynamically loads libraries and binds functions at run-time better than Gambit's which requires dabbling in C code and compilation?

I've developed pretty strong opinions on these subjects, and I'd like to write about them and how I'm convinced Gambit Scheme is a fantastic choice for development.

Benefits of Running Scheme within Objective-C

First, there's the question of why bother integrating one language in another language. The underlying reason is choice. Usually, I would rather embed Scheme in a foreign environment so that I could simply use Scheme. Sometimes it is wise to learn the foreign environment instead, but typically there's not much payoff for that.

So how do we integrate Objective-C and Scheme, and wouldn't you still have to write a bunch of Objective-C glue?

Since Objective-C provides a nice run-time API, any language capable of interfacing to C is able to provide a nice native Objective-C bridge. Python has done just that, and so has Chicken Scheme. This lets you write almost no Objective-C code to program Cocoa-heavy applications.

For my purposes, it's ok to create a few classes in Objective-C which dispatch events off into Scheme land. I'm not doing anything UI-heavy (more 3d applications), so I don't need a full Objective-C bridge, although that would be cool (and is possible if someone wants to write it). Thus, Gambit's ability to inline Objective-C allows me to "get by" by creating a few FFI's which allow me to read information from Objective-C objects. For example, creating an FFI for the UITouch object is a piece of cake:

(define UITouch-tap-count
  (c-lambda (UITouch*) int "___result = ___arg1.tapCount;"))

(define UITouch-timestamp
   (c-lambda (UITouch*) NSTimeInterval "___result = ___arg1.timestamp;"))

(define (UITouch-location touch)
  (if (current-view)
      (cons (%%UITouch-location-x touch (current-view))
            (%%UITouch-location-y touch (current-view)))
      (error "No current view available")))

(define %%UITouch-location-x
  (c-lambda (UITouch* UIView*) int "___result = [___arg1 locationInView:___arg2].x;"))

(define %%UITouch-location-y
  (c-lambda (UITouch* UIView*) int "___result = [___arg1 locationInView:___arg2].y;"))

Most of my application code is still Scheme code. Gambit Scheme gives you the choice how far you want to go with your FFIs - whether it's a full bridge or a quick interface.

Now there's a problem: debugging. Cocoa Objective-C is meant to be packaged up into an app and run. This makes debugging difficult; in fact, I would guess that it's impossible to run a Python app made with py2app in Python's debugger, PDB. However, by way of Gambit's remote debugger, debugging Scheme within Cocoa Objective-C is no problem at all.

Of course, the main benefit is that you get to use Scheme!

Gambit Scheme's FFI

Let's talk about Gambit Scheme's FFI. There are two kinds of FFIs: one which defines C interfaces at compile-time and the other which loads libraries and binds functions at run-time. Gambit's is the former.

There are many advantages to compiling C interfaces instead of loading them at run-time:

I find that writing FFIs this way is much easier, faster, and portable. Take the short FFI in the previous section, for example. Because it uses the special Objective-C syntax, you couldn't do that so simply if using the dynamic library approach.

Now, maybe I'm biased because I like C and am very comfortable with it. But if you are writing C FFIs, you probably should be comfortable with it too.

Why Gambit Scheme in particular?

I use Gambit Scheme because it is a very well-implemented system. It is not only really fast and portable, but the code itself is well-written and abstracted. I enjoy the community of number crunchers and other really smart people.

Lastly, Gambit never seems to restrict you when you are trying to do something, meaning that it's possible to write your FFIs, compile/load your code, profile, use a REPL, etc. in all sorts of ways that most likely means it will work smoothly in strange environments (such as the iPhone). I really think this is a sign of a well-implemented system. I've never been able to take a system so far and have it perform dutifully. Try running Python on the iPhone and getting a REPL prompt on your computer.

Comments are not implemented yet. In the meanwhile, send me an email.