This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-24
Channels
- # adventofcode (6)
- # announcements (4)
- # aws (21)
- # babashka (36)
- # beginners (58)
- # calva (3)
- # cider (2)
- # clj-kondo (21)
- # clojars (3)
- # clojure (35)
- # clojure-dev (4)
- # clojure-europe (5)
- # clojure-nl (8)
- # clojure-uk (8)
- # clojuredesign-podcast (7)
- # clojurescript (10)
- # core-async (3)
- # data-science (2)
- # datomic (2)
- # defnpodcast (11)
- # duct (4)
- # figwheel-main (1)
- # fulcro (34)
- # graalvm (12)
- # graphql (4)
- # joker (14)
- # kaocha (1)
- # midje (1)
- # off-topic (5)
- # pedestal (1)
- # re-frame (3)
- # reagent (4)
- # reitit (1)
- # shadow-cljs (4)
- # testing (12)
I have probably stupid question. What strategy would you recommend in case I need to call and use interfaces from here https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html and interop them from Clojure? Is there a sidekick library or something which would help me adapt Clojure code to be used smoothly with APIs which heavily use lambdas (interfaces above)?
currently I'm playing around with reify
above calls when needed, it seems to work but it is quite tedious.
There are a couple libs
Longer term, we’ve spent quite a bit of time looking at options for native interop for these, haven’t made any decisions yet
https://github.com/ajoberstar/ike.cljj is one lib, I haven’t used it myself
Took a look at ike
out of curiosity, was a bit disappointed by its intentional lack of focus on performance
I'd recommend to just craft a few "snippets" (practically all IDEs have a snippet system) that draft these reify
s
I think deftype
could be useful too, it allows me to better capture environment. Plus there is nice instantiation with ->MyType
that is done here for me. Let's see how that goes.
Does anyone remember this video where Rich explains a bit of persistent data structures in the video? I can’t remember the context, but I have a vague memory of him whiteboarding it?
I do not know if this would also be of interest, but one series of on-line articles that goes into depth on the implementation of Clojure's persistent vectors is here: https://hypirion.com/musings/understanding-persistent-vector-pt-1
It has several follow-up parts, each one linking to the next
@U0CMVHBL2 - thank you so much! This is useful!!!
This is it~ The Brian Beckman one!
In attempting to answer this StackOverflow question, I have underestimated my deep knowledge of Clojure, and found something that I'm not sure what is going on: https://stackoverflow.com/questions/59463747/how-does-clojure-bind-variable-parameters/59465336#59465336 It involves the definition of conj
inside of the clojure.core namespace, which has a recur call that is a bit subtle.
I am currently guessing that if you have a function defined with parameters like [x & xs]
, and then you do (recur foo bar)
that on the recursive call, x
is bound to the value of foo
, and xs
becomes bound to the value of bar
? If so, I don't think I have ever seen that outside of the clojure.core namespace before.
I thought that perhaps doing a clojure.walk/macroexpand-all
call on such a function might expand the [x & xs]
parameter vector into something with 2 normal parameters, and no &
, but that is not the case.
I think a recur is no different than any other binding, so x
is bound to foo
and xs
is a sequence that has one element, bar
.
(let [[x & xs] [:foo :bar]] xs)
=> (:bar)
Well, if you define a function (defn foo [x & xs] (println "x=" x " xs=" xs))
and call it as (foo 1 2)
, x
becomes 1 and xs
becomes (2)
.
That is not what happens in the recur
call of conj
In the recur call of conj
, the last parameter to recur
is a sequence, and it is not being wrapped inside of another sequence, but simply xs
becomes that sequence.
OK, I don't know why that is.
Unless I really need that morning coffee more than usual today 🙂
The doc examples point out this issue.
; Note that recur can be surprising when using variadic functions.
(defn foo [& args]
(let [[x & more] args]
(prn x)
(if more (recur more) nil)))
(defn bar [& args]
(let [[x & more] args]
(prn x)
(if more (bar more) nil)))
; The key thing to note here is that foo and bar are identical, except
; that foo uses recur and bar uses "normal" recursion. And yet...
user=> (foo :a :b :c)
:a
:b
:c
nil
user=> (bar :a :b :c)
:a
(:b :c)
nil
; The difference arises because recur does not gather variadic/rest args
; into a seq.
That's a note that someone added in ClojureDocs.
The recur expression must match the arity of the recursion point exactly. In particular, if the recursion point was the top of a variadic fn method, there is no gathering of rest args - a single seq (or null) should be passed. recur in other than a tail position is an error.
This is a really cool find. I couldn't find a sufficiently good Emoji to express that, sorry.
I'm simply amazed that I had not run across this in 10 years of serious hobby time on Clojure.
I have written a few, but I don't think ever with variadic args on the recursive function