This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-06-18
Channels
- # announcements (29)
- # aws-lambda (2)
- # babashka (4)
- # babashka-sci-dev (7)
- # beginners (16)
- # calva (35)
- # cider (1)
- # cljdoc (3)
- # clojure (47)
- # clojure-europe (50)
- # clojure-nl (5)
- # clojure-norway (50)
- # clojure-sweden (4)
- # clojure-uk (6)
- # clr (1)
- # code-reviews (3)
- # conjure (2)
- # datalevin (2)
- # datomic (7)
- # graalvm (17)
- # honeysql (1)
- # java (5)
- # malli (7)
- # nbb (8)
- # re-frame (3)
- # squint (8)
- # tools-deps (2)
- # xtdb (19)
I have a problem I am stumped by. I have a macro that I can expand.
game.cljgl.core> (macroexpand '(define-gl-stuff))
(do
(clojure.core/defn raster-pos3fv ([a0] (GL33/glRasterPos3fv a0)))
(clojure.core/alter-meta!
#'raster-pos3fv
game.cljgl.core/set-arglists
'([float<>] [java.nio.FloatBuffer])))
And I can take that expansion and copy it into the repl, and it works as expected, without any error. But when I run the macro normally, I get an error:
game.cljgl.core> (define-gl-stuff)
Execution error (IllegalArgumentException) at game.cljgl.core$eval15668/ (REPL:13).
No matching ctor found for class clojure.reflect$typesym$fn__12067
Does anyone have any ideas of what is wrong?Stack trace from calling define-gl-stuff
normally:
Reflector.java: 305 clojure.lang.Reflector/invokeConstructor
LispReader.java: 1317 clojure.lang.LispReader$EvalReader/invoke
LispReader.java: 853 clojure.lang.LispReader$DispatchReader/invoke
LispReader.java: 285 clojure.lang.LispReader/read
LispReader.java: 216 clojure.lang.LispReader/read
LispReader.java: 205 clojure.lang.LispReader/read
RT.java: 1876 clojure.lang.RT/readString
RT.java: 1871 clojure.lang.RT/readString
REPL: 48 game.cljgl.core/eval15707
Unsafe.java: -2 jdk.internal.misc.Unsafe/ensureClassInitialized0
Unsafe.java: 1160 jdk.internal.misc.Unsafe/ensureClassInitialized
MethodHandleAccessorFactory.java: 300 jdk.internal.reflect.MethodHandleAccessorFactory/ensureClassInitialized
MethodHandleAccessorFactory.java: 103 jdk.internal.reflect.MethodHandleAccessorFactory/newConstructorAccessor
ReflectionFactory.java: 200 jdk.internal.reflect.ReflectionFactory/newConstructorAccessor
Constructor.java: 549 java.lang.reflect.Constructor/acquireConstructorAccessor
Constructor.java: 499 java.lang.reflect.Constructor/newInstanceWithCaller
Constructor.java: 486 java.lang.reflect.Constructor/newInstance
Compiler.java: 5008 clojure.lang.Compiler$ObjExpr/eval
Compiler.java: 7193 clojure.lang.Compiler/eval
Compiler.java: 7183 clojure.lang.Compiler/eval
Compiler.java: 7149 clojure.lang.Compiler/eval
core.clj: 3216 clojure.core/eval
core.clj: 3212 clojure.core/eval
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 667 clojure.core/apply
core.clj: 1990 clojure.core/with-bindings*
core.clj: 1990 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 nrepl.middleware.interruptible-eval/evaluate/fn
main.clj: 437 clojure.main/repl/read-eval-print/fn
main.clj: 437 clojure.main/repl/read-eval-print
main.clj: 458 clojure.main/repl/fn
main.clj: 458 clojure.main/repl
main.clj: 368 clojure.main/repl
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 152 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
AFn.java: 22 clojure.lang.AFn/run
session.clj: 218 nrepl.middleware.session/session-exec/main-loop/fn
session.clj: 217 nrepl.middleware.session/session-exec/main-loop
AFn.java: 22 clojure.lang.AFn/run
Thread.java: 1583 java.lang.Thread/run
Your macro expansion contains a closure object(a fn object) instead of code that when evaluated creates it
That error is the result of the compiler being unable to embedded the closure in the emitted bytecode
I don't quite understand. How come I can't see the closure in the output of macroexpand
?
I found out that if I remove the arglist (`([float<>] [java.nio.FloatBuffer])`) and replace it with an empty list then it works. So, a closure is hiding in there?
Likely, looks like you are getting them from the output of clojure.reflect, which is where the object that is not being serialized in the bytecode correctly is coming from
Return a map with a 30x status code and the Location header set to the URI you want to redirect to, e.g.:
{:status 301 :headers {"Location" "/go/somewhere-else"}}
I always thought every transduce could be rewritten with reducers, but it seems like the completing function isn't called, which makes sense in retrospect given the protocols involved. Kind of disappointed now, because this was my way of writing transducer code that still looked like lazy seq code... Is there any way to salvage this, and write a partition-all reducer?
https://github.com/clojure/clojure/blob/clojure-1.11.1/src/clj/clojure/core.clj#L7308 is a stateful transducer, at the end in the completion step the remaining state is obtained and returned (the last partition). For your reducer to work you do need this final step I guess.
yah, i guess i'm trying to find a way to get reducers to actually invoke that final step
you can call it yourself
I sort of got it to do it,
(defn completing-reducible [coll]
(reify
clojure.core.protocols/CollReduce
(coll-reduce [this f1]
(clojure.core.protocols/coll-reduce this f1 (f1)))
(coll-reduce [_ f1 init]
(f1
(clojure.core.protocols/coll-reduce coll f1 init)))))
(->> (r/reducer (completing-reducible (range 10) )
(partition-all 3))
(transduce identity conj []))
i want to keep the lazy-seq-like syntax, of reducers, and have reducers like partition-all.
(->> (range 10)
(r/map inc)
...
(into [])
that all works until you have transducer that has the final step, like partition-all.
there's no easy way to write
(->> (range 10)
(r/map inc)
(r.x/partition-all 2)
...
(into [])
I arrived where I wanted to it terms of lazy seq syntax, but i can't tell yet if this implementation is sound
(defn reducer*
([coll xf]
(reify
clojure.core.protocols/CollReduce
(coll-reduce [this f1]
(clojure.core.protocols/coll-reduce this f1 (f1)))
(coll-reduce [_ f1 init]
(let [rf (xf f1)]
(rf
(clojure.core.protocols/coll-reduce coll rf init)))))))
(defn partition-all* [n coll]
(reducer* coll (partition-all n)))
(->> (range 10 )
(partition-all* 3)
(transduce identity conj [])) ; ;=> [[0 1 2] [3 4 5] [6 7 8] [9]]
EDIT: yup, not accurate, completing function may get invoked multiple times. I guess i'll just write them idempotently, this as good as it gets I think.my personal tip is to just embrace the natural shape of transducer composition
yah.. i just can't help but think there's a nice solution here. when you're in the REPL its not uncommon to eval things to see what they look like before its reduced.
How would you do it with the (->> ...)
syntax? Wouldn't you have to comment out the whole last form?
@U2FRKM4TW are you asking about this ?
so you still need a reduce step, yah that's true, unless you materialize the reducible on eval
i think if clojure had reducers from v1.0 / the beginning, they would have done an eduction on eval or something.
Assuming I understand your problem correctly, it seems that if you use the transducer syntax and the last reducing step is not something that lets you view the whole sequence, you can just temporarily change that last step. Which seems roughly the same in terms of the amount of work you need to do with reducers. In other words, if you have something like
(transduce (comp ...)
+ 0 coll)
and you want to view all the steps, you can just change it to
(transduce (comp ...)
conj [] #_#_+ 0 coll)
Yah that's fair, i guess I exaggerated it in my mind the differences in convenience
anyway, most of the core
seq transformations can in fact be re-implemented as transducers, but some would require to basically keep the entire reduction state in your transducer (e.g. sort
and take-last
), which is why they weren't implemented, I suspect.
(slack what?)
For instance, here's how a sort
transducer could look like (now with 100% less garbled code)
(defn sorting
([] (sorting compare))
([cmp]
(fn [rf]
(let [xs (java.util.ArrayList.)]
(fn
([] (.clear xs) (rf))
([res]
(rf (reduce rf res (doto xs (.sort cmp)))))
([res in]
(.add xs in) res))))))
here's the print-method with the reducible, at least i got to the end of my exercise, albeit i probably won't do this in my codebase
anyway, isn't eduction
basically what you're looking for?
me? eduction is great , i would have liked to use that in print-method, but i can't get a coll from CollReduce protocol.
I just have to say, your choices and combination of the font and the coloring scheme are the most unique I've ever seen a programmer use. That lower-case N
is unholy. :D
@U2FRKM4TW haha thanks i guess, its all custom, i probably have the only emacs theme with two foreground colors, both black and white. Font is also my own creation.
https://github.com/jasonjckn/tensora-mono-font i just paid a font designer to tweak it, a couple hours ago (in progress), since im not actually a graphic designer, but its my favorite programmer font