This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-06-22
Channels
- # announcements (7)
- # babashka (1)
- # beginners (87)
- # boot (1)
- # cider (1)
- # clj-kondo (33)
- # cljfx (1)
- # cljs-dev (8)
- # clojars (3)
- # clojure (105)
- # clojure-austin (3)
- # clojure-europe (74)
- # clojure-finland (1)
- # clojure-korea (4)
- # clojure-nl (1)
- # clojure-uk (6)
- # clojurescript (10)
- # conjure (9)
- # cursive (29)
- # datalog (6)
- # datomic (13)
- # emacs (3)
- # events (4)
- # figwheel-main (1)
- # gratitude (1)
- # humbleui (6)
- # introduce-yourself (7)
- # jackdaw (1)
- # jobs (1)
- # lsp (29)
- # malli (3)
- # nbb (2)
- # podcasts (1)
- # portal (5)
- # re-frame (4)
- # reitit (28)
- # remote-jobs (5)
- # shadow-cljs (38)
- # tools-deps (46)
- # vim (6)
- # xtdb (24)
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 https://clojure.org/reference/java_interop#_implementing_interfaces_and_extending_classes)
(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 https://stackoverflow.com/questions/5479694/extending-not-implementing-java-interfaces-in-clojure 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.
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
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)
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
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))
)
(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)
)
@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
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
@U24QP2D4J, If I use it as dynamic variable, when the value of that will be garbage collected ?
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
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)
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 - https://github.com/friemen/diffit in the README you can find links to others
I wasn't aware of that one, but I do use https://github.com/lambdaisland/deep-diff2. 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?
@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.
https://github.com/vvvvalvalval/scope-capture is also pretty close, but not quite.
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
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.
(every? true? '(true false false))
:thumbsup:
can work too
good point!
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
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
(transduce
(comp
(filter #(odd? (:x %)))
(map #(select-keys % [:z :y])))
conj
(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:
(sequence
(comp
(filter #(odd? (:x %)))
(map #(select-keys % [:z :y])))
(for [i (range 5)] {:x i
:y (* i 10)
:z (* i 100)}))
“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.
E.g. you could make it all transducers:
(sequence
(comp (map #(hash-map :x % :y (* % 10) :z (* % 100)))
(filter #(odd? (:x %)))
(map #(select-keys % [:z :y])))
(range 5))
Or none:
(->> (range 5)
(map #(hash-map :x % :y (* % 10) :z (* % 100)))
(filter #(odd? (:x %)))
(map #(select-keys % [:z :y])))
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.
Like always when it comes to performance: Don’t let your intuition fool you. Write clean code, then measure.
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?
I meant when you read the code and try to understand it.
To understand this:
(transduce
(comp
(filter #(odd? (:x %)))
(map #(select-keys % [:z :y])))
conj
(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-forwardSometimes 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)

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.
You can always add a doall
to the end to ensure everything is eagerly evaluated, or use mapv
or into
🤷

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.
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
Ok, thank you.