Fork me on GitHub

I have probably stupid question. What strategy would you recommend in case I need to call and use interfaces from here 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

alexmiller12:12:20 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 reifys

👍 1

Thanks guys, I'll explore ike little bit for inspiration.


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.


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: 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)

user=> (bar :a :b :c)
(:b :c)

; The difference arises because recur does not gather variadic/rest args
; into a seq.

👍 3

That's a note that someone added in ClojureDocs.


Official doc also talks about it


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.

💯 2

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 don't write a lot of recursive code I guess.


I have written a few, but I don't think ever with variadic args on the recursive function