9 ms·
Developing a Space Flight Simulator in Clojure
- MathMonkeyMan 1y agoGuile 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-and-Generic-Functions.html https://www.gnu.org/software/guile/manual/html_node/Methods-... [2]: https://www.gnu.org/software/guile/manual/html_node/Hash-Table-Reference.html https://www.gnu.org/software/guile/manual/html_node/Hash-Tab... [3]: https://lists.gnu.org/archive/html/guile-devel/2022-01/msg00023.html https://lists.gnu.org/archive/html/guile-devel/2022-01/msg00...
- exabrial 1y agoClojure is such a departure for me, coming from C-Like languages. I have absolutely no idea whats going when looking at the code.
- rufusthedogwoof 1y agoit's not code it's data. :) -macro
- roenxi 1y agoFun 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.
- Zambyte 1y agoClojure 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.
- iLemming 1y ago> 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.
- Zambyte 1y ago> 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.
- JoshCole 1y agoLisps (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.
- roenxi 1y agoThat 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.
- sabellito 1y agoI'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.
- iLemming 1y agoThat'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.
- pjmlp 1y agoMany of Lisp ideas are possible in C++, but I guess that depends how much you know it.
- wedesoft 1y agoYes, I forgot. However Clojure multi methods are more generic in that the function computing the dispatch value can also be defined.
- rookderby 1y agoBeautiful visuals. I'd like something to dock with.
- wedesoft 1y agoYes, space station docking is on my todo list.
- nodesocket 1y agoWow, this is impressive not using standard gaming framework like Unity or Unreal.
- adastra22 1y agoI 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.
- viccis 1y agoNo, 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)
- fkimexcited 1y agoUsing 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.
- shaunxcode 1y agoThis is awesome! Very nice example of malli in practice!
- wedesoft 1y agoThanks. Yes, Malli is really nice. Unfortunately it doesn't let you decorate type-tagged methods.
- iLemming 1y agoI just can't wait to see how Jank gets production-ready and absolutely blows the indie gaming community. Hopefully, very soon.
- msk-lywenn 1y agoProgramming 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.
- diggan 1y ago> 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.
- dapperdrake 1y agoIf 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.
- diggan 1y agoYes, you don't have to keep on selling it to me, you've hit oil already! I'm eager to reach the future :)
- iainctduncan 1y agomy understanding from game dev friends is that's precisely what they do, no?
- 1y ago
- JoshCole 1y agoVery 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.
- wedesoft 1y agoI 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.
- Fire-Dragon-DoL 1y agoThis was an amazing blog post, thank you!
- crichter 1y agoJan, 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!
- wedesoft 1y agoThanks.
- LouDNL 1y agoAs a Clojure developer for many years, this is one of the coolest projects I've seen! Going to read your blog with interest!
- simne 1y agoAlways, 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.
- beepbooptheory 1y agoWhat would have been an alternative way to go here that would have been more acceptable to gamedevs?
- simne 1y agoI 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_systems https://en.wikipedia.org/wiki/Comparison_of_operating_system...
- simne 1y agoBTW 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.
- wry_discontent 1y agoIs the code formatting not working for anybody else?
- simne 1y agoI 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 https://news.ycombinator.com/formatdoc
- simne 1y agoJust for test purposes. ───────────── / \ / \ / \ / \ │ │ │ circle of power │ │ │ │ │ │ │ \ / \ / \ / \ / ─────────────
- iLemming 1y agoIt 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.
- lyu07282 1y agojust 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/core.clj#L658 https://github.com/wedesoft/sfsim/blob/main/src/clj/sfsim/co...
- iLemming 1y agoSo 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.
- wedesoft 1y agoYes, the main function is the worst part of the code. Whenever I discover a pattern, I refactor it and put it in a module.