Anyone else using Common Lisp in their game?

Started by
29 comments, last by pTymN 16 years, 3 months ago
The problem most people have with Lisp is that they ask "why bother learning Lisp?" and they expect an answer that pertains to practical software development directly. For any other language Foo, you learn Foo because you can understand circumstances in which you might actually want to use Foo to do a particular task more effectively.

I'll probably get my Smug Lisp Weenie Club membership revoked for this, but I'm going to spill the dirty, evil secret: learning Lisp won't do shit for your real-world development directly, because you're not going to use it.

That's why people give out all the magical-sounding "hand-wavery" answers when talking about Lisp. There are far better functional languages to use for practical, real development, so from a strictly pragmatic standpoint, learning Lisp is a dead end.


However, I for one still strongly agree with the idea that learning Lisp - and sticking with it through the inevitable moment of enlightenment - is still a good thing. Why? Why is this a useful expenditure of energy when there's no direct benefit and you'll never use the language?

Lisp isn't one of those languages you learn for its own sake. The language itself (or, more correctly, the language family) is actually pretty weak by modern standards. Instead, it's worth learning for the philosophy.

The structure of Lisp ("all those damn parenthesis") is precisely what makes it a great language. It represents a powerful optimum balance between several factors: code has an atomic, uniform representation; code is human-readable and human-parseable; and complex systems can be architected with extreme ease.

Atomic and uniform representations of code also appear in machine language, but at the expense of human readability. Readability abounds in many higher level languages (c.f. Python and the "executable pseudocode" philosophy) but at the expense of uniform internal representation.

Finally, if there exists a language in which it is easier (than in Lisp) to clearly define deeply nested layers of abstraction to solve complex problems, I personally am not aware of it.


Learning Lisp is not about the practical benefits. You won't get a kick-ass library. You won't get a lean, mean runtime. You won't get crazy portability. You won't get a beautiful, pleasant IDE. You won't even get a language you're going to use on a regular basis, unless you're an emacs user.

What you will get is a perspective on optimizing some of the most complex and difficult to manage aspects of language design. That perspective can only come from experience with using the language; just looking at it from the outside is not enough. Compare this to a lot of software design questions: for a lot of beginners, it's hard to see why globals, goto, and whatever else are bad things to abuse. But with plenty of experience, the insight becomes obvious.

Training and attaining that insight is exactly why you should learn Lisp. The lessons of Lisp can be adopted and carried over into most other languages - and that's where you will see the practical benefits.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Advertisement
Quote:Original post by AndyGeers
Quote:Original post by capn_midnight
No, see, you're still doing the hand waivery thing. You have yet to mention anything unique to Lisp that makes learning Lisp a constructive use of time. Sure, the proliferation of functional programming concepts may be due to some pioneering that Lisp did, but we don't learn ALGOL over C these days.


If you want some well articulated arguments for using Lisp, Paul Graham's essays are a great place to start

I've read some of his papers before, and after reading a few more now, I have to say I think that he really doesn't know much about what he's talking about. He makes a LOT of the same hand-waivery assertions, like "the desktop is dead" and "web apps are a good idea". He derides Microsoft with an almost Slashdot-esque fervor, which is a big symbol to me that he isn't really interested in evaluating things for their *merits* as much as he is for how he looks *using* things. Here's a choice statement on Apple "Their victory is so complete I am now surprised when I see a Windows PC". He simultaneously derides managerese and spews it at every turn. He's so much a navel gazer that I can't trust anything he says.

That said, his articles on Lisp basically amount to "Lisp *is* popular, because so many languages are adopting its features". I wouldn't give all the credit to Lisp in this case, because Lisp still has that infernal syntax that is completely unnecessary. Also, Lisp has only remained relevant because of additions that it gleaned from other systems, in particular an object model borrowed from Smalltalk. Ultimately, he argues for functional programming, and not for Lisp itself. Whoopdi-doo, that's what I've been talking about all day, "why Lisp in particular"?

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

Quote:Original post by ApochPiQ
The problem most people have with Lisp is that they ask "why bother learning Lisp?" and they expect an answer that pertains to practical software development directly. For any other language Foo, you learn Foo because you can understand circumstances in which you might actually want to use Foo to do a particular task more effectively.

I'll probably get my Smug Lisp Weenie Club membership revoked for this, but I'm going to spill the dirty, evil secret: learning Lisp won't do shit for your real-world development directly, because you're not going to use it.

