Fork me on GitHub

i need to use java.rmi. java examples generally go like this

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    <T> T executeTask(Task<T> t) throws RemoteException;
what is the way to extend a java interface in Clojure? can i do it with defprotocol?


Are you trying to extend an interface or implement an interface? I'm not sure of the exact syntax, but, implementing an interface is usually done with reify, (see

(reify compute.Compute
    (executeTask [this t]
      (println "doing stuff")))


all the examples i've seen for rmi go by first extending it into another interface plus adding that exception thrown, and only then implementing it. it seems like with gen-interface , but if i'm not adding that throw exception it seems not much useful do to that. So I guess I'll try implementing it directly with reify as you suggest. Thank you!


yea, extending the interface isn't really necessary in Clojure and I'm not sure it would provide any benefit since it's not being checked by Java's static type checker.


I'm not actually sure the checked exceptions even show up in the bytecode


I would generally start with reify , and fallback to defrecord or proxy depending on the use case. That should cover most interop use cases, but it's also not that hard to include a small amount of java if that allows you to avoid awkward interop cases introduced from weird javaisms.

❤️ 1

I have a function call which is calling the function one-by-one... how can we avoid sending arguments to each functions? I do not want those arguments in function 3 4 5 6, I need extra arguments only in function 1 and function 7

Martin Půda06:06:16

Can you post an example code?


You can use dynamic vars - it's a global variable that gets rebound in the scope of a thread. It's generally not a good thing to do (it complects code where it's used to where it's bound), but it has its uses. You can't use it if it has any sort of async (the var is still bound to the thread)


(Specifically the ^:dynamic tag)


Note that this is generally not a good thing to use - if you know the function at the bottom needs it, you should pass it down through the intermediate functions


so you mean passing parameter to each function


Doing it with dynamic vars means you have slightly less boilerplate on the way down, but can introduce a lot of complexity


you can just modify or wrap those inner function to accept the same number of argument (or even any number of argument (fn [a b c & _] (f a b c)) )


Since it's not immediately obvious you're needing the var to be bound



