Programming is a tiny part of game development. No programming language would blow anything in the indie game community. It would be nice and welcome, but it wouldn’t revolutionize anything.
> It would be nice and welcome, but it wouldn’t revolutionize anything.
I dunno, it'll certainly revolutionize my world once it's ready. A editor connected REPL, changes to running games on the fly while keeping existing state, using a well-designed language like Clojure but getting the performance (or similar) of C++ and native binaries.
It's pretty much a win-win-win for me, especially if I can replicate the speed of development I get with normal Clojure but for game dev.
> my understanding from game dev friends is that's precisely what they do, no?
Do what? Program games in a Lisp engine? That's quite atypical, which is unfortunate. It's almost impossible to convey the sensation of "living" within a Lisp machine. Those who haven't experienced Lisp programming and haven't become accustomed to the process cannot grasp the dopamine effect of writing instructions virtually anywhere, at any time, changing the things on the fly. It's enormously empowering, and it's incredibly liberating.
That's why those who at least once unleashed the true power of Emacs simply can't feel the same joy in anything else. Other editor and IDEs talk about features like "keyboard macros" and how powerful they are, yet they fail to grasp that Emacs operates on an entirely different plane - its keyboard macros are programmable constructs that can be created, modified at the Lisp expression level, and converted into full-fledged functions from any recorded sequence.
Using Emacs is like playing a video game where you level up by writing s-expressions. The profound satisfaction of shaping the system to match your exact needs is immense, and sadly remains vastly underappreciated. Even when curios newbies come to explore this "immense power of Emacs", they don't even realize that it all is possible only because of Lisp.
It just feels weird to me that the gamedev community outright rejects the idea of programming in Lisp. To me (a Lisper) writing games that way makes absolute sense - games should be written as if you're playing one, right?
Arcadia's biggest drawback was that it was dependent on Unity, which meant that it had all of the issues that Unity had plus some new ones. Without source code access it's difficult to exceed the features/performance of the base engine.
Maybe they've fixed some stuff (or ported it it Godot) since I last checked it, but the general lack of editor support, the clash between how Unity wanted to operate and how Clojure wanted to work, and usual Unity problems kept me from building anything significant in it.
AFAIK Janet is not "much simpler to interface with C++". Janet has good FFI for C, but not for C++ directly. Janet's native FFI system is designed specifically for C libraries. C++ has name mangling, classes, exceptions, and other features that Janet's FFI cannot directly handle. The process would be similar to using C++ libraries from any C-based language, which is far from straightforward.
Jank, if my understanding is correct, in comparison has direct C++ interop. Jank treats C++ as a first-class compilation target rather than a foreign interface.
Yeah, well, I don't think it's that simple. You can't just say "eh, gamedevs apparently just don't want 'interactive workflows'", which of course, not true - look at Unreal's Blueprint live editing, Unity's play mode value tweaking, Godot's live scene editing, Jonathan Blow live-coding an entire game, etc.
I don't know why Arcadia wasn't very successful -I have never used it; I can only speculate on the causes, but I have good reasons to believe that Jank may actually succeed where Arcadia struggled - it is designed ground-up for game engine integration, no GC pauses, better FFI for engine bindings, etc.
the request/response command/query nature of the REPL is what I am referring to. Great fit for RPC-oriented web backends backed by OLTP databases that start fresh each time and run to completion. Live scene editing seems closer in nature to a hot module reloading workflow, where we try to take care not to disturb long-lived objects and processes. PS, Jank is very cool. No idea what his plans are here and I’m not claiming a gamedev repl is impossible in any way.
This is a weird take. It's a tiny part of game development until you can't program. Then you realize it's actually a huge part. Particularly for "indie" game development.
Ultimately code is just a tool, but it's still a tool that can translate into rapid iteration or into friction.
Yeah, jut like writing is a tiny part of book publishing. What the heck are you even talking about? Programming is absolutely fundamental to game development - it's literally what makes games exist and function.
I'm not talking about "revolutionizing" anything, but maybe you haven't noticed how Unity democratized gamedev and how GDScript made game logic accessible. There is absolutely a sizable chunk of the market for the Lisp-based gamedev - look at Lua/Fennel gaming community - LÖVE2D, Pico-8, Defold engine, etc.
Having performant Clojure option (which Fennel ain't - it's only "like" Clojure) would be absolutely wonderful news.
I think Jank will find its people, but I don't know how many of those people will be indie game developers. I'm sure some will be, but on the whole I don't think most indie game devs are clamoring for using clojure, if only if it wasn't for the JVM or the performance. I doubt many indie game developers are even aware of what clojure or jank are, or even much about functional programming to be frank.
For indie game devs you're competing against engine ecosystems like Unity, Unreal, Godot. If someone is inclined for more of a DIY route, you're competing against Lua (love2D), C# (monogame), Javascript (...), or for the people who care about performance, C++, Rust, Odin, Zig, and soon even Jai. It's a very crowded competition space and again, I think overwhelmingly the people in this space aren't dreaming of programming in a functional style.
There's not exactly tiny community (but it's not huge either) that programs against Lua-based engines using Fennel - a Clojure-like Lisp. Jank, aimed to have one-to-one Clojure-parity, I think would be great news.
> the people in this space aren't dreaming of programming in a functional style.
IMO because they are extremely pragmatic and there still, doesn't exist a good, practical way to program games in a functional style. Jank may open that possibility.
Then there are folks like Notch, that by not following such advices got gold, as they managed a great additive game, regardless of the technology stack being used.
There is also 80% of the mobile phone market available, in the context of JVM like ecosystem to target, and avoiding NDK tooling is gold if one really doesn't need it, as its experience still sucks after all these years.
I was not meaning to say that anyone was wrong for their technology choices. Personally I think Java is great and some of my favorite games are made in it. I'm just saying that I don't see jank or clojure for that matter catching on because it isn't where the head space of the indie gamedev scene is at, and I don't see this changing, especially given the number of competing stacks.
I imagine the point being the same as game development in general, hence my agreement on a sibling comment.
Many people, especially those coming from FOSS background, don't understand the game development culture is all about IP.
The culture is to create great experiences, with interesting gameplay, the actual programming languages tend to be whatever everyone uses in the industry, and in general proprietary APIs aren't the drama like in sites as this.
So if an indie is going beyond desktop, trying to maximise sales, they will pick an engine and language that covers them.
Lisps (like Clojure) treat code as data (lists), so you write: `(if x (y) (z))` instead of Python’s `y() if x else z()`. So the code is more concise, but does less to walk a novice through it.
This gains a huge advantage, which allows even more concision: all code is data, so its easy to transform the code.
In Clojure if you want to add support for unless, a thing like if, but evaluating the opposite way you could do this: `(defmacro unless [p a b] `(if (not ~p) ~a ~b))`. Obviously if you wanted to do the same thing in Python you would in practice do `z() if x else y()`. However, you would do it that way because Python isn't as powerful a language. To actually do the same thing in Python you would need to...
1. Add __future__ support.
2. Update the Python language grammar.
3. Add a new AST type.
4. Add a new pass stage to the compiler.
5. Add a python library to integrate with this so you could use it.
Then you could do something like:
from __future__ import macros
defmacro unless(pred, then: block, else_: block = []):
return q[
if not u(pred):
u*(then)
else:
u*(else_)
]
So in the trivial case its just hundreds of lines harder plus requires massive coordination with other people to accomplish the same feat.
This sort of, wow, it takes hundreds or thousands of lines more to accomplish the same thing outside of Lisp as it does to accomplish it within Lisp shows up quite often; consider something like chaining. People write entire libraries to handle function chaining nicely. `a.b().c().d().map(f).map(g)`. Very pretty. Hundreds of lines to enable it, maybe thousands, because it does not come by default in the language.
But in Lisp? In Clojure? Just change the languages usual rules, threading operator and now chaining is omnipresent: `(->> a b c d e (map f) (map g))`. Same code, no need to write wrapper libraries to enable it.
That doesn't look like a factor in the article though, he isn't using many if any macros that aren't part of the core language. And the one macro I do spot (defcfn) is pretty mild in context.
People like GP often repeat that talking point: "code is data so that's amazing because of macros".
In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
Macros can almost always be expressed with a simple function and remove all the unexpectedness without losing anything. Again, there are some exceptions.
> In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
I'm not sure "frowned upon" is the right expression, but I'm not a native speaker.
The way I've internalized it, is basically "Avoid macros unless there is no other way", which basically means use functions/anything else whenever you can, but if you absolutely have to use a macro for something (like you wanna read the arguments before they're parsed), then go for it.
I always looked at these features of being able to extend the language beyond some commonly accepted practices as detrimental to the language. I've spent way too much time debugging issues with operator overloading or complex templates (C++), or obscure side effects in DSLs. So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
But... looks like the professional community knows this and so maybe it's time to take a deeper dive :)
> So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
It can be, but also not. If you isolate them into libraries with clear interfaces, you can kind of avoid that. I think clojure.core.async is an excellent showcase in something you couldn't do in other languages, where asynchronous channels were possible to add to the core language without changing anything in the core compiler itself, and because of the small interface, you can still use it without ending up with nightmares :)
Understood. I was more referring to a case where a project would start defining its own language constructs and if each project would do that then every single project would come with a very high cognitive load.
Dunno about the Clojure communtity but for Emacs Lisp and Common Lisp there are certain broadly accepted idioms where macros are accepted:
1. "with-context", where there is a need to control resource allocation/deallocation or things in the context of code in question.
2. use-package dsl that simplify configuration in a predictable way
3. object definition helpersresource
Then, there are core language extensions and std libraries suggested for the main implementation. This is where macros are fine as they always get good documentation and plenty of additional eyeballs.
I use a few macros for creating contexts (i.e. with-texture, with-stencil, with-scissors, with-tar). Also I have macros for rendering (onscreen-render, offscreen-render). However I try not to overuse macros.
Fun fact: the big difference isn't the syntax. Lisps only go from foo(bar baz) to (foo bar baz) which is a change but not really much of one. The change is actually the immutable and high performance basic data structures. Clojure can do something that something like C can't do - cheaply create a copy of something with a small change. That leads to a completely different preferred code style in the Clojure community that is a big departure from C-like languages which make heavy use of variables. The code is doing something practically different from what a C-like language can ergonomically handle.
Clojure has a bunch of other syntactic structures not found in other lisps that makes it a lot more visually noisy. I'm very comfortable with Scheme and I can very quickly absorb Scheme code when reading it, but I have to very slowly decipher the code in the article.
> not found in other lisps that makes it a lot more visually noisy
I disagree. It only feels that way, until you learn how destructuring works in Clojure. Once you grok that, you'd understand why the vector syntax for function arguments was chosen, and not a simple list like in other Lisps. In general, Clojure is highly pragmatic - if something done certain way, most-likely it's for good reasons, and not by accident.
Also, Clojure-maps are just freaking amazing. I wish others, e.g., Elisp had them.
Clojure is extremely and nicely readable, just requires some getting used to it. At some point, I completely replaced my API-testing workflows, switching from JSON to EDN - it's almost twice more compact and much better visually, not to mention that it's incredibly nice to be able to just explore and visualize any given data through the REPL.
> It only feels that way, until you learn how destructuring works in Clojure
Well... yes. The original comment was about how Clojure code looks very foreign. The reply to that was that Lisp code is not actually that foreign because it's just taking the common foo(bar baz) and making it (foo bar baz). My comment was that Clojure is more foreign to most programmers than other Lisps, because it's not simply mapping foo(bar baz) to (foo bar baz).
Of course when you learn the things that make it unique, it becomes familiar.
That's just existing muscle memory. Nothing is wrong with you and nothing is wrong with Clojure. I had the same feeling when I started with Lisp. Give it some time, it's absolutely worth it. Interestingly, every single programmer I introduced to Clojure as their very first programming language had no issues picking it up. Later, they complained about difficulties getting used to Javascript and Python.
Have you tried experimenting with ham-fisted? I've found the libraries in the techascent part of the Clojure ecosystem to be very good performance wise. Ditto for neanderthal.
I mean it is pretty cool, but do people not roll their own graphics engines anymore? When was in to hobby game dev back in 2000 or so, we all wrote our own systems.
Using same game engines and physics lead to a generic look-and-feel, even if they do allow for a large amount of creativity and differences.
This _looks_ different, which is awesome!
Even if the atmospheric effects still need some honing, there's a ton of work around lighting to eventually be done, the edgy polys make it look about 20 years old, and it's a bit pixel-y around the edges, this is headed into a spectacular direction!
If my ADD were in charge of this project, here's what I'd add:
- Optional stars / environment - a universal simulation would be unrealistically computationally expensive, but just having stars would be neat. Later, a planet in the horseshoe nebula, or playing spherical versions of recorded or streaming video for AR or making homegrown music videos.
- Ability for others to share datasets - the Earth is f-ing awesome and I can't wait for the Moon! What about a place where users could share different datasets like Arrakis with it's sand dunes and 2 moons or Tatooine with its 3 moons, then maybe they could fly in a heighliner, landspeeder, frigate, or imperial lambda shuttle, or even the jetcar from Buckaroo Bonzai?
- Solar Mayhem - Simulate a crazy atmospheric and orbital space war simulation or arcade-style game with satellites, lasers, plasma / electrical discharges and arcing, dust and nanorobot clouds, cloaking, jamming, ramming, repairs by robots and soldiers in tethered spacesuits, zooming cameras and 2D/3D scanners in different wavelengths, spacefaring naval ships, UAPs and other secret government vehicles, and complex 20th century fantasies of space stations running on nuclear and otherworldly power.
- Eclipse Support - when you add the Moon, doing an eclipse is not just the shadow but you'll need to handle the cool colors on the edges when the moon is covering the Sun.
- Ocean Simulation - Orcas, fish, eels, coral, lobsters, octopi, old ruins, Atlantis with its merpeople, tictacs and other USOs!
- Beautiful water features in Baltic Sea, Yukon Delta, Mississippi River, Lena River, Petermann Glacier, Brunt Ice Shelf, South Georgia Island, Guinea-Bissau, New Caledonia, Patagonian Sea, and the Icelandic and Norwegian fjords.
- Weather simulation with a way to pull in current atmospheric data historically to fly through hurricanes and tornados or simulate tsunamis after earthquakes.
That's would certainly be an awesome game, but did you know that your "Solar Mayhem" concept already exists? Children of a Dead Earth - it's probably a bit more austere by virtue of limiting itself to only somewhat-plausibly realistic weapons, mind you.
> Using same game engines and physics lead to a generic look-and-feel
Sure but they're talking about using the same game engine, not the same physics engine. I don't think anyone would say Split Fiction looks at all like Oblivion Remastered. Though they both use Unreal Engine 5
The hardware graphics acceleration stack is heavily shader-based now, so there's less and less graphics code being written in systems languages like C. In a way, people are still writing their own graphics engines, it's just for such a different platform from the unusual Turing-computer CPUs that all the old techniques go out of the window.
Nothing stopping you from writing it the old fashioned way though - you can just keep generating a single screen texture in the CPU and let the GPU idle!
As old dog I find this kind of funny, because for folks of my age C was like C# is seen nowadays.
Any serious game would be pure Assembly, and when using Pascal, C or BASIC compilers, they would be full of inline Assembly, almost like a poor man's macro Assembler, as the quality of code generation was awful.
Good point! Wasn't the Sony PlayStation significant for being the first console to ship with a C API from the manufacturer, or am I misremembering? I always thought that Net Yaroze sounded fantastic but never ended up getting one.
Oh, and another question on that topic: did you ever write self-modifying code for games, or had that already gone out by 2000?
Always, when read about "functional language usage in simulation", I check if OpenGL binding used. Other important things are physics engine and collision engine, because these are more than 90% of all code.
Unfortunately, just as I suspected, this project use OpenGL (nearly all implementations are C++), and C++ collision/physics engine.
So, looks like, in this project, Clojure is used just as high level script to orchestrate all C++ parts, may be later we hear about some game scripting, but for simulators they are not as need as for example for RPGs.
I agree, Clojure is better than C++ for orchestrate, but I have seen so tiny number of art persons familiar with functional paradigm, so this looks like beautiful dead end.
Again, this is really beautiful and respectful achievement for author, but people I seen working in gamedev will not accept such approach.
That's literally the whole point of using a high level functional language though. You use it to express the business logic of your app, the code that you care about. The fact that the underlying details of how rendering and physics are done is written in an imperative language doesn't really matter here. What I care about is maintaining the logic of my application, and that's what a language like Clojure makes easier to do.
Why not use some simpler, like old good UNIX Make? Or for business logic existing for a long time Lua, which is much easier to learn/use than Clojure.
I love functional paradigm, but sometimes fp lovers, looks like evangelists of Blockchain or LLMs - not bad things, but all have their limits, and not very useful without powerful support of large library of fp structures and debugging programs. So, trying to use fp, you dive into abyss, writing with fp, but debugging with low level C debugger.
BTW, as I know, OcaML, flagship of fp, just don't have graphics debugger, so people used to write on Haskell using old classic REPL technology, than, thanks to syntax similarity, most code just compile on OcaML without additional moves.
OCaml supports imperative, functional, and OOP just fine, and you use whichever makes more sense, and it has a REPL, too, most popular one is called "utop", but "ocaml" works. As for graphics debuggers, I have no idea if OCaml has a graphical one (if that is what you meant), but there is ocamldebug[1][2].
That said, I agree, why not just use Lua? Seems like the perfect language when you only care about the game itself and not the underlying stuff. There are many other alternatives that are better than Clojure anyways. I might be pessimistic, but I doubt Clojure is going to catch on.
Well, I'll believe you about fp debugger, so only problem left with OcaML and Clojure, each of them have GC with non-linear complexity (Clojure as I understand using BEAM GC which claimed soft-realtime, meaning 90% of GC work will look like realtime, but OcaML using some typical GC), and what all these mean for games - they will suffer framedrops or even short freezing, when GC running.
Exist two approaches to overcome GC problem, but if somebody will again minus my comment I will not bother to find links in my records.
1. Here on HN mentioned GC-free fp platform.
2. Few years ago appeared GC algorithm with linear complexity (sure, with limitations, but good enough for example for 16-bit consoles level games).
Unfortunately, haters minusing comments, but don't add anything valuable, and author was not mentioned these problems.
> Unfortunately, haters minusing comments, but don't add anything valuable
Tell me about it. It happens so often that I am very reluctant to leave comments now, especially on topics that I know people have already made up their mind and are not willing to discuss it with an open mind. That said, I did just leave a comment about something I probably should not have, but oh well.
Is it really Clojure that uses BEAM? I thought it was a JVM-based language, I would have to look this up.
BTW OCaml finally has multicore support, which was a long time coming.
[1] Especially this part: "OxCaml gives programmers tools to control allocations, reducing GC pressure and making programs more cache efficient and deterministic.".
Unfortunately, I see very familiar things from Perl world - many people made really interest things alone, but for some reason, they don't organize to make one direction really on par with commercial platforms (even when with current technologies could make efficient distributed governance, and even could make significant sells for sustainable development). I mean, people disperse resources, making many good small things, but most Open Source software recessing or even in crisis without moving ahead.
I've seen JVM, BEAM, CLR at field with heavy load, they all have significant drawbacks, but from my opinion, CLR ecosystem developing faster than other mentioned.
Clojure is not a "JVM-based" language, it's a hosted language - means Clojure is designed as an abstract language that can be implemented on different runtime platforms. The language's core abstractions (persistent data structures, protocols, vars, etc.) are not tied to any particular host - it's just that JVM variant was first and remains the main focus. Clojurescript run on JS VMs, ClojureCLR on .NET, ClojureDart - targets DartVM, babashka is great for scripting, SCI - for small embedded Clojure DSLs. There is also Clojerl - that runs on BEAM, and Jank for native compilation. You can run Python in Clojure and Go, and it just keeps growing. Seriously, one could learn only Clojure and write code for [almost] any platform.
Because there isn't "true" REPL. Non-homoiconic languages don't have the same kind of REPLs, because every step in them - Read, Eval, Print and Loop have slightly different semantics.
I just wrote my Hyprland config in babashka - native Clojure scripting engine. Once I build a socket management function that connects me to hyprctl, I was able to do the rest from within my editor connected to the REPL. I would write (hypr-cmd :clients), eval it, get the list of windows in my WM, and then filter, group, sort, etc. It is so much nicer to build things "from within", most people who never experienced that, wouldn't get it.
I'm running my WM and fully controlling it by writing code and executing it in-place, from the editor running in that same WM - without saving the code, without compiling it, without restarting the WM or my editor. I'm programming my shit as if I'm playing a video game. If I was a game developer, for sure, I would stick to the same mentality - why the heck work on a game, if I can build it by playing?
Fennel already "works". There's a small community of devs around it and in my opinion and practice, it remains a better choice to use instead of Lua directly. I don't even hesitate - whenever I need to tap into Lua-based engines, I would try to bootstrap Fennel on top - I use it with Hammerspoon, with Neovim, with mpv, and if I at some point I finally decide to switch to Wez terminal, I will for sure use Fennel.
That being said, Fennel is nice but ain't ideal, it's rather weird. It tries to imitate Clojure syntactically, without actually posing as a Clojure dialect. Fennel is extremely thin layer over Lua - you're essentially writing Lua with s-expressions. In Fennel, you constantly feel Lua's presence (1-indexed arrays, table semantics, nil behavior), while Clojure abstracts over Java/JS/Dart/etc., much more heavily with its own semantics. I constantly feel like I'm missing good CLJ ergonomics - no built-in immutable data structures; no rich standard library; limited REPL experience;
The difference in philosophy is that Fennel prioritizes being "just a syntax" for Lua and Clojure prioritizes being a "better language" that happens to run on JVM/JS/.NET/Dart/etc. Makes Fennel feel more like a transpiler - remember the days of Coffeescript?
I guess, maybe all that actually makes Fennel more appealing to some - abstraction layer thickness sometimes does matter. I personally, wish for an actual Clojure dialect on top of Lua, rather than something "like Clojure".
> Lua, which is much easier to learn/use than Clojure.
As someone who used both, I can certainly argue for that point not being true at all, and in practice it isn't.
Lua's syntax is a mixed bag and even after years dealing with it, I just can't stand how ugly the darn lang is - I just never know how to format it for better readability. Metatables are powerful but conceptually complex; global by default and 1-indexed arrays - who the fuck even thought it was even worthy to call it "an idea" - those are just plain stupid. Nil handling can also get weird.
While Clojure for sure may feel like having a steeper learning curve, once you get past parentheses - it feels so much simpler.
As I understand, you mean, fp approach is comfortable to work with large codebase.
But in GD this is not the case, and even not was case at past.
Why so, because, at digital games dawn, hardware was too limited, just hardware limitations prohibited large projects;
when appeared big networking games, complexity shifted to server-side, so for them subject irrelevant;
now possible big games without networking, but high-definition multimedia costs prohibitive.
So, for subject only relevant small games, with small codebase, so they even avoid text programming at all and many people switched to so named Visual Scripting (google).
> As I understand, you mean, fp approach is comfortable to work with large codebase.
I didn't say anything about "large codebases" or "FP approach". I'm just saying that in comparison with Lua, Clojure holistically simplifies many aspects of the entire process - for small and large code, and not only because it's an FP language - after all, it's not "purely functional".
Clojure gets many small details right that other languages, including Lua, struggle to handle elegantly. But programmers often face a cognitive trap: once they master their language's quirks and edge cases, they mistake familiarity for design quality. What once seemed obscure becomes "the way things should be". This expertise paradox prevents them from seeing these quirks as the pragmatic obstacles they really are - they've internalized the workarounds so deeply that they defend them as features rather than flaws.
Clojure is not without flaws, but somehow, it just doesn't feel like one needs to learn a collection of language gotchas to be productive.
We can talk about philosophy, psychology, technical merits, and design of programming languages, but at the end of the day people will use whatever makes them happy. Clojure and its dialects genuinely bring joy to thousands of programmers, and I understand now why. After writing code in a dozen of languages, I see why.
Ok, I'll say more strict - I talking about GAMEDEV, not about abstract things.
And in GD, code have much less importance than in other fields.
As example, I once meet amateur of RC-planes, and looking on his setup I asked, why his electronics is so simple, as I understand, he could make much more sophisticated things.
Answer was: "here, I want to be airplane designer, not electronics designer, so I make plane highest priority, and sure, when you will make your plane, you could make electronics priority".
Again, this is not philosophy, this is real thing - in GD language is the least important thing for happiness, in best case it is small obstacle at the way to create game, so the best language could be no language at all.
If you could suggest some way, how it is possible to do platform where programming language hidden deep under the hood, so people just don't use language at all, but things are done, this will be very constructive talk.
> code have much less importance than in other fields.
Although I'm not a game developer anymore (I've done some in the past) I still have hard time believing this sentiment to be true, even today. Game development is interdisciplinary - code, art, design, and audio all matter. But code is definitely not less important than in other software fields; it's just that games also need those other disciplines to succeed.
Yes, modern game engines abstract away low-level code and many successful indie games have simple mechanics but great art/design, still, code remains one of the most important aspects of a good game. Physics, collision detection, rendering and graphics optimization, network for multiplayer, AI for NPCs and procedural generation, performance optimization, state management, input handling - all that still needs code.
Google "Visual Scripting", "Unreal Blueprints". It is now possible to make game literally without writing any STRING of code.
Second, with development of AI more and more appearing "no-code" solutions, in some cases even capable deliver app from blueprint painted with pencil on paper.
This is interest assumption, but let's think, who are building large applications?
I've taken part at some large apps built inside one company in extremely short time.
And no, in my list only more or less adequate platforms - Perl, MS VBA on web.
And I've countless times just rebuilt some large systems from sources - FFMPEG, Unreal 4 environment, what interest, whole FreeBSD 4.x with BSD environment including XWindow is smaller than U4.
And what was really big pain, I tried to work with NASA OpenMCT, and because it was based on Javasript technologies, I spent huge amount of time to figure out, where end server-side and where begin client-side. I think you understand this is important, because each part debugged with very different instruments and techniques.
And what I must say there, games are very different in scale.
- Sure, exist very large games (named AAAA, like cinema movies, and have so huge download size, as for example new Stalker, that my friends working in telecom complained, it was like huge DOS attack when game came out). And what also interest, AAAA games tend to make their own custom game engine, yes, each game with own game engine, because for them easier to figure out in their own code than to learn ready game engines.
Also exist industry of game studios, medium businesses, but they tend to be much like big businesses just without resources to make own engine.
And also exist huge industry of independent -games (i will use indi- name), which have very small amount of code, because of tiny budgets or just "no-budget" work, in many cases literally made by one person, who making pictures, code and sound himself. And in reality I know very few cases, where indi- makes his own engine, but most others are slightly modified already known game mechanics.
What important - big business will not use subject code, nearly guaranteed, because they have very specific demands about maintenance, to fulfill them need at least medium company;
there is more probability to reach medium business clients, they are trying to be "like a big boys", but in most cases possible to achieve some understanding;
and the most probability is to reach indi- developers.
So, what we talking about now, is mostly about indi- developers, one-person sized commands, and it is very god if they will just use C-like languages, but you cannot account for them to use fp paradigm.
I cannot at the moment give estimate of distribution of game sizes, but now tend to appear more indi- developers with small games (and sure, using some made by other people.
In the past I have done some rigid body physics in GNU Guile (see https://www.youtube.com/watch?v=zBq3kW2jVxs for example). Of course if you need to simulate many objects, you will hit performance problems sooner if you don't use C/C++/Rust. Also the developer of Jolt has solved quite difficult problems, so I was quite happy to use it instead of rolling my own.
Computers are stateful and imperative, so any functional language that runs on real computers has a stateful and imperative base. OpenGL vs not seems like an odd place to draw the line on what you would consider functional vs not.
Modern off the shelf Microcomputers nearly all imperative, because marketing won, but when world was under Mainframes (nearly up to 1980), existed many examples FP-optimized architectures or high-level architectures, even some of them was commercially successful (Lisp computers and some high-level mainframes).
Also, most developers don't deal with naked hardware, but working with libraries of structures and libraries of high level algorithms, this named abstraction layer. Just some existing abstraction layers are less abstract and other are more abstract. As example, in Windows (and in most UNIXes) file abstraction is very simple and just imperative, but in MacOS it is OOP (derived from NEXTStep as I hear, based on ObjectiveC), and also exist some other OSes based on OOP languages, like BeOS, even when MacOS/BeOS are now running on same x86 hardware.
So possible just run inside higher level VM.
And mathematics is not prohibiting FP-machine, they could have very effective implementations with modern math.
What really problem, except of Prolog, I don't hear about high-level debuggers for fp languages, so writing on for example Ocaml, you once end up looking on fp structures with old C debugger, which sure don't see fp structures.
A Lisp machine is no counterexample - they had assembly language instructions that were tailored for Lisp, but were still very much imperative. In fact, Clojure is significantly more functional than other Lisps, which used mutable cons cells extensively. Object oriented languages are also stateful and imperative, so I'm not sure why those are relevant here.
I'm not saying these things are bad - it's possible to imagine a computer architecture that makes functional programming easier, but it's really hard to imagine a useful computer that is not stateful and imperative! What would it do, in that case?
OpenGL vs not-OpenGL still seems like a very arbitrary way to classify simulations.
Lisp really counter-example, because they have read-ahead (superscalar), specialized data types and hardware GC support.
Read-ahead (superscalar) becomes typical from Pentium and similar class CPUs; even specialized data types gaining some usage (AVX-512, FP-16/FP-8); but for hardware GC I don't know any widely used examples.
From second view, looks like good way using ECMA-6 (for example) with Babel and some things added into browser debugger.
So, technically, high-level ECMA-6 language transpiled (more traditional word translated) to ordinary Javascript, and supplied file with structures, similar ideologically to C symbols tables, and within browser debugger (Chrome work) you could see not target JS but sources and debug on high level.
And when your code become mature, you just remove symbols tables and as usual, target optimized code become very much like obfuscated, and you could provide it as closed source.
So, as summary - must have all from list:
1. high-level language translator (may be into assembler, may be into some lover level language, as with ECMA-6 and JS)
2. some sort of debug support (as mentioned symbols tables)
3. good enough debugger, as much close to client platform as possible (Chrome is good example).
There is an (IMHO quite underexplored) alternative of using HLL as a metalanguage for generating low-level code. Like Chisel/Spinal does for Verilog RTL, but with C or LLVM IR instead of RTL. I. e. terra-lang did this with Lua (afair didn't took off because of unfixably bad design choices from the start).
Why this matters: compile-time metaprogramming is the way to provide zero-cost abstractions. HLLs tends to avoid metaprogramming because it's hard, instead relying on rich runtime (i. e. late binding and dynamic dispatch). Sometimes (i. e. in game engine code) that's not really an option. And metaprogramming is best done is something lisp-like, rather than C-like or C++-templates like.
As to why this is underexplored, I think there are multiple reasons:
- The most important one: those who care about the language tends to spend so much time on the language that they never get to the actual product,
- We already have C++ templates which can do anything (they are also an unholy ureadable mess because they were invented for a completely different purpose) and C macros (which are also unholy unreadable mess because K&R hated macroprocessors passionately and curbed cpp to a bare unusable minimum). And people exposed to those conclude that any compile-time metaprogramming must necessarily be an unholy unreadable mess not worth exploring.
- Most library bindings are in C, so any such system should include a C parser. At which point you wonder why bother at all?
> using HLL as a metalanguage for generating low-level code
Unfortunately, this is very long known dead-end, because very few programs written evidence-based, but most just begin their life with first production release, and on some platforms (JVM), more than 90% of developer time spend to refactoring and maintenance of existing code, and many people don't know anything else.
So, templates are not enough to break through this wall, need infrastructure of libraries and debuggers, and may be macros, etc, designed specifically for fp and be at least on par with their imperative counterparts.
From what I see, looking promising, to discontinue UNIX systems (based on C, and yes, Windows is also favor of UNIX, as NT was made directly on foundations of VMS from Digital), and switch to something more high-level, like OpenStep (with high usage of SmallTalk), or at least BeOS (based on C++).
Sure, would be better to use Prolog based OS, when one will appear, or may somebody will create OS based on OcaML (Haskell, Rust).
What I see problem for gamedev, in many cases they need very high performance, and when nearly all target (current) OSs are just C-machines, it is very much like discover epic huge wall, when need to switch from OcaML level to C to get additional few FPS.
So most people choose easy way, they learn just primitive subset of C++ and work with it.
BTW I have an idea - for gamedev could be beneficial to make some VM engine (multiplatform), for example like BEAM, why not, but probably something much faster (like LLVM), but including rich library of structures and algorithms for structured data and optimized for GD, and with good debugging tools for high level structures.
This may become gamechanger, as it could be very fast, but high level abstraction, so people don't need to dive into machine level, and could work on high level.
I worked with IBM PC clones and DOS for a long time. What I seen - just hexadecimal dumps, sometimes picture patterns and nearly nothing else.
Once one boy said me "this is Mac, on it things look different" and shown me just ordinary MS Office (for Mac) files in just standard utility. And I seen really other world - even on old MacOS (7..something), Office files was not just hexadecimal, but I easily see structure. Unfortunately, that's time I have not enough education in CS to understand how structures work, but some things was obvious. These was just some things partially implemented on ObjectiveC (too small objective part and too large C part), but any way it become significant shake of my world.
Unfortunately, in Linux I constantly see the same as in DOS - mostly just hexadecimal dumps, no structure, so developers don't have motivation to use structured data, as it will not help them on build and maintenance.
Jan, This is awesome! I have been following your progress for quite some time now. I actually found your project because you liked my dream chaser model that I put on GitHub some time ago. Really Looking forward to what’s to come and to try out your simulator at some point!
It took me a minute to realize that you're talking about code formatting on HN, and it has nothing to do with Clojure.
I was like: "What formatting are they talking about? It's darn Lisp - there's no 'formatting gripes' here..." The only thing Clojure devs have to agree on - to align or to indent, and that's all the formatting rules and conventions you need to know about.
Inexperienced newbies say: "Lisp is hard to read", which I think is completely overblown and in fact is the opposite - Lisp is so nicely readable, that even on a narrow screen of a phone it remains readable - the code simply wraps around - a trick Python and Haskell programmers especially hate.
I have yesterday tried to read docs (sure, find by google :) ), and there stated "Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.)".
So what's your point? I guess you haven't even used Clojure, just looked at this specific piece of code and decided for whatever reason is not "good"?
It's as if I posted some text in Sanskrit (which I don't know) and complained that some people put Bhagavad Gita on a weird pedestal - "verdic concepts don't make your religion magically better".
Can you elaborate the heck you're complaining about? Arguing that "this FP code doesn't look nice to me, but OOP generally does", without more context is like arguing that "this French poem doesn't sound nice to me, but English poetry generally does" without understanding either language deeply.
That's just comparing surface aesthetics rather than understanding the underlying paradigms, idioms, and design principles, not to mention the fact that Clojure isn't "purely functional" - it does have object-orientation and polymorphic dispatch and other mechanisms that you've apparently put on some other weird pedestal.
I just can't wait to see how Jank gets production-ready and absolutely blows the indie gaming community. Hopefully, very soon.
Programming is a tiny part of game development. No programming language would blow anything in the indie game community. It would be nice and welcome, but it wouldn’t revolutionize anything.
> It would be nice and welcome, but it wouldn’t revolutionize anything.
I dunno, it'll certainly revolutionize my world once it's ready. A editor connected REPL, changes to running games on the fly while keeping existing state, using a well-designed language like Clojure but getting the performance (or similar) of C++ and native binaries.
It's pretty much a win-win-win for me, especially if I can replicate the speed of development I get with normal Clojure but for game dev.
If it is built in Lisp it will end up very customized. Just look at how far people take their emacs setups. It will be like a bespoke glove.
Yes, you don't have to keep on selling it to me, you've hit oil already! I'm eager to reach the future :)
my understanding from game dev friends is that's precisely what they do, no?
> my understanding from game dev friends is that's precisely what they do, no?
Do what? Program games in a Lisp engine? That's quite atypical, which is unfortunate. It's almost impossible to convey the sensation of "living" within a Lisp machine. Those who haven't experienced Lisp programming and haven't become accustomed to the process cannot grasp the dopamine effect of writing instructions virtually anywhere, at any time, changing the things on the fly. It's enormously empowering, and it's incredibly liberating.
That's why those who at least once unleashed the true power of Emacs simply can't feel the same joy in anything else. Other editor and IDEs talk about features like "keyboard macros" and how powerful they are, yet they fail to grasp that Emacs operates on an entirely different plane - its keyboard macros are programmable constructs that can be created, modified at the Lisp expression level, and converted into full-fledged functions from any recorded sequence.
Using Emacs is like playing a video game where you level up by writing s-expressions. The profound satisfaction of shaping the system to match your exact needs is immense, and sadly remains vastly underappreciated. Even when curios newbies come to explore this "immense power of Emacs", they don't even realize that it all is possible only because of Lisp.
It just feels weird to me that the gamedev community outright rejects the idea of programming in Lisp. To me (a Lisper) writing games that way makes absolute sense - games should be written as if you're playing one, right?
the Arcadia team spent several years on this hypothesis, I am not sure the idea of a Clojure REPL for gamedev is free of impedance mismatches
Arcadia's biggest drawback was that it was dependent on Unity, which meant that it had all of the issues that Unity had plus some new ones. Without source code access it's difficult to exceed the features/performance of the base engine.
Maybe they've fixed some stuff (or ported it it Godot) since I last checked it, but the general lack of editor support, the clash between how Unity wanted to operate and how Clojure wanted to work, and usual Unity problems kept me from building anything significant in it.
I'm curious how this would go with something like Janet that is much simpler to interface with C++.
AFAIK Janet is not "much simpler to interface with C++". Janet has good FFI for C, but not for C++ directly. Janet's native FFI system is designed specifically for C libraries. C++ has name mangling, classes, exceptions, and other features that Janet's FFI cannot directly handle. The process would be similar to using C++ libraries from any C-based language, which is far from straightforward.
Jank, if my understanding is correct, in comparison has direct C++ interop. Jank treats C++ as a first-class compilation target rather than a foreign interface.
It shouldn't be that much work to wrap a C interface into C++ but yeah Jank is probably the way to go if it natively supports C++.
Yeah, well, I don't think it's that simple. You can't just say "eh, gamedevs apparently just don't want 'interactive workflows'", which of course, not true - look at Unreal's Blueprint live editing, Unity's play mode value tweaking, Godot's live scene editing, Jonathan Blow live-coding an entire game, etc.
I don't know why Arcadia wasn't very successful -I have never used it; I can only speculate on the causes, but I have good reasons to believe that Jank may actually succeed where Arcadia struggled - it is designed ground-up for game engine integration, no GC pauses, better FFI for engine bindings, etc.
the request/response command/query nature of the REPL is what I am referring to. Great fit for RPC-oriented web backends backed by OLTP databases that start fresh each time and run to completion. Live scene editing seems closer in nature to a hot module reloading workflow, where we try to take care not to disturb long-lived objects and processes. PS, Jank is very cool. No idea what his plans are here and I’m not claiming a gamedev repl is impossible in any way.
> Programming is a tiny part of game development.
This is a weird take. It's a tiny part of game development until you can't program. Then you realize it's actually a huge part. Particularly for "indie" game development.
Ultimately code is just a tool, but it's still a tool that can translate into rapid iteration or into friction.
> Programming is a tiny part of game development.
Yeah, jut like writing is a tiny part of book publishing. What the heck are you even talking about? Programming is absolutely fundamental to game development - it's literally what makes games exist and function.
I'm not talking about "revolutionizing" anything, but maybe you haven't noticed how Unity democratized gamedev and how GDScript made game logic accessible. There is absolutely a sizable chunk of the market for the Lisp-based gamedev - look at Lua/Fennel gaming community - LÖVE2D, Pico-8, Defold engine, etc.
Having performant Clojure option (which Fennel ain't - it's only "like" Clojure) would be absolutely wonderful news.
I think Jank will find its people, but I don't know how many of those people will be indie game developers. I'm sure some will be, but on the whole I don't think most indie game devs are clamoring for using clojure, if only if it wasn't for the JVM or the performance. I doubt many indie game developers are even aware of what clojure or jank are, or even much about functional programming to be frank.
For indie game devs you're competing against engine ecosystems like Unity, Unreal, Godot. If someone is inclined for more of a DIY route, you're competing against Lua (love2D), C# (monogame), Javascript (...), or for the people who care about performance, C++, Rust, Odin, Zig, and soon even Jai. It's a very crowded competition space and again, I think overwhelmingly the people in this space aren't dreaming of programming in a functional style.
> you're competing against Lua
There's not exactly tiny community (but it's not huge either) that programs against Lua-based engines using Fennel - a Clojure-like Lisp. Jank, aimed to have one-to-one Clojure-parity, I think would be great news.
> the people in this space aren't dreaming of programming in a functional style.
IMO because they are extremely pragmatic and there still, doesn't exist a good, practical way to program games in a functional style. Jank may open that possibility.
Then there are folks like Notch, that by not following such advices got gold, as they managed a great additive game, regardless of the technology stack being used.
There is also 80% of the mobile phone market available, in the context of JVM like ecosystem to target, and avoiding NDK tooling is gold if one really doesn't need it, as its experience still sucks after all these years.
I was not meaning to say that anyone was wrong for their technology choices. Personally I think Java is great and some of my favorite games are made in it. I'm just saying that I don't see jank or clojure for that matter catching on because it isn't where the head space of the indie gamedev scene is at, and I don't see this changing, especially given the number of competing stacks.
Come to think of it, where is the headspace of the Indie gaming community at?
I imagine the point being the same as game development in general, hence my agreement on a sibling comment.
Many people, especially those coming from FOSS background, don't understand the game development culture is all about IP.
The culture is to create great experiences, with interesting gameplay, the actual programming languages tend to be whatever everyone uses in the industry, and in general proprietary APIs aren't the drama like in sites as this.
So if an indie is going beyond desktop, trying to maximise sales, they will pick an engine and language that covers them.
Ah, that is a good point.
Guile has [multi-methods][1] and [fast hash maps][2], but not yet [dynamic vectors][3].
Clojure's data structures are easier to use, though.
[1]: https://www.gnu.org/software/guile/manual/html_node/Methods-...
[2]: https://www.gnu.org/software/guile/manual/html_node/Hash-Tab...
[3]: https://lists.gnu.org/archive/html/guile-devel/2022-01/msg00...
Yes, I forgot. However Clojure multi methods are more generic in that the function computing the dispatch value can also be defined.
Clojure is such a departure for me, coming from C-Like languages. I have absolutely no idea whats going when looking at the code.
Lisps (like Clojure) treat code as data (lists), so you write: `(if x (y) (z))` instead of Python’s `y() if x else z()`. So the code is more concise, but does less to walk a novice through it.
This gains a huge advantage, which allows even more concision: all code is data, so its easy to transform the code.
In Clojure if you want to add support for unless, a thing like if, but evaluating the opposite way you could do this: `(defmacro unless [p a b] `(if (not ~p) ~a ~b))`. Obviously if you wanted to do the same thing in Python you would in practice do `z() if x else y()`. However, you would do it that way because Python isn't as powerful a language. To actually do the same thing in Python you would need to...
1. Add __future__ support.
2. Update the Python language grammar.
3. Add a new AST type.
4. Add a new pass stage to the compiler.
5. Add a python library to integrate with this so you could use it.
Then you could do something like:
So in the trivial case its just hundreds of lines harder plus requires massive coordination with other people to accomplish the same feat.This sort of, wow, it takes hundreds or thousands of lines more to accomplish the same thing outside of Lisp as it does to accomplish it within Lisp shows up quite often; consider something like chaining. People write entire libraries to handle function chaining nicely. `a.b().c().d().map(f).map(g)`. Very pretty. Hundreds of lines to enable it, maybe thousands, because it does not come by default in the language.
But in Lisp? In Clojure? Just change the languages usual rules, threading operator and now chaining is omnipresent: `(->> a b c d e (map f) (map g))`. Same code, no need to write wrapper libraries to enable it.
That doesn't look like a factor in the article though, he isn't using many if any macros that aren't part of the core language. And the one macro I do spot (defcfn) is pretty mild in context.
I've programmed in Clojure professionally.
People like GP often repeat that talking point: "code is data so that's amazing because of macros".
In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
Macros can almost always be expressed with a simple function and remove all the unexpectedness without losing anything. Again, there are some exceptions.
> In practice, by and large, with very few exceptions, macros are frowned upon in the same way that using metaprogramming in ruby is. Macros are only fun to the person writing them (and not even the author when they have to maintain it).
I'm not sure "frowned upon" is the right expression, but I'm not a native speaker.
The way I've internalized it, is basically "Avoid macros unless there is no other way", which basically means use functions/anything else whenever you can, but if you absolutely have to use a macro for something (like you wanna read the arguments before they're parsed), then go for it.
Thank you for posting this.
I always looked at these features of being able to extend the language beyond some commonly accepted practices as detrimental to the language. I've spent way too much time debugging issues with operator overloading or complex templates (C++), or obscure side effects in DSLs. So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
But... looks like the professional community knows this and so maybe it's time to take a deeper dive :)
> So, (re)defining language constructs in a project seems nightmarish to me to support in production and therefore I never even attempted anything serious in a functional programming language.
It can be, but also not. If you isolate them into libraries with clear interfaces, you can kind of avoid that. I think clojure.core.async is an excellent showcase in something you couldn't do in other languages, where asynchronous channels were possible to add to the core language without changing anything in the core compiler itself, and because of the small interface, you can still use it without ending up with nightmares :)
Understood. I was more referring to a case where a project would start defining its own language constructs and if each project would do that then every single project would come with a very high cognitive load.
Dunno about the Clojure communtity but for Emacs Lisp and Common Lisp there are certain broadly accepted idioms where macros are accepted:
1. "with-context", where there is a need to control resource allocation/deallocation or things in the context of code in question. 2. use-package dsl that simplify configuration in a predictable way 3. object definition helpersresource
Then, there are core language extensions and std libraries suggested for the main implementation. This is where macros are fine as they always get good documentation and plenty of additional eyeballs.
Fully agreed with your examples. As a rule of thumb macros should be kept inside libraries, not application code.
I use a few macros for creating contexts (i.e. with-texture, with-stencil, with-scissors, with-tar). Also I have macros for rendering (onscreen-render, offscreen-render). However I try not to overuse macros.
This was incredibly useful
Fun fact: the big difference isn't the syntax. Lisps only go from foo(bar baz) to (foo bar baz) which is a change but not really much of one. The change is actually the immutable and high performance basic data structures. Clojure can do something that something like C can't do - cheaply create a copy of something with a small change. That leads to a completely different preferred code style in the Clojure community that is a big departure from C-like languages which make heavy use of variables. The code is doing something practically different from what a C-like language can ergonomically handle.
Clojure has a bunch of other syntactic structures not found in other lisps that makes it a lot more visually noisy. I'm very comfortable with Scheme and I can very quickly absorb Scheme code when reading it, but I have to very slowly decipher the code in the article.
> not found in other lisps that makes it a lot more visually noisy
I disagree. It only feels that way, until you learn how destructuring works in Clojure. Once you grok that, you'd understand why the vector syntax for function arguments was chosen, and not a simple list like in other Lisps. In general, Clojure is highly pragmatic - if something done certain way, most-likely it's for good reasons, and not by accident.
Also, Clojure-maps are just freaking amazing. I wish others, e.g., Elisp had them.
Clojure is extremely and nicely readable, just requires some getting used to it. At some point, I completely replaced my API-testing workflows, switching from JSON to EDN - it's almost twice more compact and much better visually, not to mention that it's incredibly nice to be able to just explore and visualize any given data through the REPL.
> It only feels that way, until you learn how destructuring works in Clojure
Well... yes. The original comment was about how Clojure code looks very foreign. The reply to that was that Lisp code is not actually that foreign because it's just taking the common foo(bar baz) and making it (foo bar baz). My comment was that Clojure is more foreign to most programmers than other Lisps, because it's not simply mapping foo(bar baz) to (foo bar baz).
Of course when you learn the things that make it unique, it becomes familiar.
Many of Lisp ideas are possible in C++, but I guess that depends how much you know it.
That's just existing muscle memory. Nothing is wrong with you and nothing is wrong with Clojure. I had the same feeling when I started with Lisp. Give it some time, it's absolutely worth it. Interestingly, every single programmer I introduced to Clojure as their very first programming language had no issues picking it up. Later, they complained about difficulties getting used to Javascript and Python.
it's not code it's data. :) -macro
As a Clojure developer for many years, this is one of the coolest projects I've seen! Going to read your blog with interest!
Very cool work Jan!
Have you tried experimenting with ham-fisted? I've found the libraries in the techascent part of the Clojure ecosystem to be very good performance wise. Ditto for neanderthal.
I am aware of Neanderthal. I think it is more suitable for larger tensors and matrices. Will have to check out what ham-fisted is about.
Wow, this is impressive not using standard gaming framework like Unity or Unreal.
I mean it is pretty cool, but do people not roll their own graphics engines anymore? When was in to hobby game dev back in 2000 or so, we all wrote our own systems.
No, that's rightfully viewed as a waste of time if you want to make a game (vs if you want to make a game engine)
Using same game engines and physics lead to a generic look-and-feel, even if they do allow for a large amount of creativity and differences.
This _looks_ different, which is awesome!
Even if the atmospheric effects still need some honing, there's a ton of work around lighting to eventually be done, the edgy polys make it look about 20 years old, and it's a bit pixel-y around the edges, this is headed into a spectacular direction!
If my ADD were in charge of this project, here's what I'd add:
- Optional stars / environment - a universal simulation would be unrealistically computationally expensive, but just having stars would be neat. Later, a planet in the horseshoe nebula, or playing spherical versions of recorded or streaming video for AR or making homegrown music videos.
- Ability for others to share datasets - the Earth is f-ing awesome and I can't wait for the Moon! What about a place where users could share different datasets like Arrakis with it's sand dunes and 2 moons or Tatooine with its 3 moons, then maybe they could fly in a heighliner, landspeeder, frigate, or imperial lambda shuttle, or even the jetcar from Buckaroo Bonzai?
- Solar Mayhem - Simulate a crazy atmospheric and orbital space war simulation or arcade-style game with satellites, lasers, plasma / electrical discharges and arcing, dust and nanorobot clouds, cloaking, jamming, ramming, repairs by robots and soldiers in tethered spacesuits, zooming cameras and 2D/3D scanners in different wavelengths, spacefaring naval ships, UAPs and other secret government vehicles, and complex 20th century fantasies of space stations running on nuclear and otherworldly power.
- Eclipse Support - when you add the Moon, doing an eclipse is not just the shadow but you'll need to handle the cool colors on the edges when the moon is covering the Sun.
- Ocean Simulation - Orcas, fish, eels, coral, lobsters, octopi, old ruins, Atlantis with its merpeople, tictacs and other USOs!
- Beautiful water features in Baltic Sea, Yukon Delta, Mississippi River, Lena River, Petermann Glacier, Brunt Ice Shelf, South Georgia Island, Guinea-Bissau, New Caledonia, Patagonian Sea, and the Icelandic and Norwegian fjords.
- Weather simulation with a way to pull in current atmospheric data historically to fly through hurricanes and tornados or simulate tsunamis after earthquakes.
- Subterreania and the inner sun of the Earth.
- A 2D sim for flat earthers.
That's would certainly be an awesome game, but did you know that your "Solar Mayhem" concept already exists? Children of a Dead Earth - it's probably a bit more austere by virtue of limiting itself to only somewhat-plausibly realistic weapons, mind you.
https://childrenofadeadearth.wordpress.com/
That's a lot of features. Moon is on my TODO list though and eclipses would be nice as well.
> Using same game engines and physics lead to a generic look-and-feel
Sure but they're talking about using the same game engine, not the same physics engine. I don't think anyone would say Split Fiction looks at all like Oblivion Remastered. Though they both use Unreal Engine 5
The hardware graphics acceleration stack is heavily shader-based now, so there's less and less graphics code being written in systems languages like C. In a way, people are still writing their own graphics engines, it's just for such a different platform from the unusual Turing-computer CPUs that all the old techniques go out of the window.
Nothing stopping you from writing it the old fashioned way though - you can just keep generating a single screen texture in the CPU and let the GPU idle!
As old dog I find this kind of funny, because for folks of my age C was like C# is seen nowadays.
Any serious game would be pure Assembly, and when using Pascal, C or BASIC compilers, they would be full of inline Assembly, almost like a poor man's macro Assembler, as the quality of code generation was awful.
Good point! Wasn't the Sony PlayStation significant for being the first console to ship with a C API from the manufacturer, or am I misremembering? I always thought that Net Yaroze sounded fantastic but never ended up getting one.
Oh, and another question on that topic: did you ever write self-modifying code for games, or had that already gone out by 2000?
Always, when read about "functional language usage in simulation", I check if OpenGL binding used. Other important things are physics engine and collision engine, because these are more than 90% of all code.
Unfortunately, just as I suspected, this project use OpenGL (nearly all implementations are C++), and C++ collision/physics engine.
So, looks like, in this project, Clojure is used just as high level script to orchestrate all C++ parts, may be later we hear about some game scripting, but for simulators they are not as need as for example for RPGs.
I agree, Clojure is better than C++ for orchestrate, but I have seen so tiny number of art persons familiar with functional paradigm, so this looks like beautiful dead end.
Again, this is really beautiful and respectful achievement for author, but people I seen working in gamedev will not accept such approach.
That's literally the whole point of using a high level functional language though. You use it to express the business logic of your app, the code that you care about. The fact that the underlying details of how rendering and physics are done is written in an imperative language doesn't really matter here. What I care about is maintaining the logic of my application, and that's what a language like Clojure makes easier to do.
Why not use some simpler, like old good UNIX Make? Or for business logic existing for a long time Lua, which is much easier to learn/use than Clojure.
I love functional paradigm, but sometimes fp lovers, looks like evangelists of Blockchain or LLMs - not bad things, but all have their limits, and not very useful without powerful support of large library of fp structures and debugging programs. So, trying to use fp, you dive into abyss, writing with fp, but debugging with low level C debugger.
BTW, as I know, OcaML, flagship of fp, just don't have graphics debugger, so people used to write on Haskell using old classic REPL technology, than, thanks to syntax similarity, most code just compile on OcaML without additional moves.
OCaml supports imperative, functional, and OOP just fine, and you use whichever makes more sense, and it has a REPL, too, most popular one is called "utop", but "ocaml" works. As for graphics debuggers, I have no idea if OCaml has a graphical one (if that is what you meant), but there is ocamldebug[1][2].
That said, I agree, why not just use Lua? Seems like the perfect language when you only care about the game itself and not the underlying stuff. There are many other alternatives that are better than Clojure anyways. I might be pessimistic, but I doubt Clojure is going to catch on.
[1] https://ocaml.org/docs/debugging
[2] https://caml.inria.fr/resources/doc/guides/debug.en.html (contains section "Using the debugger under (X)Emacs")
Well, I'll believe you about fp debugger, so only problem left with OcaML and Clojure, each of them have GC with non-linear complexity (Clojure as I understand using BEAM GC which claimed soft-realtime, meaning 90% of GC work will look like realtime, but OcaML using some typical GC), and what all these mean for games - they will suffer framedrops or even short freezing, when GC running.
Exist two approaches to overcome GC problem, but if somebody will again minus my comment I will not bother to find links in my records.
1. Here on HN mentioned GC-free fp platform.
2. Few years ago appeared GC algorithm with linear complexity (sure, with limitations, but good enough for example for 16-bit consoles level games).
Unfortunately, haters minusing comments, but don't add anything valuable, and author was not mentioned these problems.
> Unfortunately, haters minusing comments, but don't add anything valuable
Tell me about it. It happens so often that I am very reluctant to leave comments now, especially on topics that I know people have already made up their mind and are not willing to discuss it with an open mind. That said, I did just leave a comment about something I probably should not have, but oh well.
Is it really Clojure that uses BEAM? I thought it was a JVM-based language, I would have to look this up.
BTW OCaml finally has multicore support, which was a long time coming.
As for GC, you might find OxCaml interesting or to your liking: https://oxcaml.org/[1].
[1] Especially this part: "OxCaml gives programmers tools to control allocations, reducing GC pressure and making programs more cache efficient and deterministic.".
Thank you!
For Closure, I just confused it with Elixir.
Unfortunately, I see very familiar things from Perl world - many people made really interest things alone, but for some reason, they don't organize to make one direction really on par with commercial platforms (even when with current technologies could make efficient distributed governance, and even could make significant sells for sustainable development). I mean, people disperse resources, making many good small things, but most Open Source software recessing or even in crisis without moving ahead.
I've seen JVM, BEAM, CLR at field with heavy load, they all have significant drawbacks, but from my opinion, CLR ecosystem developing faster than other mentioned.
> I thought it was a JVM-based language
Clojure is not a "JVM-based" language, it's a hosted language - means Clojure is designed as an abstract language that can be implemented on different runtime platforms. The language's core abstractions (persistent data structures, protocols, vars, etc.) are not tied to any particular host - it's just that JVM variant was first and remains the main focus. Clojurescript run on JS VMs, ClojureCLR on .NET, ClojureDart - targets DartVM, babashka is great for scripting, SCI - for small embedded Clojure DSLs. There is also Clojerl - that runs on BEAM, and Jank for native compilation. You can run Python in Clojure and Go, and it just keeps growing. Seriously, one could learn only Clojure and write code for [almost] any platform.
That is good to know, thanks!
Good point. I definitely need to keep an eye on garbage collector pauses. I am using the new ZGC which supposedly has very short garbage pauses.
Oh I'd love some talk on GC-free FP platforms!
https://github.com/carp-lang/Carp
I had this project starred and completely forgot about it!
wow thanks I had heard of this then totally forgot about it. This is super cool!
> why not just use Lua?
Because there isn't "true" REPL. Non-homoiconic languages don't have the same kind of REPLs, because every step in them - Read, Eval, Print and Loop have slightly different semantics.
I just wrote my Hyprland config in babashka - native Clojure scripting engine. Once I build a socket management function that connects me to hyprctl, I was able to do the rest from within my editor connected to the REPL. I would write (hypr-cmd :clients), eval it, get the list of windows in my WM, and then filter, group, sort, etc. It is so much nicer to build things "from within", most people who never experienced that, wouldn't get it.
I'm running my WM and fully controlling it by writing code and executing it in-place, from the editor running in that same WM - without saving the code, without compiling it, without restarting the WM or my editor. I'm programming my shit as if I'm playing a video game. If I was a game developer, for sure, I would stick to the same mentality - why the heck work on a game, if I can build it by playing?
What about Fennel, would that work?
As for the rest, yeah, I have used stumpwm before and configured it on the fly. :D
Fennel already "works". There's a small community of devs around it and in my opinion and practice, it remains a better choice to use instead of Lua directly. I don't even hesitate - whenever I need to tap into Lua-based engines, I would try to bootstrap Fennel on top - I use it with Hammerspoon, with Neovim, with mpv, and if I at some point I finally decide to switch to Wez terminal, I will for sure use Fennel.
That being said, Fennel is nice but ain't ideal, it's rather weird. It tries to imitate Clojure syntactically, without actually posing as a Clojure dialect. Fennel is extremely thin layer over Lua - you're essentially writing Lua with s-expressions. In Fennel, you constantly feel Lua's presence (1-indexed arrays, table semantics, nil behavior), while Clojure abstracts over Java/JS/Dart/etc., much more heavily with its own semantics. I constantly feel like I'm missing good CLJ ergonomics - no built-in immutable data structures; no rich standard library; limited REPL experience;
The difference in philosophy is that Fennel prioritizes being "just a syntax" for Lua and Clojure prioritizes being a "better language" that happens to run on JVM/JS/.NET/Dart/etc. Makes Fennel feel more like a transpiler - remember the days of Coffeescript?
I guess, maybe all that actually makes Fennel more appealing to some - abstraction layer thickness sometimes does matter. I personally, wish for an actual Clojure dialect on top of Lua, rather than something "like Clojure".
> Lua, which is much easier to learn/use than Clojure.
As someone who used both, I can certainly argue for that point not being true at all, and in practice it isn't.
Lua's syntax is a mixed bag and even after years dealing with it, I just can't stand how ugly the darn lang is - I just never know how to format it for better readability. Metatables are powerful but conceptually complex; global by default and 1-indexed arrays - who the fuck even thought it was even worthy to call it "an idea" - those are just plain stupid. Nil handling can also get weird.
While Clojure for sure may feel like having a steeper learning curve, once you get past parentheses - it feels so much simpler.
As I understand, you mean, fp approach is comfortable to work with large codebase. But in GD this is not the case, and even not was case at past.
Why so, because, at digital games dawn, hardware was too limited, just hardware limitations prohibited large projects; when appeared big networking games, complexity shifted to server-side, so for them subject irrelevant; now possible big games without networking, but high-definition multimedia costs prohibitive.
So, for subject only relevant small games, with small codebase, so they even avoid text programming at all and many people switched to so named Visual Scripting (google).
https://news.ycombinator.com/item?id=45158181
> As I understand, you mean, fp approach is comfortable to work with large codebase.
I didn't say anything about "large codebases" or "FP approach". I'm just saying that in comparison with Lua, Clojure holistically simplifies many aspects of the entire process - for small and large code, and not only because it's an FP language - after all, it's not "purely functional".
Clojure gets many small details right that other languages, including Lua, struggle to handle elegantly. But programmers often face a cognitive trap: once they master their language's quirks and edge cases, they mistake familiarity for design quality. What once seemed obscure becomes "the way things should be". This expertise paradox prevents them from seeing these quirks as the pragmatic obstacles they really are - they've internalized the workarounds so deeply that they defend them as features rather than flaws.
Clojure is not without flaws, but somehow, it just doesn't feel like one needs to learn a collection of language gotchas to be productive.
We can talk about philosophy, psychology, technical merits, and design of programming languages, but at the end of the day people will use whatever makes them happy. Clojure and its dialects genuinely bring joy to thousands of programmers, and I understand now why. After writing code in a dozen of languages, I see why.
Ok, I'll say more strict - I talking about GAMEDEV, not about abstract things.
And in GD, code have much less importance than in other fields.
As example, I once meet amateur of RC-planes, and looking on his setup I asked, why his electronics is so simple, as I understand, he could make much more sophisticated things.
Answer was: "here, I want to be airplane designer, not electronics designer, so I make plane highest priority, and sure, when you will make your plane, you could make electronics priority".
Again, this is not philosophy, this is real thing - in GD language is the least important thing for happiness, in best case it is small obstacle at the way to create game, so the best language could be no language at all.
If you could suggest some way, how it is possible to do platform where programming language hidden deep under the hood, so people just don't use language at all, but things are done, this will be very constructive talk.
> code have much less importance than in other fields.
Although I'm not a game developer anymore (I've done some in the past) I still have hard time believing this sentiment to be true, even today. Game development is interdisciplinary - code, art, design, and audio all matter. But code is definitely not less important than in other software fields; it's just that games also need those other disciplines to succeed.
Yes, modern game engines abstract away low-level code and many successful indie games have simple mechanics but great art/design, still, code remains one of the most important aspects of a good game. Physics, collision detection, rendering and graphics optimization, network for multiplayer, AI for NPCs and procedural generation, performance optimization, state management, input handling - all that still needs code.
> all that still needs code
Nope.
It's 2025 outside.
Google "Visual Scripting", "Unreal Blueprints". It is now possible to make game literally without writing any STRING of code.
Second, with development of AI more and more appearing "no-code" solutions, in some cases even capable deliver app from blueprint painted with pencil on paper.
I can only assume you're trolling here or that you've never actually built any large applications in your life.
This is interest assumption, but let's think, who are building large applications?
I've taken part at some large apps built inside one company in extremely short time. And no, in my list only more or less adequate platforms - Perl, MS VBA on web.
And I've countless times just rebuilt some large systems from sources - FFMPEG, Unreal 4 environment, what interest, whole FreeBSD 4.x with BSD environment including XWindow is smaller than U4.
And what was really big pain, I tried to work with NASA OpenMCT, and because it was based on Javasript technologies, I spent huge amount of time to figure out, where end server-side and where begin client-side. I think you understand this is important, because each part debugged with very different instruments and techniques.
And what I must say there, games are very different in scale.
- Sure, exist very large games (named AAAA, like cinema movies, and have so huge download size, as for example new Stalker, that my friends working in telecom complained, it was like huge DOS attack when game came out). And what also interest, AAAA games tend to make their own custom game engine, yes, each game with own game engine, because for them easier to figure out in their own code than to learn ready game engines.
Also exist industry of game studios, medium businesses, but they tend to be much like big businesses just without resources to make own engine.
And also exist huge industry of independent -games (i will use indi- name), which have very small amount of code, because of tiny budgets or just "no-budget" work, in many cases literally made by one person, who making pictures, code and sound himself. And in reality I know very few cases, where indi- makes his own engine, but most others are slightly modified already known game mechanics.
What important - big business will not use subject code, nearly guaranteed, because they have very specific demands about maintenance, to fulfill them need at least medium company; there is more probability to reach medium business clients, they are trying to be "like a big boys", but in most cases possible to achieve some understanding; and the most probability is to reach indi- developers.
So, what we talking about now, is mostly about indi- developers, one-person sized commands, and it is very god if they will just use C-like languages, but you cannot account for them to use fp paradigm.
I cannot at the moment give estimate of distribution of game sizes, but now tend to appear more indi- developers with small games (and sure, using some made by other people.
https://nasa.github.io/openmct/
In the past I have done some rigid body physics in GNU Guile (see https://www.youtube.com/watch?v=zBq3kW2jVxs for example). Of course if you need to simulate many objects, you will hit performance problems sooner if you don't use C/C++/Rust. Also the developer of Jolt has solved quite difficult problems, so I was quite happy to use it instead of rolling my own.
Computers are stateful and imperative, so any functional language that runs on real computers has a stateful and imperative base. OpenGL vs not seems like an odd place to draw the line on what you would consider functional vs not.
> Computers are stateful and imperative
This is semi-Truth.
Modern off the shelf Microcomputers nearly all imperative, because marketing won, but when world was under Mainframes (nearly up to 1980), existed many examples FP-optimized architectures or high-level architectures, even some of them was commercially successful (Lisp computers and some high-level mainframes).
Also, most developers don't deal with naked hardware, but working with libraries of structures and libraries of high level algorithms, this named abstraction layer. Just some existing abstraction layers are less abstract and other are more abstract. As example, in Windows (and in most UNIXes) file abstraction is very simple and just imperative, but in MacOS it is OOP (derived from NEXTStep as I hear, based on ObjectiveC), and also exist some other OSes based on OOP languages, like BeOS, even when MacOS/BeOS are now running on same x86 hardware.
So possible just run inside higher level VM.
And mathematics is not prohibiting FP-machine, they could have very effective implementations with modern math.
What really problem, except of Prolog, I don't hear about high-level debuggers for fp languages, so writing on for example Ocaml, you once end up looking on fp structures with old C debugger, which sure don't see fp structures.
A Lisp machine is no counterexample - they had assembly language instructions that were tailored for Lisp, but were still very much imperative. In fact, Clojure is significantly more functional than other Lisps, which used mutable cons cells extensively. Object oriented languages are also stateful and imperative, so I'm not sure why those are relevant here.
I'm not saying these things are bad - it's possible to imagine a computer architecture that makes functional programming easier, but it's really hard to imagine a useful computer that is not stateful and imperative! What would it do, in that case?
OpenGL vs not-OpenGL still seems like a very arbitrary way to classify simulations.
Lisp really counter-example, because they have read-ahead (superscalar), specialized data types and hardware GC support.
Read-ahead (superscalar) becomes typical from Pentium and similar class CPUs; even specialized data types gaining some usage (AVX-512, FP-16/FP-8); but for hardware GC I don't know any widely used examples.
What conclusion do you draw from that? Nothing you're saying contradicts anything I said.
I stated exactly - MICROCOMPUTERS are stateful and imperative just because marketing dictated them, but multi-chip CPUs are not always imperative.
Other conclusion, looks like you are hater, minusing my comments just because you don't agree and don't accept any views except your own.
We're talking past each other somehow. Nothing I've said in this thread is hateful.
So I must assume your answer as "thank you for your view, I just see other"?
I just don't see thank you. Formally your answers are not hateful, but you may say thanks for info I provided, as I see you was not aware before.
What would have been an alternative way to go here that would have been more acceptable to gamedevs?
From second view, looks like good way using ECMA-6 (for example) with Babel and some things added into browser debugger.
So, technically, high-level ECMA-6 language transpiled (more traditional word translated) to ordinary Javascript, and supplied file with structures, similar ideologically to C symbols tables, and within browser debugger (Chrome work) you could see not target JS but sources and debug on high level.
And when your code become mature, you just remove symbols tables and as usual, target optimized code become very much like obfuscated, and you could provide it as closed source.
So, as summary - must have all from list:
1. high-level language translator (may be into assembler, may be into some lover level language, as with ECMA-6 and JS)
2. some sort of debug support (as mentioned symbols tables)
3. good enough debugger, as much close to client platform as possible (Chrome is good example).
There is an (IMHO quite underexplored) alternative of using HLL as a metalanguage for generating low-level code. Like Chisel/Spinal does for Verilog RTL, but with C or LLVM IR instead of RTL. I. e. terra-lang did this with Lua (afair didn't took off because of unfixably bad design choices from the start).
Why this matters: compile-time metaprogramming is the way to provide zero-cost abstractions. HLLs tends to avoid metaprogramming because it's hard, instead relying on rich runtime (i. e. late binding and dynamic dispatch). Sometimes (i. e. in game engine code) that's not really an option. And metaprogramming is best done is something lisp-like, rather than C-like or C++-templates like.
As to why this is underexplored, I think there are multiple reasons:
- The most important one: those who care about the language tends to spend so much time on the language that they never get to the actual product,
- We already have C++ templates which can do anything (they are also an unholy ureadable mess because they were invented for a completely different purpose) and C macros (which are also unholy unreadable mess because K&R hated macroprocessors passionately and curbed cpp to a bare unusable minimum). And people exposed to those conclude that any compile-time metaprogramming must necessarily be an unholy unreadable mess not worth exploring.
- Most library bindings are in C, so any such system should include a C parser. At which point you wonder why bother at all?
> using HLL as a metalanguage for generating low-level code
Unfortunately, this is very long known dead-end, because very few programs written evidence-based, but most just begin their life with first production release, and on some platforms (JVM), more than 90% of developer time spend to refactoring and maintenance of existing code, and many people don't know anything else.
So, templates are not enough to break through this wall, need infrastructure of libraries and debuggers, and may be macros, etc, designed specifically for fp and be at least on par with their imperative counterparts.
I don't know such way now.
From what I see, looking promising, to discontinue UNIX systems (based on C, and yes, Windows is also favor of UNIX, as NT was made directly on foundations of VMS from Digital), and switch to something more high-level, like OpenStep (with high usage of SmallTalk), or at least BeOS (based on C++).
Sure, would be better to use Prolog based OS, when one will appear, or may somebody will create OS based on OcaML (Haskell, Rust).
What I see problem for gamedev, in many cases they need very high performance, and when nearly all target (current) OSs are just C-machines, it is very much like discover epic huge wall, when need to switch from OcaML level to C to get additional few FPS.
So most people choose easy way, they learn just primitive subset of C++ and work with it.
https://en.wikipedia.org/wiki/Comparison_of_operating_system...
BTW I have an idea - for gamedev could be beneficial to make some VM engine (multiplatform), for example like BEAM, why not, but probably something much faster (like LLVM), but including rich library of structures and algorithms for structured data and optimized for GD, and with good debugging tools for high level structures.
This may become gamechanger, as it could be very fast, but high level abstraction, so people don't need to dive into machine level, and could work on high level.
I worked with IBM PC clones and DOS for a long time. What I seen - just hexadecimal dumps, sometimes picture patterns and nearly nothing else.
Once one boy said me "this is Mac, on it things look different" and shown me just ordinary MS Office (for Mac) files in just standard utility. And I seen really other world - even on old MacOS (7..something), Office files was not just hexadecimal, but I easily see structure. Unfortunately, that's time I have not enough education in CS to understand how structures work, but some things was obvious. These was just some things partially implemented on ObjectiveC (too small objective part and too large C part), but any way it become significant shake of my world.
Unfortunately, in Linux I constantly see the same as in DOS - mostly just hexadecimal dumps, no structure, so developers don't have motivation to use structured data, as it will not help them on build and maintenance.
Jan, This is awesome! I have been following your progress for quite some time now. I actually found your project because you liked my dream chaser model that I put on GitHub some time ago. Really Looking forward to what’s to come and to try out your simulator at some point!
Thanks.
This is awesome! Very nice example of malli in practice!
Thanks. Yes, Malli is really nice. Unfortunately it doesn't let you decorate type-tagged methods.
Beautiful visuals. I'd like something to dock with.
Yes, space station docking is on my todo list.
This was an amazing blog post, thank you!
Is the code formatting not working for anybody else?
It took me a minute to realize that you're talking about code formatting on HN, and it has nothing to do with Clojure.
I was like: "What formatting are they talking about? It's darn Lisp - there's no 'formatting gripes' here..." The only thing Clojure devs have to agree on - to align or to indent, and that's all the formatting rules and conventions you need to know about.
Inexperienced newbies say: "Lisp is hard to read", which I think is completely overblown and in fact is the opposite - Lisp is so nicely readable, that even on a narrow screen of a phone it remains readable - the code simply wraps around - a trick Python and Haskell programmers especially hate.
I have yesterday tried to read docs (sure, find by google :) ), and there stated "Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.)".
- Tried, and it really work.
https://news.ycombinator.com/formatdoc
Just for test purposes.
just linking the code, I'm just saying that some people put functional languages on a weird pedestal. It doesn't just magically make your code good.
https://github.com/wedesoft/sfsim/blob/main/src/clj/sfsim/co...
Yes, the main function is the worst part of the code. Whenever I discover a pattern, I refactor it and put it in a module.
So what's your point? I guess you haven't even used Clojure, just looked at this specific piece of code and decided for whatever reason is not "good"?
It's as if I posted some text in Sanskrit (which I don't know) and complained that some people put Bhagavad Gita on a weird pedestal - "verdic concepts don't make your religion magically better".
Can you elaborate the heck you're complaining about? Arguing that "this FP code doesn't look nice to me, but OOP generally does", without more context is like arguing that "this French poem doesn't sound nice to me, but English poetry generally does" without understanding either language deeply.
That's just comparing surface aesthetics rather than understanding the underlying paradigms, idioms, and design principles, not to mention the fact that Clojure isn't "purely functional" - it does have object-orientation and polymorphic dispatch and other mechanisms that you've apparently put on some other weird pedestal.