That's why people give out all the magical-sounding "hand-wavery" answers when talking about Lisp. There are far better functional languages to use for practical, real development, so from a strictly pragmatic standpoint, learning Lisp is a dead end.


However, I for one still strongly agree with the idea that learning Lisp - and sticking with it through the inevitable moment of enlightenment - is still a good thing. Why? Why is this a useful expenditure of energy when there's no direct benefit and you'll never use the language?

Lisp isn't one of those languages you learn for its own sake. The language itself (or, more correctly, the language family) is actually pretty weak by modern standards. Instead, it's worth learning for the philosophy.

The structure of Lisp ("all those damn parenthesis") is precisely what makes it a great language. It represents a powerful optimum balance between several factors: code has an atomic, uniform representation; code is human-readable and human-parseable; and complex systems can be architected with extreme ease.

Atomic and uniform representations of code also appear in machine language, but at the expense of human readability. Readability abounds in many higher level languages (c.f. Python and the "executable pseudocode" philosophy) but at the expense of uniform internal representation.

Finally, if there exists a language in which it is easier (than in Lisp) to clearly define deeply nested layers of abstraction to solve complex problems, I personally am not aware of it.


Learning Lisp is not about the practical benefits. You won't get a kick-ass library. You won't get a lean, mean runtime. You won't get crazy portability. You won't get a beautiful, pleasant IDE. You won't even get a language you're going to use on a regular basis, unless you're an emacs user.

What you will get is a perspective on optimizing some of the most complex and difficult to manage aspects of language design. That perspective can only come from experience with using the language; just looking at it from the outside is not enough. Compare this to a lot of software design questions: for a lot of beginners, it's hard to see why globals, goto, and whatever else are bad things to abuse. But with plenty of experience, the insight becomes obvious.

Training and attaining that insight is exactly why you should learn Lisp. The lessons of Lisp can be adopted and carried over into most other languages - and that's where you will see the practical benefits.


this is a much better reply and exactly what I mean about "be articulate enough to express what you mean."

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

The common sentiment seems to be that Lisp has great ideas embedded in it, but has practical limitations that make it useless. There are some reasons that I find Lisp preferable to python, lua, or other common scripting languages:

1) The implementation that I use is compiled to native code.

Corman Common Lisp is Win32 only, but then so is DX9. While not free, CCL costs $250 and even the eval version comes with full source to the lisp runtime. Roger Corman wrote C/C++ compilers for many years before writing CCL, and it shows. CCL talks natively to COM objects, and can compile to DLL or EXE trivially. Many other languages that are flexible enough to be useful as a scripting language are not compiled, so they do affect performance for any sort of beefy game object behaviors.

2) Using a data<==>code language is MUCH preferable to any sort of convoluted XML parser scheme.

If anyone has played with CEGUI's layout files or other XML systems that try to incorporate basic programmability into XML, you know how painful it is to use those systems. It is also painful to write and maintain an data driven system that has some programmability in it. What is preferable is to have some sort of data driven system that pushes data out, rather than one that has to be coaxed through a VM that pushes the data out. Better explanation than I can give.

3) No other language that I've seen makes it as easy to mix data and code.

Like many indy developers, I have put off writing tools that write the data files that the game will consume. The fastest way to get up and running was to have a text file format that would allow me to enter structured data in a concise format. Sexp > XML for readability, imho.

4) The ability to use macros to hide complexity and create a DSL is exactly what I want.

