This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-08-16
Channels
- # announcements (25)
- # babashka (15)
- # beginners (14)
- # calva (60)
- # circleci (1)
- # clerk (1)
- # clj-kondo (13)
- # cljdoc (7)
- # clojure (45)
- # clojure-austin (1)
- # clojure-bay-area (1)
- # clojure-brasil (4)
- # clojure-dev (9)
- # clojure-europe (24)
- # clojure-norway (105)
- # clojure-uk (2)
- # clojurescript (6)
- # conjure (1)
- # core-typed (4)
- # cursive (4)
- # datalevin (1)
- # datomic (25)
- # emacs (31)
- # fulcro (3)
- # humbleui (10)
- # hyperfiddle (19)
- # jobs (2)
- # luminus (3)
- # malli (13)
- # nbb (5)
- # off-topic (16)
- # polylith (2)
- # portal (7)
- # releases (2)
- # shadow-cljs (5)
- # sql (8)
Is there a technical reason why Clojure can’t import java files?
It would need to run the Java compiler to turn that source into .class
files to load.
Which means all of the javac
options potentially need to be exposed...
In theory, you could dynamically invoke javac, put the class files in your class path, and import them
See https://github.com/ztellman/virgil or my fork of it which is currently maintained: https://github.com/clojure-goes-fast/virgil
https://github.com/ztellman/virgil I apparently need to pay closer attention (although I think slack was lagging)
Maybe this is just the limits of my JVM/Clojure knowledge but what's the difference between the compilation Clojure does when parsing/compiling clojure code and compilation of raw java?
@UEENNMX0T Not sure I understood your question correctly, but I'd say that there is no difference (besides one is compiling Clojure code and one is compiling Java code:slightly_smiling_face:). Both transform the source code to JVM bytecode (a .class
file/files, however it doesn't have to be present as a file on disk, could be completely in memory), and then JVM classloader can load that bytecode, and from then on you can use the compiled code in your program.
Cool, that's what I thought. Clojure is pretty focused on "only Clojure code" and was originally built to be used alongside an existing Java app with an existing compilation process, but it's a little annoying that things like import
can't dynamically compile/recompile java when it's encountered.
Java's development paradigm is not very well suited for such piecewise recompilation. That is why the Clojure core doesn't include this functionality. If you need it and are ready to go out of your way to adapt the Java part of your project to such dynamic recompilation (or you are building one from scratch), then Virgil is a proper tool for that.
To follow up on that: Clojure's "unit of compilation" is a single form and the language is designed around that semantic so that the behavior of the REPL and the behavior of the compiler are essentially the same -- and the compiler is part of Clojure's runtime. Java's "unit of compilation" is a file and the whole mindset is "compile one or more files" followed by "run a program based on the output of compilation". So the compiler isn't part of the core runtime (the JRE), but it's in the JDK and can be invoked programmatically. At a distance, both processes kind of look "the same" but while dynamic recompilation and loading is part of Clojure's core semantics, the same isn't true of Java so there are some edges trying to make that work. I'm kind of impressed that Virgil exists (and works) but I would definitely consider it "niche functionality" 🙂
"unit of compilation" is a good way to think about it, thanks.
I have to agree with @U04V70XH6 that Virgil is quite niche and has its gotchas. At the same time, mixed Clojure/Java projects were a "standard" practice in the times when Leiningen and Boot ruled. tools.deps lags behind a bit in that department, and without Virgil you'd have to restart the REPL on each Java code change, but still having Java mixins in a Clojure project is nothing outworldly.
In the game I am developing (https://github.com/damn/Cyber-Dungeon-Quest), I have saved the domain data in *.edn files. Like https://github.com/damn/Cyber-Dungeon-Quest/blob/master/resources/creatures/creatures.edn.
I am looking to build a GUI to edit those fields, which should give me, for example a checkbox for booleans, etc.
I was looking to implement it with seesaw, now discovered cljfx, which seems to be quite an alternative and more actively developed.
But there might be tools out there to edit edn data? On the other hand, I will have to make lots of customizations like specify which values are allowed in :items
of a creature etc. Thought about using clojure.spec for this, but not sure.
The more I think about it, the more I understand what I want is actually an entity-component-editor.
Components are for example :image
and this component would need a specific behaviour in the gui. (for example filechooser, show image..)
I just found this which is quite interesting:https://vlaaad.github.io/reveal/feature/spec-forms
I've prototyped and investigated variations of turning specs into UIs, but I was never quite happy with the result. @U47G49KHQ seemed to share a similar sentiment in his London Clojurian's talks, https://youtu.be/lZtxc66zU5s?t=2061.
At least for me, some of the challenges of using specs for specifying UIs were:
• couples editing with validation
• making your specs better for specifying widgets makes it harder to specify validation and vice versa
• specs leave out a lot of info that would be useful in a generic editor
◦ UIs usually want to prioritize common properties and deemphasize less common properties.
◦ Layout
◦ Should a string?
or keyword?
picker allow any string (eg. textarea) or is it actually a mostly unchanging list of options?
◦ No references. While a treasure chest could contain any valid ::item
, you usually want it to be a reference to an item created previously.
It's not that I think it's impossible, but there's still quite a bit of work to make it useable as far as I can tell.
I find spec really useful, but I'm not sure it's the best tool for your use case. Spec is mostly about saying what data you can have rather than what data you can't have. If you'd like some validation that constrains the data (eg. only fire weapons dropped in desert levels), then you might want to try other options or use spec in addition to other tool. Another popular validation tool is https://github.com/metosin/malli.
Thank you! I am sure some system will evolve once I start defining which components can have what values
> I am looking to build a GUI to edit those fields, which should give me, for example a checkbox for booleans, etc. I'm curious why you don't build this inside your game engine?
I’ve also played with doing stuff driven by spec introspection in the past (not UIs, but close enough) and my general takeaway is that if you want to do introspection, you really want Malli. It’s just data, so it’s much easier to work with.
Maybe you can find something for json-schema on Desktop. Here is an example for web: https://rjsf-team.github.io/react-jsonschema-form/
Bookmarked Malli. I wanted to build it into the game, so there can be an editor too. But now going for swing/seesaw.
Looks good. Did you go with seesaw or cljfx for it? I would also suggest, doing a web UI is actually pretty nice. The app can start, launch a web server, and open a browser at the URL for it.
Its with seesaw, but tables are not editable by default even. And I have no idea how much work it is for example to make items/spells link to all available, etc. Hmm to push changes over http? Oh my god. I am also considering using libgdx scene2d.ui which is integrated into the game engine already, and more simple... But not so mature like swing with so many options,etc.
But a web UI would also look quite nice, and I could have pages for all the different domain objects, with links, etc.
I'm a little hesitant to suggest my UI library, https://github.com/phronmophobic/membrane, since there aren't a lot of builtin widgets, but tbh, the other options don't seem that great either.
One nice thing about membrane, is that it's highly embeddable so you could run your UI stand alone and/or inside your game engine (with some effort).
The UI is represented as views. There are multiple implementations for drawing views and you can provide your own (it's mostly just shapes, images, and text). Specifically for lwjgl3, I think there might be a way to reuse the skia or skija graphics backends.
IMO, it's much easier to implement widgets than it would be to embed other options (which you may not care about) or wrangle all of the incidental complexity caused by web tech.
Ya, I just feel all Java UI frameworks are in a weird place, because they're all a bit old and not really being improved much, like swing, javafx, etc. Some real programs use them, but in all cases I think it requires a large amount of customizing them to get what you want. While a webUI doesn't give you that native feel, at least it opens up access to the full gamut. Styling is much easier, you can use whatever widget lib you want, generally text highlight copy/paste, all that works well.
For game config and map editors, you usually want some custom widgets anyway.
I think the most sane way to go is https://libgdx.com/wiki/graphics/2d/scene2d/scene2d-ui which is fully integrated with libgdx, just was asking here in case I am reinventing the wheel for such entity-component-editors.
I do agree with @U0K064KQV that web tech is probably still the "safe" option.
But I guess at some point I want to integrate with the game itself, and web might not be good for that, although nice for editing text.
This is really not so easy the whole UI thingy. ... And every program has its own layouting etc.
That libGDX UI actually looks pretty good. Hadn't heard of it before. Might be more modern than swing and javafx, since it seems newer and maybe still maintained
But if I think about , I want to investigate game entities, right click context menus, it has to be scene2d.ui ...
There are two amazing products built with libgdx & scene2d.ui: http://esotericsoftware.com/ spine
And hyperlap2d: https://hyperlap2d.rednblack.games/
Its also quite simple, although not so many features like swing of course, something like sorting my table etc. I think I need to build by hand, but not sure.
Quick one: I saved my cider repl as a text file C-x C-w
and now it’s no longer a repl buffer. Any way to get it back?