4 ms·
It is completely possible and has interesting trade-offs. Here are some of my favorite blog entries related to functional game development: https://prog21.dad
by thesuperbigfrog 2y ago
It is completely possible and has interesting trade-offs.
Here are some of my favorite blog entries related to functional game development:
https://prog21.dadgum.com/228.html https://prog21.dadgum.com/228.html
https://prog21.dadgum.com/23.html https://prog21.dadgum.com/23.html
https://prog21.dadgum.com/24.html https://prog21.dadgum.com/24.html
https://prog21.dadgum.com/25.html https://prog21.dadgum.com/25.html
https://prog21.dadgum.com/26.html https://prog21.dadgum.com/26.html
- sph 2y agoAfter doing functional programming for a while now (6 years of Elixir) it seems obvious to me that it is possible and no more complex than using imperative logic. In fact I would go so far as to say that managing complexity (i.e. state) is much easier to do in a functional style than imperative. Functional is all about transformation of data structures, and a game is nothing more than a function that takes {state, mouse, keyboard} as input and returns {new_state, output} where output is a set of Vulkan commands, or pixels that you bitblt to screen. Rinse and repeat in an vsynced infinite loop. I think the linked articles above betray the fact that they were written 15 years ago when functional programming was a niche quasi-academic idea and no one was used to building stateful programs with it. 15 years ago it was all about Java and C++. Lisp was as forgotten as it is today. In 2024 most above average programmers have experience in functional logic, and it is not that arcane of an idea. The reason that it is not widely adopted is that functional programming is not as performant as imperative semantics, and you need all the speed you can get. On the other hand, imperative often means buggy mess as game complexity grows and painful debugging session trying to understand who and why changed this state variable.
- smellybigbelly 2y agoCould an expert strong man the argument that functional programming languages like Haskell could in theory be more performant than C because of the nice properties of pure functional languages?
- sph 2y agoCPUs are imperative and pervasively mutable. Languages like Rust are able to have so called zero-cost abstractions that are reminiscent of functional programming (iterators for example) but the thing is abstractions are by nature always slower than the real thing. But not all games are AAA FPS that require ingenious optimized codepaths to perform well, not in this day and age, so this is why you see commercial games running on "slower" abstractions such as C# (AOT compilation doesn't make it less of an abstraction layer), so you can very well design a commercial game in Haskell or Scheme or Lisp or Clojure if you wish. Nothing stops you, apart from the lack of serious game dev frameworks built in those languages. It all depends on the compiler, really, and it is asymptotically hard to compile functional languages so they perform as fast as C for example. There is no market for "high performance Haskell or Clojure", so there is no compiler that good either.
- neonsunset 2y ago"Cost" in C# comes from the (ab)use of classes for transient data, virtual/interface calls and automatic memory management. Another source of difference is in compiler capability of Unity's own flavours: IL2CPP, Mono and Burst, versus .NET's CoreCLR JIT and NAOT versus GCC/Clang. However, the latter has much less impact on "application code" and more impact w.r.t loop autovectorization, for which in C# you're supposed to use bespoke portable SIMD API which is fairly user-friendly. For the former, you are not "locked" into a particular paradigm like with Java or Rust and can mix and match depending on how hot a particular path is (for example - construct buffer slices with LINQ because there are only 16 of them, but each one is 512MiB large, so do the actual work with Vector<T>). JVM languages have a huge gap* in low-level capabilities where-as C# sits next to C and Rust in many of the features that it offers, even if the syntax is different. JVM implementations also come with significantly higher FFI cost. This makes them an overall poor choice for game development. Your experience of writing a game engine in pure C#, calling out to rendering and other device APIs will be massively better than doing so in Java/Kotlin/Clojure/etc, because of both runtime capabilities and ecosystem of interop libraries. Also, C# has zero-cost abstractions in the form of struct generics which are monomorphized like in Rust, and performance-sensitive code relies on this where applicable in "modern" codebases. * Projects like https://github.com/bepu/bepuphysics2 https://github.com/bepu/bepuphysics2 are impossible to implement on top of JVM without calling out to native components. This might change once the incubating Panama vectors improve upon their API and what they compile to.
- Barrin92 2y ago>a game is nothing more than a function that takes {state, mouse, keyboard} as input and returns {new_state, output} but that's a completely convoluted approach to identity in a model for a videogame. The reason Rich Hickey took that approach in Clojure to state and identity is because in the domains he cared about he wanted to prevent the destruction of past state. (he wanted to avoid what he called "place based programming" IIRC). If you want to implement a git like versioning history say, you really care about any change to state as a collection of individually immutable snapshots. But in a videogame that's completely artificial. Nobody thinks about a persistent entity in a game as a collection of states at a million points in time. It's much more natural and performant to think of your entities as persistent and mutable and you basically only care about where they are now.
- AlotOfReading 2y agoIt's not that artificial, it's basically a traditional game loop where mutation happens in the background between iterations. It has many of the same challenges too.
- filoeleven 2y ago> you basically only care about where they are now. You care about what they are doing now, and what they should do on next render based on the rules of the game and the player’s input. To me, that looks a lot like (state, actions) => newState. I’m not sure how much of a difference there really is between having objects track their own state vs having them pull their state from somewhere in a single State tree. The advantage to the latter approach IMO is that it simplifies cross-cutting concerns (“player deals bonus damage when all enemies are affected by poison”), and it helps immensely with debugging to be able to query the exact, full game state whenever it’s needed. My brain has been rewired to find FP easier to reason about than OOP. This won’t be true for everyone, and it isn’t always the right tool. I think it works well for game dev but can be held back by performance concerns.
- deisteve 2y agoComing from clojure I'm very wary of any non-mainstream languages like Elixir, Rust, Clojure etc. It's a costly business mistake to build your tech stack using any of the above languages. The trade off simply is not significant enough to matter vs using mainstream languages with 10,000x the number of mindshare.
- bluGill 2y agoThe cost is not paid today, but in the future when whatever you choose is no longer supported. If you write in something like C++ or Java running on Linux or Windows I'm confident that in 20 years you will find a tool that can build your code for the latest computers (not just the compiler, but the other tools as well). Of course Python 2 is a perfect example of why even the highest confidence choices may be wrong. Rust is starting to look like it will make the jump to likely to be around for the foreseeable future, but only time will tell. Of course just because you can build it doesn't mean it will work. I know of an embedded system where the 16 bit CPU went obsolete and they discovered that the C code was not 32 bit safe and worse it relied on the timing of the one CPU it was written for (though not so bad as to have to turn off compiler optimizations). I know of a product written for X11 that is porting to wayland. Keeping code running for decades is a hard problem - and one that many fail to understand. (nor do they need to - the web site you do today will need a major rewrite to fit the latest UI fad no matter what you do)
- filoeleven 2y agoThe other two languages GP mentioned, Elixir and Clojure, run on the BEAM and Java virtual machines respectively. I can’t speak to BEAM/Erlang, but your confidence that the JVM isn’t going away should remove any concerns about Clojure being supported in 20 years. It’s just a Java library, and has the same conservative approach as Java of ensuring backwards compatibility. Clojure won’t necessarily live as long as the JVM does, in that the language could someday be abandoned, but support for its hypothetical last language version won’t be somehow removed from the JVM.
- bluGill 2y ago
- deisteve 2y agothe biggest tradeoff is talent pool you won't be able to find them in enough numbers and it would be tough to gauge their proficiency too unless you are purely interested in it for academic purposes, its best to avoid clojure and any sort of esoteric languages. Even Rust development is riddled with false roads and mirages. i just want to save anyone reading this 5 years of their time. You don't get better when you are constantly having to re-invent the wheel for essentially shaving off roughly 20~30% lines of code you'd write in python, php, ts. It's hardly a fair trade off
- bluGill 2y agoI can teach any developer Rust or Clojure in a couple weeks. I've only done a few hours of Rust study myself, and just minutes in Clojure and yet I will say that with confidence. It takes years to master, but the difference between 1 month and 10 years for an otherwise experienced programmer is not very large - either way the hard part is the problem domain, understanding your code, and other such details not related to the language. HR puts far too high a weight on skills in a programming language, in part because they are easy to measure while the ability to write good code is hard to measure.
- whiterknight 2y agoThe longer I am around the less true I find this. Can any good developer learn and contribute with a new language? Yes. But there is also a peak performance achieved by using tools for decades that is not transferable. C experts didn’t switch to Java, they found different jobs. For your core technology you want a few of those 5-10+ year guys.
- bluGill 2y agoSure, but you only need a few of those 5-10+ year "guys". The rest can be behind and will develop those skills over time.