(offset '(1000 100)	(make-carrot))


If I really want to see what that code is doing, its not that hard to macroexpand-1 it.

(macroexpand-1     '(offset '(1000 100)    	 (make-carrot)))(LET ((*OFFSET*             (V+ '(1000 100) *OFFSET*)))     (MAKE-CARROT))


The bonus is that dynamic scoping allows me to refer to *offset* at the lowest levels of the code, right before geometry is pushed to the C++ side, and I can always assume that *offset* is 0,0 (no effect) unless someone higher up the call stack decided to modify *offset*. Sure, DSLs add complexity when you must debug the DSL, but my goal is to keep the DSL simple enough for a non-programmer to use it, and I need lisp's flexible approach in order to spend little overhead maintaining the DSL as needs expand.

Quote:Original post by Rebooted
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.


It sure is. Heck, I've run into people who somehow don't like Python syntax. ;)

Quote:Original post by pTymN
3) No other language that I've seen makes it as easy to mix data and code.

Like many indy developers, I have put off writing tools that write the data files that the game will consume. The fastest way to get up and running was to have a text file format that would allow me to enter structured data in a concise format. Sexp > XML for readability, imho.

4) The ability to use macros to hide complexity and create a DSL is exactly what I want.

(offset '(1000 100)	(make-carrot))



But really, you can do DSLs in any language that supports (a) eval() and (b) anonymous data structures. Python is a prime candidate:

# <foo><bar /><baz quux = 'spam'>ni!<bar /></baz><bar /></foo>Foo(bar(), baz('ni!', bar(), quux = 'spam'), bar())


Well-formedness is verified by eval:

try:  data = eval(file('Foo.pml').read())except SyntaxError:  # not well formed


Validity is verified by the class constructors. You can even use reflection (or perhaps more eval()ing) to build something equivalent to the XML Schema concept.

Then to actually do something, just call some function (maybe even __call__) on the root.

It's not as convenient due to the less-regular syntax, but this kind of thing is not normally the bulk of your work, and having lots of syntactic "marking" is very convenient and practical for basically everything else.

But anyway, there's "a text file format that would allow me to enter structured data in a concise format", and you don't have to pull in an XML parser module.
Quote:Original post by Zahlman
[...]But really, you can do DSLs in any language that supports (a) eval() and (b) anonymous data structures. Python is a prime candidate:

# <foo><bar /><baz quux = 'spam'>ni!<bar /></baz><bar /></foo>Foo(bar(), baz('ni!', bar(), quux = 'spam'), bar())
[...]
Can you modify the Python parser via python so that it will interpret the statement "<foo><bar /><baz quux = 'spam'>ni!<bar /></baz><bar /></foo>" without having to perform manual translation as you did in your example? It's not trivial in Lisp, but it doesn't involve writing a full parser, either. The Common Lisp reader and parser are both open for modification, which means you can let it do a LOT of work for you.

Your example creates a language that mimics the semantics of one language using the syntax of another, which can make the DSL very difficult to use. In Lisp, you can construct both the syntax and semantics to match the language you're modeling. Unfortunately my internet is practically dead at the moment, so a decent example will have to wait until it is fixed.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Neat! Python's syntax is definately one of its strengths, and you are right that eval is really all that's necessary. Would you agree that XML or Sexp or equivalent that is run through a compiler is generally going to be easier to maintain? I feel like compilers, while buggy, tackle a very difficult problem of meaning and context that is often overlooked when someone starts their own XML based game data loader.

Not directly related to the question, but I'm taking the consequence of the Tenth Rule and writing a Lisp interpreter to use for my scripting language. Yes, yes, I know, I'm reinventing the wheel, but I'm having fun with it - if I expected ever to finish the game I wouldn't do this. But I really got quite a bit of pleasure out of defining some Lisp basics and then defining a for loop in my scripting language, using recursion.
To win one hundred victories in one hundred battles is not the acme of skill. To subdue the enemy without fighting is the acme of skill.
I have been using CL for gamedev for some time, mostly 2d strategy and oldskool arcade with
PAL

Reasons I stick with CL, even after learning "superior" languages like Haskell or Ocaml:

- CLOS. Multiple dispatch and method combinations fit nicely in many problems.
- Live environment and introspection. It is fast to test things out, writing editors and handling resources is easy. SLIME is also very nice.
- Usually people mention macros first but to me they are not that important. Funnily though I still miss them in other languages.
- Very good - adequete performance.
- Sexp syntax. Very easy to edit when using Emacs and Paredit.el
- Portable (C)FFI, I get sourcecode compatibity across most implementations and OS's without any ugly C stubs.

Bad things:

- There is still no cheap and adequete Windows compiler. SBCL is not stable yet, CLisp is slow and Corman is not too standards compliant.
- EXEs build with SBCL tend to be large. Might be a problem for smaller games
- I might want a more fascist module system, something like PLT Schemes maybe. I'm not just sure if it would work well with interactive/incremental development style.

Personally I found the old argument about learning lisp because of its mind expanding properties a bit silly since to most people it seems to mean learning the basics of Scheme/CL and macros and then moving on to the next language. I use CL primarily because it is a very practical tool for some (all? ;) ) tasks, if I were after elegance I would use Scheme or Haskell.
That is not say that I don't found CL to be more elegant than most of the other languages...
---from www.yellow-hut.com/blog

This topic is closed to new replies.

Advertisement