While I know that functional languages aren't the most commonly used for game writing, there are a lot of benefits associate with them that seem like they would be interesting in any programming context. Especially the ease of parallelization I would think could be very useful as focus is moving toward more and more processors.

Also, with F# as a new member of the .NET family, it can be used directly with XNA, for example, which lowers the threshold quite a bit, as opposed to going with LISP, Haskell, Erlang, etc.

If anyone has experience writing games with functional code, what has turned out to be the positives and negatives? What was it suited for, what not?

Edit: Finding it hard to decide that there's a single good answer for this, so it's probably better suited as a community wiki post.

I'm sure you're right about the original Rogue being in C, since it was written on Unix, but there are certainly several Rogue clones in Lisp: cl-user.net/asp/root-dir (not the direct Game link, it had so many special characters it seems to have broken linkage).
–
CyclopsJul 27 '10 at 15:52

10 Answers
10

Dave mentions some excellent points, although I have to point out that Haskell has solved both of his issues. Statelessness can be bypassed using the State monad (EDIT: not really -- see below for details), and sequencing can be handled using the IO monad (EDIT: or any other monad, for that matter...).

The challenges you'll have (and that I've had trying to learn both games programming and Haskell), are more along these lines. (These are all Haskell-specific, since I really haven't gone deep with any other FP languages yet.)

FP Learning curve: FP requires a complete shift of mindset from iterative programming. Learning to think in terms of maps and folds rather than loops requires a mental workout if you're not used to it.

Mathy learning curve: Haskell is both blessed and cursed by the mathematical sophistication of its designers, because after you learn the basics of FP, you're stuck with monads, morphisms, arrows, and a whole host of other considerations which, while not tough in and of themselves, are very abstract.

Monads: these puppies are not particularly hard to wrap your mind around, especially if you accept Eric Raymond's statement that they are a "a hack to turn function composition into a way of forcing the sequencing of function calls." Unfortunately (though this is getting better as Haskell gains in popularity), many explanations of monads either aim way over the head of most programmers ("they're monoids in the category of endofunctors!"), or at a completely unhelpful analogy (e.g., Brent Yorgey's distressingly accurate example, "monads are like burritos!" You think he's kidding? That nobody could ever come up with such a goofy analogy in a tutorial? Think again.)

Ecosystem: If you've managed to get beyond all the other bumps in the road, you will be cheek-and-jowl up against the practical day-to-day reality of working with a still largely experimental language. God help you when you get here. Here's where I started seriously jonesing for Scala, or F#, or some other language where there is at least some guarantee of interoperability with other libraries. Once upon a time, I got Haskell to link and load the OpenGL libraries in Windows. That made me feel pretty good. Then the OpenGL bindings were re-released, and broke everything I had done. That's life in Haskell-land. Honestly, it can be a pain. You want a wrapper for the Bullet engine? It's in Hackage -- as abandonware from November of last year. You like Ogre3d? Hackage has bindings to only a subset of the library. Bottom line is that if you stick to a language off the beaten path for game development, you will spend a lot more time working on basic plumbing than you would if you just followed the herd and stuck with C++.

The flip side of this is that things are rapidly improving. And it really all depends on what you want out of the experience. You want to build a game and put it on your website to seek fame and fortune? Stick with C++ or Python. But if you want to learn something new that will require you to innovate your processes, try a functional language. Just have a lot of patience with yourself while you're learning.

Edit (one year later): Now that I've studied the State monad more, I realize it's not a particularly good solution for state that is intended to persist outside a particular function. The real solutions to statelessness are found in Haskell in IOVar, ST, MVar (for thread safety), or through something like Yampa, which uses Arrows and FRP to manage internal state that is nonetheless hidden from the developer. (This list is in order of difficulty, though the first three are not particularly difficult once you understand monads.)

Some good thoughts there, even if fairly Haskell specific, I think those are thoughts that apply to most fringe languages. As you mentioned briefly, I think this is where languages like F# have the potential to shine. Handling state/UI with C#, for example, and then have logic modules in F# for algorithms like potentially path finding, AI, etc.
–
McMuttonsJul 23 '10 at 5:12

I've spent the last year developing a commercial game engine in Haskell, and for us, the experience has been overwhelmingly positive. Our game world is complex, and Haskell has made it easy to model the process of conversion from an editor format to a game engine format. I would hate to think what that code would look like in an imperative language.

Space leaks have come up on occasions, and while they've caused a bit of trouble, in the general scheme it has been a small amount (for example as compared with finding deadlocks in a similarly sized Java projects), and once they were fixed, they stayed fixed.

We are using FRP similar to Yampa, and there's certainly a learning curve associated with it, but once that's over with, the experience is very positive. Libraries have not been a problem for us - everything we've needed has been available. Garbage collection delays were a particular issue since it's for an embedded platform. We've used some C++ to manage the animation. Performance has also been an issue with this being an embedded platform (= slow processor). We've done some C and we're also looking at emerging Haskell technologies like accelerate. The C++ animator was a design decision early on and the places where the code is too slow are only very small areas. In the long run, we want to translate all our C to Haskell.

Haskell has made a difficult job easy, and all the difficulties I've just mentioned have been tiny in comparison to the large amount of complex code we've produced that is clean, maintainable and pretty much unbreakable. Parallelism will be an issue in game development very soon, and we are extremely well placed to deal with it. Some of what I've said may not apply to small projects, because we are in this for the long haul, so start-up costs like learning curves, library support, etc, are much less of an issue.

It's approaching 5 years since you posted this answer; would you be willing it to update it? How has the commercial game engine worked out? What pieces proved to be valuable? Have you been able to take advantage of parallelism like you hoped?
–
Levi MorrisonApr 27 at 21:29

Not really an answer to anything, but I feel like a discussion of game programming in functional languages is incomplete without mention of Functional Reactive Programming (FRP) - http://www.haskell.org/frp/ - and its most common implementation (I think?), YAMPA - http://www.haskell.org/yampa/.

I'm currently working on a game in Haskell. I can't speak for functional programming in general, but for Haskell specifically:

The Good

These are the awesome things that make Haskell really stand out.

Purity means that reasoning about your code is a lot easier. You don't have to worry about the "current" value of a variable or whether using a given function will conflict with your global state in some way. It also means that parallelism and concurrency are far easier to work with (and in many cases, trivial). These things can be a godsend to game developers.

Haskell makes it very easy to write at a very high level using abstractions of your own creation. It's often easier to write very generic code than specialized code in Haskell, and the benefits of this manifest themselves in less development time and easier code comprehension. It's more true in Haskell than in any other language I know of that using an interface is like using an entirely new language (while still keeping the benefits of the rest of the Haskell ecosystem). What most languages call language features, Haskell calls a library, and it doesn't feel forced. If you ever find yourself reasoning about your game in psuedocode, you could probably just write a simple interface and make it real code, and it's usually worth it to do so.

This might conflict with other answers, but Haskell is better at handling imperative code than any other language I know of. The constraints of purity mean that Haskell has a separation between the concepts of "evaluation" (reducing expressions) and "execution" (performing side effects). You can control when and how side effects are performed with an ease unparalleled by the so-called "imperative" languages. Despite what I said about purity earlier, some C bindings are still very imperative (OpenGL, I'm looking at you), so this fine-grained control over imperative code is very welcome. Even the most seasoned of C programmers are likely to appreciate it once they get used to it.

GHC generates pretty fast binaries. They are not as fast as binaries generated from common C compilers, but are within an order of magnitude, and are far faster than what you would achieve with an interpreted language. Even if you can't write your game in other high level languages like Python because it would be too slow, there's a good chance you can do it in Haskell.

Despite there not being many game-related libraries in Haskell, as noted under "The Bad" below, the Haskell foreign function interface is the easiest I have ever used. You can bind to C by writing almost exclusively in Haskell.

The Bad

These are things that are not good but can be worked around without too much effort.

The time and effort needed to learn Haskell can be fairly high if you are very used to working with non-functional languages. The language itself isn't very difficult, but when you factor in common language extensions and the huge amount of libraries (remember, many things you might consider language features in other languages are libraries in Haskell), it looks much more ominous. In my opinion, it's worth it, but others may disagree.

Some people complain about laziness a lot. If you know what you're doing, you will not cause space leaks that are difficult to track down (I have not created a space leak in a couple years now), but beginners have a lot more trouble with this. It would be foolish of me to shoot these people down and claim that this is not a problem, but I will assert that it's a problem that is easily solved with experience.

There are not many great libraries for making games in Haskell, and not many Haskellers write games in it, so it's difficult to find resources and help on this matter.

The Ugly

These are things that would take considerable effort to overcome.

If you are writing a resource intensive game, GHC's garbage collector might bite you pretty hard. It's a generational, stop-the-world GC, so every once in a while you might drop a few frames. For some games this is okay, but for others it's a major problem. I and some other game developers using Haskell would like to see a soft-real-time GC implemented for GHC, but no effort is being spent on that yet, to my knowledge. Currently, I'm not worrying about working around this (and haven't seen any dropped frames from it yet), but at least one other team has resorted to putting their main rendering loop into C.

@Wei Hu: I am a huge fan of the idea of FRP and have researched it fairly extensively myself, including creating a few different semantics and writing a few implementations. The best implementations still have severe semantic and/or implementation bugs. I would say that they are viable for game development, but not with many advantages (yet) over traditional approaches.
–
Jake McArthurAug 12 '10 at 19:45

Unfortunately, that isn't actually true. The concurrent GC was found to be too complicated to justify the small overall improvement, and it hasn't been merged in.
–
Jake McArthurJul 8 '14 at 13:25

@JakeMcArthur AFAIK there's a way to convert haskell code into c-code. Although I've never tried it, but I guess this'd mean throwing away GC in favor of scope bound variables, thus increasing performance. Have you anything to comment for this?
–
Hi-AngelJun 23 at 22:37

Using functional languages can be a huge advantage in most types of software development, mostly because they cut development time considerably. I can see a big potential for writing a server backend to a game, or the AI and logic layers on the client, in a functional language. And as everyone knows, LISP has been used for NPC scripting.

If I were to try to write the frontend of a game in a functional language, I would definitely go for Objective Caml, which is a hybrid language. It's an ML descendant, and allows to mix iterative and functional styles, has an objective system with stateful objects. (Caml is the language that F# is modeled on.)

OpenGL bindings seem to work flawlessly and people have been making games in OCaml for a long time. The language can be compiled and is potentially very fast (it famously won over C in some benchmarks a long time ago, don't how things stand now).

There are also tons of libraries. Everything from computer science stuff to bindings to all kinds of libraries.

As for benefits, check out Clean Game Library (http://cleangl.sourceforge.net/) and check the platformer game. Once you get your head around the syntax (I encourage you to try) you'll see the sheer elegance of the constructs and how closely the source maps to the concepts they're expressing.
As an added bonus, the abstraction of state, and the necessity to explicitly pass state around, makes your code much more multicore friendly.

On the other hand, it requires a major paradigm shift. A lot of what you're used to do without thinking about it suddenly doesn't exist anymore and you'll be puzzling how to solve it, simply because you're thinking in the wrong patterns.

You can write your code in C/C++ and use an embedded language such as Embedded Common Lisp for your scripting. Although getting these to compile on a different platform might be difficult. You might look at Lisp In Small Pieces in order to learn how to write your own scripting language. It's really not that hard, if you have the time.

the positive would be performance and portability and the negative would be managing complexity, game today are seriously complex and need tools or programming language that can manage the complexity better, such as object-oriented methodology or generic programming which is hard to implement in functional programming language.

Statelessness of functional languages: The idea in games is that each entity has a state and this state is being modified from frame to frame. There are mechanics to mimic that behavior in some languages (for example functions with a "!" in plt scheme) but it feels kind of unnaturally.

Order of execution: In games some code parts depend on other code parts to be finished before executing. Functional languages generally don't make any guarantees about the order of execution of the arguments of a function. There are ways to mimic this behavior (for example "(begin..." in plt scheme).

Feel free to extend this list (and maybe to add some positive points^^).

Order of execution might vary in non-strict language like Haskell but it doesn't cause create problems for code parts that depend on other code parts. You can think of it as evaluation on demand. A computation isn't performed until the result is needed. I think the only way it might cause you grief is in terms of performance. For example, it might make it hard to get good caching in some cases because you won't have control over the ordering on the evaluation other than specifying the dependencies between computations.
–
Jason DagitJul 26 '11 at 6:07

I have written simple games in LISP and it was fun but not something I would recommend. Functional programming is all about the end result. So it's very handy for processing data and making decisions but I found it made it hard to do simple clean code like a basic control loop.

My initial thought might be to write the scaffolding and state handling with an imperative language, and then do game logic and such with functional bits. With .NET and C#/F# this would be very easy, for example, since they use the same libraries and can talk to each other with no real penalty that I know of.
–
McMuttonsJul 15 '10 at 10:32