Functional languages in gamedev

This topic is 2224 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Does anyone here use (or know of someone using) a functional langauge in gamedev? Any game that there's a remote chance I may have heard of?

A friend and I was having this discussion about languages when he mentioned Scheme. He posted some examples of scenarios where scheme was much simpler/cleaner [than <insert_imperative_language_of_choice>] and so on, in particular an algorithm to generate primes. While I may or may not agree, he can be right for arguments sake at least. My response was "the question is how nice and clean you can do something more practial.." to which he said that Lisp was invented for AI, so it should at least be able to handle that, and probably also physics..

I then asked him if he could name an example, which he couldn't. I'm guessing that's because there are none, (feel free to prove me wrong) but why is that? Education among developers (or lack thereof)? Lack of performant implementations? No significant advantage? Solution looking for a problem?

Share on other sites
Well I'm using racket scheme to make small demos, though not a game. The advantages for are that it's functional, and has all the advantages that come with that (Of which I'm never going back to an imperative language for personal use). You can mix imperative code with functional, which is necessary for doing inputs and outputs, e.g. drawing graphics, loading files, keyboard input etc.

Also it has macros which allow you do add extensions to the language, e.g. I used this to make a system for loading and setting shaders.

 (define (some-effect) (effect (attribute "a_pos" 0) (attribute "a_nor" 1) (uniform "a" 0.0 0.3 0.0) (uniform "b" 0.9) (vertex " #version 150 attribute vec3 a_pos, a_nor; uniform mat4 u_modelViewProjMat; varying vec3 c; void main() { gl_Position = u_modelViewProjMat * vec4(a_pos,1.0); c = abs(normalize(a_nor)); }") (fragment " #version 150 varying vec3 c; uniform float b[2]; uniform vec3 a; void main() { gl_FragColor = vec4(c+a+vec3(0.0,b[1],b[0]),1.0); }"))) 

The disadvantages are that you have to write interfaces to c shared libraries to do anything useful, e.g. latest version of opengl, physics, sound, window etc. Though some of the other lisps might have bindings for those things already (I know common lisp does, but I prefer scheme).

I'm currently in the process of writing a library that auto generates bindings from c header files (nearly complete), it uses macros so that you just make a module and call a macro from my library which when compiled will auto generate the bindings for you.

I have a feeling writing a physics engine in it wouldn't be as fast as one written in c/c++, but for a game, if all the intensive code is imported from c bindings leaving the the rest in scheme, it should be fine.

Share on other sites
Check out Land of Lisp!

Share on other sites
About 5 years ago, Tim Sweeney (creator of the Unreal Engine) was making a lot of noise about Haskell/Erlang (can't remember which) being the next big language for game development, but AFAIK, they're still sticking with procedural C++/UnrealScript.

A search for his name + Haskell or Erlang might turn up some of these presentations.

Share on other sites
Naughty Dog supposedly did a lot of their work using a language called GOAL, which was a customized version of Lisp. I've heard conflicting reports about the extent to which this was actually successful, including an old insider who told me that the public description of GOAL was pretty much BS. I'm not sure, but I know they did build a lot of the old games in it.

Share on other sites
If I were to pick a functional language and try to write a game in it right now, it's probably be Scala. Scala actually has a mixture of functional and procedural/OO paradigms, but it is heavily influenced by Scheme/Lisp in its idioms. The good thing is that the language compiles down to Java bytecode to run on the JVM (and can utilize any Java class library), and there are a bunch of Java libraries for game development, so it might actually work.

Share on other sites
I think the main barriers to adoptation as a game language are functional purity; its hard to think of a game where you wouldnt want to mutate state at some point (and do it efficiently). I know you are supposedly able to do all this in functional languages, but give me set_pixel(x,y,color) any day of the week.

On a related issue, most successful game languages have relatively smooth interoperability with C.

The only way I could see myself using a functional language in a game, would be if I was making the game in C#. The seemless interoperability of F# with the .NET platform is a pretty awesome thing.

Share on other sites

About 5 years ago, Tim Sweeney (creator of the Unreal Engine) was making a lot of noise about Haskell/Erlang (can't remember which) being the next big language for game development, but AFAIK, they're still sticking with procedural C++/UnrealScript.

A search for his name + Haskell or Erlang might turn up some of these presentations.

You mean this? He talked about Haskell's advantages but said that the syntax is not accessible enough for new programmers. It was essentially a call for a new, practical and easily accessible functional PL.

Share on other sites
Andrew111, check out SWIG. I haven't had an opportunity to use it yet, but it looks like a solid project for auto-generating wrappers. A quick check shows that they support Racket.

The disadvantages are that you have to write interfaces to c shared libraries to do anything useful, e.g. latest version of opengl, physics, sound, window etc. Though some of the other lisps might have bindings for those things already (I know common lisp does, but I prefer scheme).

I'm currently in the process of writing a library that auto generates bindings from c header files (nearly complete), it uses macros so that you just make a module and call a macro from my library which when compiled will auto generate the bindings for you.

Share on other sites
There are thousands of 18-year olds who have 5 years of experience in C++ (because it's fast) applying for every single job to work 90 hours a week at minimum wage.

The odd math PhD that benefits from functional programming is a poor fit in such environments. And they'll probably apply at Wall Street anyway.

On technical side, graphics APIs, due to being defined in C and based on legacy of decades of C usage aren't perfect fit. Functional programming also produces non-deterministic running-time results, which isn't a problem when expressiveness is concerned, but is a big deal for real-time systems. There is also dire lack of tooling. So even if functional approaches are used, they need to be watered down. Finally there's deadlines. With project development cycles ranging from 1 year and down to 2 weeks, there simply isn't time for experimentation of any kind. There is essentially no new tech being developed outside of middleware and research companies and for something to be used it needs to have a track record of several years to demonstrate real world maturity.

Share on other sites

I then asked him if he could name an example, which he couldn't. I'm guessing that's because there are none, (feel free to prove me wrong) but why is that? Education among developers (or lack thereof)? Lack of performant implementations? No significant advantage? Solution looking for a problem?

It is an interesting question.

Given that both imperative (FORTRAN) and functional (LISP) came on the scene at about the same time (very early 1950) the question can be reduced to "why is the use of imperative programming so much more widespread than functional programming?"

I think there are two possible answers.

Firstly, imperative languages were effectively "higher level" versions of the machine code used to program computers at the time when they were invented, whereas functional languages were effectively an implementation of a fairly obscure branch of mathematics (Church's lambda calculus, which McCarthy was teaching at the time). Thus, imperative programming came naturally to the "old hands" then working the altar of big iron and functional programming limited to a few interest courses in better universities. When CODASYL was struck to determine the way forward for the next several decades, it consisted mostly of "old hands." Thus the foundation for the supremacy of imperative programming languages was laid.

A second possibly answer is that imperative languages are easier for Joe Bitpack to pick up: you don't need to understand about partially-enumerable functions to understand "make this box blue". Since most pointy-haired bosses see all code monkeys as interchangeable, grabbing the first guy to apply who has the right TLAs on his CV and can wipe the drool off his chin most of the time is seen as cost-effective. Natural selection in such an environment gives the reproductive advantage to a paradigm that does not tire out the lips as quickly.

Be thankful. When I was in university I was told that all the old languages were dead and everything would be programmed using 5th-generation languages like Prolog. I am sure my flying car is programmed using Prolog today.

Share on other sites

A second possibly answer is that imperative languages are easier for Joe Bitpack to pick up: you don't need to understand about partially-enumerable functions to understand "make this box blue".

Almost any real-world problem that needs to be encoded is nothing remotely close to pure. While it can be converted into mathematical form, it won't reduce to a nice equation.

Consider a very trivial thing - clicking on a button. Windows feels different from Linux or Mac UIs. Even though point-in-rect math is exactly the same, Windows has a few extra checks looking something like this: "if user hovered over second--to-last item for more than 1600ms then accept +3 pixels to left, unless there are less than 3 items in menu or there is a separator and only if US or UK English is selected, under Germanic locales adjust border to +5 and for LTR IME have border on left, but also adjust left window offset by 4."

And these details are the difference between software worth billions and college projects flooding open source repositories. The code above does not come from deep mathematical derivation but from user testing over period of years in real world situations.

Be thankful. When I was in university I was told that all the old languages were dead and everything would be programmed using 5th-generation languages like Prolog. I am sure my flying car is programmed using Prolog today.[/quote]

A lot of business actually is, just not in the way it was imagined.

UX and A/B testing, applied on everything from trivial UIs to business processes is the 5th gen language. It's not automated, but it's how, for example, Google, Facebook, most of newer games work. Programmers no longer make decisions no more than they do in original button click question. They merely shape the data they gather. The syntax this is done in is mostly inconsequential.

Prolog was about: "Is X human?". Development today is: "Will changing button to blue improve revenue?". Applied AI is not only in use today, but is just about only profitable programming venue left, outside of monopolies. And this approach is absurd. People start with some dumb app, then follow the flow into profitability, never being any the wiser as to what or why they are doing it.

We are living in the future.

Share on other sites

Andrew111, check out SWIG. I haven't had an opportunity to use it yet, but it looks like a solid project for auto-generating wrappers. A quick check shows that they support Racket.

[quote name='andrew111' timestamp='1324266690' post='4895176']
The disadvantages are that you have to write interfaces to c shared libraries to do anything useful, e.g. latest version of opengl, physics, sound, window etc. Though some of the other lisps might have bindings for those things already (I know common lisp does, but I prefer scheme).

I'm currently in the process of writing a library that auto generates bindings from c header files (nearly complete), it uses macros so that you just make a module and call a macro from my library which when compiled will auto generate the bindings for you.

[/quote]

Share on other sites
I did a mapgen in F# once as a 'real' project since the problem fit the language fairly nicely and it could integrate with the rest of the C# game. I don't remember really how it went. Probably not so well given my inexperience with F# at the time.

In general, it's a solution looking for a problem. People, even programmers, just don't think in that sort of 'cascading series of functions' manner; certainly not for anything sizable.

Share on other sites

I did a mapgen in F# once as a 'real' project since the problem fit the language fairly nicely and it could integrate with the rest of the C# game. I don't remember really how it went. Probably not so well given my inexperience with F# at the time.

In general, it's a solution looking for a problem. People, even programmers, just don't think in that sort of 'cascading series of functions' manner; certainly not for anything sizable.

Well, referential transparency and deep immutability are quite generally useful tools in my opinion that deserve to be used a lot more. Tools, that is, that I would wish to be able to opt into whenever I want, instead of getting them shoved down my throat, after which I have to take a doctorate in CS to relearn how to print to the command line using monad-magic.

I am quite eagerly waiting for D 2.0 to mature. It is still buggy at present, but it has the right idea: being able to mark functions as pure, and being able to declare data as deeply immutable. That, plus functions as first class citizens, is basically all I want from the functional world.

On an unrelated note, I heartily despise the terseness of most functional languages. I dont care if you can reduce the syntax of your language to lambda-calculus, I want to be able to see the structure of my code at a glance. I think python has the right idea there. Make whitespace a rule rather than a convention, ditch the damn braces, and use descriptive names for operators rather than cryptic symbols. Code gets read a lot more often than it is written, and writing do_useful_operation isnt really that much more work than writing '%^, but its a lot easier to parse to the human eye. Functional language designers seem to have all the wrong ideas here, that kind of hacker mentality which boils down to not realizing brainf*ck was never anything but an example of what not to do.

Share on other sites
Keep in mind that Scheme is not a functional language -- It may prefer functional constructs and share some other features, but the macro system in Scheme and Lisp make it a very different beast, allowing you, essentially, to build up your own language moreso than with any other -- in fact, Scheme was created with the goal of taking that ability to its logical conclusion, wherein most of what you think is Scheme itself, is really just Scheme code running on the very core of Scheme itself. You can effectively build scheme into all sorts of paradigms.

Scheme and functional languages map pretty clearly to problems that are fundamentally a transformation -- though efficiency can be difficult. They tend also to map well to problems that can be defined with a declarative style (good functional APIs often read as declarative statements).

The graphics pipeline is essentially a functional one, so its something of a shame that the first high-level shader languages were modeled on C. In the earliest shader models, the C-like model actually broke down, though today the hardware is evolving upwards to meet the language model that was foisted upon it. Many shaders become exceedingly short if you remove all the cruft that's modeled after C.

Share on other sites
Paging Associat0r. I repeat, Associat0r to the lounge forum, there is a thread here for you to ruin.

Share on other sites
I used F# for one of my tech test. It uses C# / SlimDX for the graphics side while I used F# for the entire car dynamics module.
It was incredibly smooth, bug free and a very rewarding programming experience overall. The ability of F# to keep that "imperative door" open sort of makes you feel safe you'll never find yourself trapped in some pure functional nonsense lockdown, at the same time it gives you the challenge to implement it functionally.

It is incredible how true is the claim that once you get the thing to compile, you'll hardly need to debug it.. it sounds like a marketing slogan, it really isn't. You just switch around the development time, investing more time designing a functional solution to the problem (this might get better with experience) rather than chasing bugs later in the development stage.

Learning functional languages was one of the best thing that happened to me in the last 2 years of programming, the influence even in my production C++ is huge, and more and more of my classes are now immutable right from the start. I wish C++ added a "readonly" keyword just as C# did.

So I would say, regardless of its present or future use in production code, I would recommend learning functional languages to every programmer interested in an whole new approach to problem solving.

Share on other sites

I used F# for one of my tech test. It uses C# / SlimDX for the graphics side while I used F# for the entire car dynamics module.
It was incredibly smooth, bug free and a very rewarding programming experience overall. The ability of F# to keep that "imperative door" open sort of makes you feel safe you'll never find yourself trapped in some pure functional nonsense lockdown, at the same time it gives you the challenge to implement it functionally.

It is incredible how true is the claim that once you get the thing to compile, you'll hardly need to debug it.. it sounds like a marketing slogan, it really isn't. You just switch around the development time, investing more time designing a functional solution to the problem (this might get better with experience) rather than chasing bugs later in the development stage.

Learning functional languages was one of the best thing that happened to me in the last 2 years of programming, the influence even in my production C++ is huge, and more and more of my classes are now immutable right from the start. I wish C++ added a "readonly" keyword just as C# did.

So I would say, regardless of its present or future use in production code, I would recommend learning functional languages to every programmer interested in an whole new approach to problem solving.

I'm curious, what does F# bring to the table over C# now with linq & lambdas? I haven't toyed with F# at all but i'm wondering what the craze is about as the few i've seen was things that were done before they were implemented in C# but now the same is available on both sides.

What does C# miss that F# has, in today's .NET 4 world?

Share on other sites

I'm curious, what does F# bring to the table over C# now with linq & lambdas? I haven't toyed with F# at all but i'm wondering what the craze is about as the few i've seen was things that were done before they were implemented in C# but now the same is available on both sides.

What does C# miss that F# has, in today's .NET 4 world?

I don't consider myself an expert in F#. Being C# a very modern language I don't think there is a single thing that you can do with F# and you can't in C#. But the default assumptions are different, in C# you can make an immutable value by declaring it readonly, in F# it's just the opposite, you need to mark it "mutable" if you dont want immutability.. most, if not all, bugs in F# come from mutable values. so, in a way, you're marking yourself the places where anything can go wrong. So it is no what you can or cant do, but it is more about how the language "wants" you to use it and how the language drives you towards a certain style of solution.

Plus F#'s syntax is much more clean and simple.. if that's an added value. I hope MS will invest in better tools to navigate F#'s source code and improves intellisense with it.

Share on other sites

What does C# miss that F# has, in today's .NET 4 world?

F# has units of measure, some syntactic sugar for type fiddling, type providers (which are cool for programming language theorists, but I haven't seen them do much in practice yet). But mostly F#'s fancy pattern matching capabilities.

Personally I don't think that those are anywhere near enough, given C#'s advantages with tooling and more natural integration with existing .NET code.

Well, referential transparency and deep immutability are quite generally useful tools in my opinion that deserve to be used a lot more. Tools, that is, that I would wish to be able to opt into whenever I want, instead of getting them shoved down my throat, after which I have to take a doctorate in CS to relearn how to print to the command line using monad-magic.
[/quote]

Indeed. And that's what we're seeing. Scala and C# pulling in the good stuff of functional programming to use where applicable.

On an unrelated note, I heartily despise the terseness of most functional languages.
[/quote]

I very much agree, though among programming language theorists it's not even discussed. Take a look through LtU sometime and see how much of the site is dedicated to programmer usability. But then again, I tend to be on the far end of the spectrum in wanting/making verbose programming languages.

Share on other sites
I think the rub, for me anyway, is that these 5th-gen PLs are becoming more and more functional. It's almost like, us as programmers, are in some weird denial process. We use imperative languages that are becoming more and more functional. But at the same time we say, "OMG, it's functional! The syntax. My eyes, my eyes!" (ok, there's some exaggeration there) We should just brace F#/OCaml/Lisp and be done with it.

(end rant)

Share on other sites

[quote name='ranakor' timestamp='1324378739' post='4895664']
What does C# miss that F# has, in today's .NET 4 world?

F# has units of measure, some syntactic sugar for type fiddling, type providers (which are cool for programming language theorists, but I haven't seen them do much in practice yet). But mostly F#'s fancy pattern matching capabilities.

Personally I don't think that those are anywhere near enough, given C#'s advantages with tooling and more natural integration with existing .NET code.
[/quote]
Dunno, considering how painless it is to add an F# project to your C# solution and just call its functions, id say the barrier to entry is very low. I dont see F# replacing C# anytime soon, but its certainly a nice option.

Dont forget the type polymorphism.

Well, referential transparency and deep immutability are quite generally useful tools in my opinion that deserve to be used a lot more. Tools, that is, that I would wish to be able to opt into whenever I want, instead of getting them shoved down my throat, after which I have to take a doctorate in CS to relearn how to print to the command line using monad-magic.
[/quote]

Indeed. And that's what we're seeing. Scala and C# pulling in the good stuff of functional programming to use where applicable.
[/quote]
C# does not have deep immutability (dereferencing an immutable object always returning an immutable object), nor can one declare functions as being pure. I dont see either of these changes coming in C# I suppose.

On an unrelated note, I heartily despise the terseness of most functional languages.
[/quote]

I very much agree, though among programming language theorists it's not even discussed. Take a look through LtU sometime and see how much of the site is dedicated to programmer usability. But then again, I tend to be on the far end of the spectrum in wanting/making verbose programming languages.
[/quote]

Share on other sites
Trying not to get too off track...

C# does not have deep immutability (dereferencing an immutable object always returning an immutable object), nor can one declare functions as being pure. I dont see either of these changes coming in C# I suppose.

I don't see deep-immutability as being a language feature (unless I misunderstand you). If you want an immutable object, make one; declare it sealed.
Likewise with pure functions. If you want a pure function, write one.

The optimizer loses some opportunities, but the core concurrency benefits will exist regardless.

[/quote]

Clicking the blog title brings you to the landing page. Most info is there, otherwise a PM might yield better answers to questions.

Share on other sites

Trying not to get too off track...

[quote name='Eelco' timestamp='1324397057' post='4895744']
C# does not have deep immutability (dereferencing an immutable object always returning an immutable object), nor can one declare functions as being pure. I dont see either of these changes coming in C# I suppose.

I don't see deep-immutability as being a language feature (unless I misunderstand you). If you want an immutable object, make one; declare it sealed.
Likewise with pure functions. If you want a pure function, write one.

The optimizer loses some opportunities, but the core concurrency benefits will exist regardless.
[/quote]
Well, of course one can always program in an immutable style by convention, in any language. But aside from compiler optimizations, its also a matter of coding efficiency. If I use a library function marked as 'pure', I know what im getting into. If I pass into a function an object declared as immutable, I know its going to be the same before and after the call. Without having to dig into the function and check for myself if the person making that function stuck to the convention.

Sealed only applies to declarations, not to instances of the class, or am i missing something?