Anyone else using Common Lisp in their game?

Started by
29 comments, last by pTymN 16 years, 3 months ago
My game is using Corman CL 3.0 for all the level layout, game object behaviors, and high level control of the graphical effects. I was interested in starting a discussion with any other developers who have discovered that modern hardware isn't finding a 40mb runtime overhead to be anything bad. It almost seems that the widespread adoption of .net for games in the indy community should make lisp also seem to be a more likely choice. Both have a GC and can generate code at runtime. Both can hot reload code in a running application. I've been delighted with the results in my game for rapid prototyping. About the only pain is having to constantly update my FFI interface for lisp to access more features of the C++ based libraries that I'm using. (Gamebryo, FMOD, FantastiqUI, Chipmunk)

Advertisement
Lisp isn't used for three reasons:

First, as far as I'm aware, there are no good IDEs that help make sense of the parenthesis. I'd love to use Lisp if I could find an IDE that made it as easy as other languages, but the huge level of nesting that necessarily occurs makes reading large code very difficult. 100 lines of Lisp code could be one expression or 100, and there isn't any easy way to tell which it is without dissecting the whole thing. Indentation helps, but not enough - it makes small sections of code easily readable, but it can only help so much.

Second, common lisp is a behemoth, and is way, way larger than it needs to be. Not only is it overly large, but it omits a lot of things considered standard these days (such as just about everything the .Net framework does). It's great that every modern implementation provides custom solutions, but that just fractures things worse. You could always import functions from elsewhere, but they won't ever mesh properly with the rest of the code because Windows API (for example) doesn't follow the same philosophy as Lisp.

Third, Lisp is difficult. Well, maybe not difficult, but easy to screw up. Being able to mix object-oriented, procedural, and functional code might be good for flexibility, but it's not so great on maintainability. Throw in that the code can rewrite itself (at your direction, but still...) and it's a scary thing for large projects.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Your objections are silly. Perl has a difficult syntax, and it is highly used. .NET is a large runtime overhead, and it is used. C++ allows you to shoot yourself in the foot with a somewhat complex underlying system for virtual methods and vtables and this pointers that can change based on whether the code is in the base class's constructor or parent class's constructor, and people get work done with it.

Quote:Original post by pTymN
Your objections are silly.
Were you actually interested in discussion, or is this thread just advocacy disguised as discussion?
As an experiment, I'm currently working on a simple game in Haskell (++ OpenGL/Glut). I have been playing around with Scheme before, but only for quick math related problems, not to create 'real' applications.
Since we're talking FP: I've heard some good things about F#, but I'll stick with Haskell for now.
Quote:Original post by pTymN
[...]Perl has a difficult syntax, and it is highly used.[...]
That was not one of my objections. Perl is not difficult to visually parse, it is difficult to understand because there are many details. Lisp is very difficult to visually parse, which is something a good IDE could help considerably with. Unfortunately, there are no such IDEs that I am aware of.
Quote:[...].NET is a large runtime overhead[...]
That was not one of my objections. .Net is large, but every feature in it serves a very specific purpose applicable to modern paradigms. Lisp is large, and half of it is no longer relevant, and the other half is pretty much only computational (meaning it has very limited functionality for communicating with outside world).
Quote:[...]C++ allows you to shoot yourself in the foot [...], and people get work done with it.
That was not one of my objections, but of the three, it was closest. Plenty of people get work done in C++, but plenty of people also write horrible overcomplicated code that is impossible to read and even more difficult to maintain. All the Lisp code I've found that wasn't explicitly a tutorial was along the same lines, and even that horrible code doesn't even abuse Lisp to it's fullest. Mix in all 3 paradigms, code modifying itself, and DSLs that make a syntax completely change meaning, and you've got something difficult NOT to make horrible code with.
It's one thing to make it work, and quite another to make maintainable code that is pleasant to work on months later. I don't think it is impossible to write decent code in C++ or Lisp, but I haven't ever seen any in a large application.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Original post by Extrarius
First, as far as I'm aware, there are no good IDEs that help make sense of the parenthesis.
Not even SLIME or Lispworks?

