Fork me on GitHub
#clojure
<
2021-10-31
>
wombawomba14:10:54

Is there a way to wrap a Java object and override a single (public) method, without reimplementing every single method in the object's class?

wombawomba14:10:00

cool, thanks

didibus17:10:07

A slightly more tedious way is that you can re-implement all methods in your proxy and just use proxy-super to call the parent implementation

Dynom21:10:35

I'm not sure if this belongs in #beginners or here, but I'm guessing here. What is the clojure way of handling multiple "jobs"? For example, I have an application which has a few jobs/threads which do not rely on each other, but might need to send some data to other jobs/threads.

emccue23:10:26

If its the most basic case - you want to fire off a job and let it run to completion and there aren’t that many of them - just submit the job onto a thread pool

emccue23:10:36

(.submit (ForkJoinPool/commonPool)
         (reify Runnable 
           (run [_]
             (println "Doing thing"))))

emccue23:10:58

and if you need to communicate data to annother process, have those processes share a reference to a queue

emccue23:10:33

ArrayBlockingQueue is good. chan from core.async can be a bit more powerful and (i think) lightweight. There are other options too

emccue23:10:32

(import java.util.concurrent.ForkJoinPool)
=> java.util.concurrent.ForkJoinPool
(require '[clojure.core.async :as async])
=> nil
(let [shared-chan (async/chan)]
  (.submit (ForkJoinPool/commonPool)
           (reify Runnable 
             (run [_] 
               (println "Worker 1: Waiting for one second")
               (Thread/sleep 1000)
               (println "Worker 1: Giving data to the other worker")
               (async/>!! shared-chan {:data :stuff})
               (Thread/sleep 2000)
               (println "Worker 1: Doing more work"))))
  (.submit (ForkJoinPool/commonPool)
           (reify Runnable
             (run [_]
               (println "Worker 2: Waiting for data")
               (println "Worker 2: Got Data: " (async/<!! shared-chan))))))

emccue23:10:49

small example

emccue02:11:43

(require '[promesa.core :as promesa])

(let [shared-promise (promesa/deferred)]
  (.submit (ForkJoinPool/commonPool)
           (reify Runnable
             (run [_]
               (println "Worker 1: Waiting for one second")
               (Thread/sleep 1000)
               (println "Worker 1: Giving data to the other worker")
               (promesa/resolve! shared-promise {:data :stuff})
               (Thread/sleep 2000)
               (println "Worker 1: Doing more work"))))
  (.submit (ForkJoinPool/commonPool)
           (reify Runnable
             (run [_]
               (println "Worker 2: Waiting for data")
               (println "Worker 2: Got Data: " @shared-promise)))))

emccue02:11:55

same example but with promesa promises

Ben Sless05:11:25

For communication between processes, you can also use a sort of internal pub/sub mechanism. This will prevent processes needing to know about and directly reference others

borkdude22:10:03

@nielsdewaal sounds like that might be a good use case for core.async

emccue23:10:48

I’d disagree - or at the very least i’d specify which parts of core.async - go blocks aren’t really useful for something like this, channels would be

borkdude07:11:22

Yes, channels I mean. You don’t have to use go but just threads and channels between them sounded like what was described

Dynom09:11:58

Right now I am using channels with go blocks. I use pub/sub for control and channels for message passing. Problem for me is that it doesn't really feel very nice to work with. However, maybe that's just due to pub/sub.