This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-20
Channels
- # adventofcode (1)
- # announcements (2)
- # babashka (81)
- # beginners (33)
- # calva (11)
- # circleci (4)
- # clj-commons (3)
- # cljdoc (7)
- # clojars (5)
- # clojure (21)
- # clojure-europe (5)
- # clojure-japan (1)
- # clojure-norway (27)
- # clojurescript (24)
- # emacs (11)
- # events (5)
- # fulcro (14)
- # lsp (40)
- # malli (9)
- # nbb (1)
- # off-topic (5)
- # portal (4)
- # reitit (8)
- # scittle (9)
- # shadow-cljs (14)
- # spacemacs (3)
- # tools-deps (3)
Hi all!
I'm trying to run libGDX Clojure code on Android, and I'm facing some problems.
I built a Clojure uberjar that is a dependency in the Android project, and some specific Clojure functions break the program (e.g. calling println
& reset!
isn't a problem).
My stack trace is the following:
I/AndroidGraphics: Managed buffers/app: { }
E/AndroidRuntime: FATAL EXCEPTION: GLThread 691
Process: com.flyhighware.rbhm, PID: 9403
java.lang.ExceptionInInitializerError
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:426)
at com.flyhighware.rbhm.core_clj$_startGame$fn__262.invoke(core_clj.clj:99)
at com.flyhighware.rbhm.core_clj.proxy$com.badlogic.gdx.Game$ff19274a.render(Unknown Source:12)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:474)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1573)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1272)
Caused by: java.lang.NoSuchMethodException: canAccess [class java.lang.Object]
at java.lang.invoke.MethodHandles$Lookup.findVirtual(MethodHandles.java:923)
at clojure.lang.Reflector.<clinit>(Reflector.java:38)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:426)
at com.flyhighware.rbhm.core_clj$_startGame$fn__262.invoke(core_clj.clj:99)
at com.flyhighware.rbhm.core_clj.proxy$com.badlogic.gdx.Game$ff19274a.render(Unknown Source:12)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:474)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1573)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1272)
W/System: A resource failed to call close.
As you can see, the problems is that someone is calling canAccess
which doesn't exist.
I found an answer in stack overflow: https://stackoverflow.com/a/53381284
Anyone has been able to run compiled Clojure code in Android?
Thanks!I think running clojure on android is pretty rare. I'm not aware of anyone doing it successfully in the last few years (although I'd love to be proved wrong!). It looks like the specific error you're running into is related to reflection. If you (set! *warn-on-reflection* true)
and get rid of all the reflection warnings, does that make a difference?
See https://clojure.org/reference/java_interop#typehints for more info on reflection warnings.
It worked, I'll try to add type hints everywhere in my small project and l'll let you know
Android is not Java, it just duplicated almost all of the Java API, as it existed when Android was created. Seems kind of strange to me that with Clojure being ported to JavaScript, .NET, and Dart (just the projects I know of), nobody has bothered with patching it up to run cleanly on the almost-Java system running on Android.
I successfully ran my libGDX code on Android using Clojure 🙂 But I probably don't want to add type hints everywhere since using libGDX uses lots of interop
Thanks @U7RJTCH6J 🙂
It's probably possible to find/create a tool that helps with the type hints, but makes sense if that is more trouble than it's worth. There's also no guarantee that you won't run into other issues, but maybe it's not so bad. Thanks for the report!
You might be able to reduce the need for type hints with careful structuring of your code. E.g. In most cases type-hinting once a the top of a function is enough for everything that happens inside that function.
@U90R0EPHA Yeah, I agree. I set the type hints in the function's agrs.
hi! is there a a clojure utility function that allows easy templating of a map's values into a string? something like (str-template-fn "This is a {:adjective} {:what}" {:adjective "short" :what "template"}). Java's string formatter I know, but I don't want to keep repeating (:prop1 map}, {:prop2 map}, etc. in the paramter section.
not builtin clojure, but may work for you https://funcool.github.io/cuerdas/latest/cuerdas.core.html#var-istr
(defn map-format [s m & ks]
(apply format s (map m ks)))
(let [m {:name "%username%"
:fun? "fun"}]
(map-format "Hello %s! Formatting is %s."
m :name :fun?))
:)Have a look at Selmer https://github.com/yogthos/Selmer I’ve used successfully for this kind of templating job, and not just for HTML.
core.incubator has a macro that works like python's fstrings: https://github.com/clojure/core.incubator/blob/be509fd967df8ce1ee43c43bca52360cf710252a/src/main/clojure/clojure/core/strint.clj#L49 However: • You still have to do the destructuring of the map (only once but still it's not exactly what you asked...) • clojure.core.incubator is no longer developed edit: I just realized that this is the same code as funcool/cuerdas so if you like the approach just pick that...
Another vote for Selmer -- we use it very heavily at work and the maintainer is super responsive.