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.
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.
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.
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.
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.
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 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 :)
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.
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.
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.
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.
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.
> 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.
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?
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.
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.
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!
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.
> 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.
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++.
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.
> 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.
> 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.
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...
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.
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.
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 :)
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.
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
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.
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.
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.
> 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.
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!
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
I can only assume you're trolling here or that you've never actually built any large applications in your life.
What would have been an alternative way to go here that would have been more acceptable to gamedevs?
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.
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.
This is awesome! Very nice example of malli in practice!
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!
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.
> 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.
Beautiful visuals. I'd like something to dock with.
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...
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.