(defn transformation [arg1 arg2 arg3 arg5 arg6 ]

(defn function-5 [ arg1 arg2 arg3]
  ;; Need arg5 args6
  (transformation arg1 arg2 arg3 arg5 arg6 )


(defn function-4 [ arg1 arg2 arg3]
  (function-5  arg1 arg2 arg3)

(defn function-3 [ arg1 arg2 arg3]
  (function-4  arg1 arg2 arg3)

(defn function-2 [ arg1 arg2 arg3]
  (function-3  arg1 arg2 arg3)

(defn function-1 [ arg1 arg2 arg3]
   (function-2  arg1 arg2 arg3)


(defn f1 [{:keys [a b]}])
(defn f2 [{:keys [a b c]}])


if you struture you functions like that you can pass the whole hash map


Ah yes, option maps would work well


@U02F0C62TC1 thanks for your response, I have hash-map or atom as my initial plan which I had that in my mind. But wanted to find better solution if any 🙂 if we do not have any other option I will go with hash-map


can' t we do this using partial function ?


You can, but it means every level you're doing multi-arity boilerplate


Options maps are excellent because you can pass down all your arities in a single item, and in your destructuring you can refer to the keys you care about at that level


i dont understand the intention in your code sample so it's a bit hard


@U24QP2D4J, If I use it as dynamic variable, when the value of that will be garbage collected ?


if you wrap the call in binding, it should be gc-ed at the end


what if I do it using atom, when it will be cleared? only calling reset! function ?


when you modify the value the old one is cleared


Then you introduce state that's not thread-local


And things go off the rails


oh I think I get the sample, yes the usual clojure way is to pass those additional args to each functions, could be an option map. In some rare cases, or in tests it's sometimes easier to use dynamic vars. And it's okay to introduce a global atom state sometimes, but beware of concurrency


I mean, in general don't introduce a global state atom unless it's actually global state


Introducing a global state atom to run in a scoped state is asking for trouble


What about

(defn f1 [a1 a2 a3] [a1 a2 a3])
(defn f2 [a1 _  a3] [a1 a3])
(defn f3 [_  _  a3] a3)
(defn f4 [a1 & _] a1)

((juxt f1 f2 f3 f4) 1 2 3)
> ([1 2 3] [1 3] 3 1)


these are function inside a function


Is there any clever way to diff two values between different executions for debugging? I'm resorting to a lot of copy/paste manual diffing... wonder if there's a better way.


there are few projects this library as an example - in the README you can find links to others


I wasn't aware of that one, but I do use The issue isn't so much in diffing two structures, it's moreso about storing the value between two different execution runs. My workflow is something like: start with working copy -> make a seemingly benign change -> notice bug -> compare values between working copy and bug which resulted from "benign" change. The copy/paste required for comparison is just very tedious at times. Is there a better way?


you could write a test and run it on save


@U02F0C62TC1 if I'm debugging I don't necessarily know what to test.


so ideally you'd want a tool that instrument the return values of functions and store multiple versions ? I'm not aware of such a tool but i might exist. spyscope or postmortem could help a bit maybe


Yes, a tap-diff tool or something like that. Or, alternatively, a better approach altogether. Spyscope looks interesting. Will play around with that one.


I feel like it already exists and I don't know it 😅


Perhaps the new flowstorm debugger could also be a good fit for such a feature


how do i (apply and '(true false false)) ? right now i am getting Can't take value of a macro: #'clojure.core/and but i don't understand why that's happening? reason is i have variable list of conditions and i need to use and on it don't know how to do it properly

Ferdinand Beyer15:06:03

Just to answer your original question as well 🙂 This happens because and is not an ordinary function, but a macro, that will expand to an if! This is needed so that it can short-circuit, e.g. (and false (println "Hello")) will not print. This is not possible with ordinary functions. Macros cannot be passed around like other functions, e.g. you cannot pass it to apply. That’s what the error message Can't take value of a macro means.

👍 1

Thanks! Just read this (little late ) 🙂

👍 1
Alex Miller (Clojure team)14:06:44

(every? true? '(true false false))


i may get non boolean in that list

Alex Miller (Clojure team)14:06:57

or (every? identity '(true false false))

👍 1
👀 1
🙌 1
😮 1

little bit ashamed it was so obvious. Thanks a lot !


some instead of every? no ?

👍 1

but every? is and


That's a very good point. I actually made a mistake because i needed and anyway and my test cases passed. I will correct original thread


but now my reply looks stupid 😅


i disagree, you actually corrected my question and provided more context to other functions


Is there a better approach to this pattern?

;; filter seq of maps and then select a subset of the keys
    (filter #(odd? (:x %)))
    (map #(select-keys % [:z :y])))
  (for [i (range 5)] {:x i
                      :y (* i 10)
                      :z (* i 100)})
; => [{:z 100, :y 10} {:z 300, :y 30}]


(keep #(when (odd? (:x %)) (select-keys % [:z :y]))
  (for [i (range 5)] {:x i
                      :y (* i 10)
                      :z (* i 100)}))


but even with the for only if it's part of your question:

(for [i (range 5)
           :when (odd? i)] {:y (* i 10)
                      :z (* i 100)})


@U02F0C62TC1 The first one is what I was after. Thanks!


and with transducer:

    (filter #(odd? (:x %)))
    (map #(select-keys % [:z :y])))
  (for [i (range 5)] {:x i
                      :y (* i 10)
                      :z (* i 100)}))

🙏 1

Ah, "application of transducer to an input collection" :pencil:

Ferdinand Beyer16:06:42

“better approach” is super subjective. While I find transducers cool, they are often hard to read and understand, especially when mixed with other constructs, like in your example.

Ferdinand Beyer16:06:01

E.g. you could make it all transducers:

  (comp (map #(hash-map :x % :y (* % 10) :z (* % 100)))
        (filter #(odd? (:x %)))
        (map #(select-keys % [:z :y])))
  (range 5))

Ferdinand Beyer16:06:31

Or none:

(->> (range 5)
     (map #(hash-map :x % :y (* % 10) :z (* % 100)))
     (filter #(odd? (:x %)))
     (map #(select-keys % [:z :y])))

Ferdinand Beyer16:06:23

I think transducers are great when you can reuse functionality in places other than collections, like in core.async channels. But in most cases like these here, I would avoid them, as they are harder to understand than using (lazy) sequences. You need to jump between forms to understand what happens. With ->> it reads super nicely: It’s just a pipeline of transformations.


Yes, it is somewhat challenging to understand when to use which option. In my case I have an ETL pipeline where there are a many records being transformed and performance at scale is a factor. My understanding is that the transducer option will generally perform better in such circumstances.

Ferdinand Beyer16:06:33

Like always when it comes to performance: Don’t let your intuition fool you. Write clean code, then measure.

❤️ 1
Ferdinand Beyer16:06:56

Performance at scale: Sounds like you will distribute over multiple computers, then this kind of micro-optimisation will probably not make a difference. Plus fast does not help if the code has bugs because it was hard to understand 🙂


@U031CHTGX1T > You need to jump between forms to understand what happens. Can you elaborate on this point? You have to "jump between" different expressions in a threaded sequence transformation as well, no? Are you referring to the combination of stateful transducers and ones that process individual elements?

Ferdinand Beyer16:06:23

I meant when you read the code and try to understand it.

Ferdinand Beyer16:06:19

To understand this:

    (filter #(odd? (:x %)))
    (map #(select-keys % [:z :y])))
  (for [i (range 5)] {:x i
                      :y (* i 10)
                      :z (* i 100)})
You have to jump into the for to see that it works on range, then jump to the body of for, then up to the transducer, then you have to remember in which order transducers are run when combined with comp. There’s a lot to grasp. Compare this to:
(->> (range 5)
     (map #(hash-map :x % :y (* % 10) :z (* % 100)))
     (filter #(odd? (:x %)))
     (map #(select-keys % [:z :y])))
This is super straight-forward


Sometimes the combination of lazy and eager functions trips me up. With a transducer you can be sure that the whole thing is consumed in a non-lazy way, yes?


oh with sequence it was, lazy, for the non lazy transducer way: (into [] (keep ...) coll)

👍 1
gratitude-thank-you 1

Or... I guess when you produce a sequence transformation with ->> the next step is deciding how it will be consumed, so the laziness isn't a factor in what you wrote.

Ferdinand Beyer17:06:09

You can always add a doall to the end to ensure everything is eagerly evaluated, or use mapv or into 🤷

gratitude-thank-you 1
Ferdinand Beyer17:06:01

But remember that premature optimisation is the root of all evil.


heh, I don't think Donald Knuth meant that the way people use that these days 😛 But yes, your point stands. Although with those "tricks" I have run into memory consumption issues here and there.

Quentin Le Guennec19:06:28

hello, is that function in clojure.core? (f "account" :name) => :account/name


Almost: (keyword "account" "name") => :account/name so you'd want (keyword "account" (name k)) for an arbitrary keyword k