Quote:Being able to mix object-oriented, procedural, and functional code might be good for flexibility, but it's not so great on maintainability.
Why? I would have thought expressive languages lead to reduced code size and easier-to-understand programs that attack the problem more directly.

I'd imagine debugging a program that makes heavy use of procedural macros would be a nightmare though. Scheme's macros, which respect the semantics of programs they are operating on, are much better in this regard. Something I think is essential is an IDE that can tell you through highlighting which identifiers refer to variables and which to macros, though.

The problem with CL in my opinion is a lack of abstraction. No proper module system, macros don't respect bindings, raw symbols are used instead of ADTs, ... This is exactly the problem that typed FP languages like ML and Haskell attack. I don't think it's practical to do extensive higher-order programming or build combinator libraries without an expressive static type system either, and for me this is were much of the power of FP comes from.

I think F#, which is a dialect of ML targeting .NET, ought to be very suited to making a game.
Quote:Original post by Rebooted
Quote:Original post by Extrarius
First, as far as I'm aware, there are no good IDEs that help make sense of the parenthesis.
Not even SLIME or Lispworks?[...]
It's been a long time since I've used Lisp, but using google to locate some screenshots of each, I don't see how either is any better than a generic 'programming editor' with respect to making the onslaught of parenthesis more visually distinguishable from eachother. 5 black curves in a row doesn't exactly tell you much about what is going on. At the simplest, I think something like coloring the text's background based on the nesting depth would help tremendously with making code readable. I should be able to look at a block and tell where one expression/statement starts and the next one ends, as it is trivial to do in most language, but in Lisp, since everything is uniform in appearance, it all blends together.

Quote:[...]
Quote:Being able to mix object-oriented, procedural, and functional code might be good for flexibility, but it's not so great on maintainability.
Why? I would have thought expressive languages lead to reduced code size and easier-to-understand programs that attack the problem more directly.[...]
Because programmers get messy - few people have enough discipline to stick to ideals forever, and as soon as you start indiscrimintely mixing the many possibilities, it'll be hell to know what is going on. Big code is difficult enough to understand without having to also figure out what type of code it is.

Quote:[...]The problem with CL in my opinion is a lack of abstraction.[...]
Even basic CL has a package system built in, and it uses : to dig down into them, which makes it fairly clear what is from where. Also, have you ever heard of CLOS or MOP?
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Original post by Extrarius
5 black curves in a row doesn't exactly tell you much about what is going on. At the simplest, I think something like coloring the text's background based on the nesting depth would help tremendously with making code readable. I should be able to look at a block and tell where one expression/statement starts and the next one ends, as it is trivial to do in most language, but in Lisp, since everything is uniform in appearance, it all blends together.


In vim (and regardless of the language), moving the cursor next to a bracket will highlight it and its matching open/close.
Quote:Original post by Extrarius
I should be able to look at a block and tell where one expression/statement starts and the next one ends, as it is trivial to do in most language, but in Lisp, since everything is uniform in appearance, it all blends together.

I also find Lisp syntax harder to read. I guess syntax is completely subjective though, some Lispers seem to love it.

Quote:At the simplest, I think something like coloring the text's background based on the nesting depth would help tremendously with making code readable.
That sounds like a pretty good idea. I think I've seen something like that for emacs, maybe.

Quote:Even basic CL has a package system built in

From what I remember/know about the CL package system it seems to just provide crude namespace management. I could be very wrong.

Quote:Also, have you ever heard of CLOS or MOP?

Yes, but CLOS don't provide much in the way of data abstraction. If you want to represent, say, a colour in Lisp, you'll probably use a symbol. In ML/Haskell you'd almost certainly define a new type, building layers of abstraction and making program development more tractable.

A better example: if you were building a web app in Lisp, you'd represent HTML elements as symbols. In Haskell, you'd work at a higher level of abstraction, constructing and composing HTML documents as values of an algebraic data type with an interface that matches the DTD. As a result, you get a static guarantee that all constructed documents are well-formed and valid with respect to the DTD. Other things you could express include the invariant that GET requests don't modify the database.

This topic is closed to new replies.

Advertisement