Fork me on GitHub

I am trying to understand the use of comp in transducers. It would seem that normally comp applies functions right-to-left but left-to-right when used as a transducers. Is this correct? My brain hurts:exploding_head:.


It still composes functions right to left, but in the case of tansducers, that's the order they need to be composed in for the transducers to apply the transforms left to right


Hi didibus, thanks for the response. I am not sure I follow, though.


It gets pretty complicated quick 😝




Too much:joy:


Are you saying the functions are composed right to left, but the transducer flips it around?


Kind of yes


Ah. I see. is there a reason I would want to use (sequence xf coll) over (map xf coll) ?


Think of comp as doing the following: (a (b (c))) is (comp a b c)


Awesome. I see that comp comparison.


And comp always just does that, no exception to the rule


This is true even when a, b, and c are transducers


It just happens that the way transducers work, when you do: (a (b (c xf coll))) For each element in coll, a will process it first, then b, then c, then xf


ok. I will play with it a bit to understand it better.


Thanks @U0K064KQV! Did you see the question about (sequence xf coll) and (map xf coll) ?


But ya, it just means when you use comp with transducer, the logical order of the data transformation is now left to right, but the actual functions are still composed the way comp does.


Ya, there is a reason to use sequence xf


Hum... I'm trying to remember 😝 I think I wrote something explaining it let me find it


Ok, did not find it. Even I always forget because it's a bit confusing the difference between transducer, lazy sequence, and sequence xf


I'm a bit fuzzy, but the difference is mostly that (sequence xf) will not create as many intermediate objects, so it should be a little faster than lazy-seq (which is what default map would do)


Ya it's complicated. Basically (map mapping-fn coll) is using lazy seq, no transducer involved here


While (sequence xf) wraps a transducer inside a lazy-seq. This then means you can process the transducer lazily. Because normally transducers are eager


The difference only appears when you apply multiple transformations


Ok... Brain still hurts, but I think I am closer than I was when i started.


So if you do; (->> (map inc coll) (remove odd?))


Ya, nevermind. I won't be able to summarize this 😝


Oh I found it


Its complicated, but that explains it


I'm off to bed. Transducers take a long time to understand how they work. But to get the hang of using them is pretty quick. Good luck


Thanks. Cheers


What helped me to understand the inverse ordering with comp and transducers was to carefully study the source code


I'm trying to write an endpoint test for my api rest, I'm using component on it. But basically I thought I had to do a (component / start (system)) before (deftest) but doesn't work. Someone have a link to help?


You probably want to define a fixture that starts your component system, runs the test, then stops the system afterwards. See


hola amigos im new to java, clojure and ring. so i'm trying to extract an information but i haven't found any resources on google

{:file {:filename "fdf.txt", :content-type "text/plain", :tempfile #object[ 0x2fc9a402 "/tmp/ring-multipart-11354728889402997926.tmp"], :size 55}}
this is map of my request, i don't understand this part #object[ 0x2fc9a402 "/tmp/ring-multipart-11354728889402997926.tmp"]. my only understanding is that this is a java Object ? i want to extract the string "/tmp/ring-multipart-11354728889402997926.tmp" out of that, any idea how to do that?

Dan Boitnott11:06:06

What you have there is a instance and I'm guessing you want to extract it's absolute path as a string?

Dan Boitnott11:06:10

If so, then you'll want something like:

(.getPath (:tempfile my-map))

Dan Boitnott11:06:39

You'll probably also need to add an import for to your ns form.


oh wait let me try that

Jiří Rejman12:06:54

Hi, i need to import java.math class to use log function but i cannot require it inside leinengen project do i need to add it into project.clj?


Core Java classes are already available. You can just use it.

Alex Miller (Clojure team)14:06:01

If you did need it, you would use :import, not :require

Jiří Rejman17:06:37

ok, i can use function from java math like this (java.lang.Math/log 3) but how can i get the namespace name for use in import? This is propably the problem 🙂 and thanks for help!


You can do this:

(ns example.core
  (:import java.lang.Math))

(Math/log 3)

Jiří Rejman18:06:32

thanks! i searched books and stuff like this but clojuredocs is best 😉 just quick question i used io like this

(ns programming-ml.fourth
   [ :as io])

Jiří Rejman18:06:13

is it worse? and how should i know that the path is actualy ?


looks fine to me. I think problem of "discoverability" is the same as other languages, you can improve a little by using code completions frameworks in your editor of choice. But also, would encorage an overview of at least the high-level namespaces available at the core. Clojuredocs and searching in general helps a lot.

❤️ 4
Fredrik Meyer16:06:40

I'm trying to make a command line application with some animations in the terminal. I've found out how to replace one line (using carriage return), but is there a way to replace several lines? For example, what I'd like is something like this:

|––|        |--|
|--|    --> |xx|
|--|        |--|


i’ve used lanterna for a similar use case,


And if you’re familiar with ANSI escape codes and want something lightweight, is quite good too.

Daniel Stephens18:06:49

how does clojure.walk/walk avoid a stackoverflow exception, from the looks of it it doesn't do anything fancy with recur and it's basically just calling itself over and over isn't it?

Daniel Stephens18:06:08

or is it down to the fact that the function being called oscillates between post/prewalk and walk

Alex Miller (Clojure team)18:06:22

It doesn’t avoid it, it can overflow

Daniel Stephens19:06:13

Oh interesting, I realise now that in the specific case of a seq it doesn't do much recursion so testing on (range) was pointless, mb! Thanks for the information 🙂


I'm trying understand how I write test to endpoint to my API. I have this test but when I run lein test my server always stay in running. May someone can help? This is api is for me understanding how component works and how write testing using components.


I tried to use fixtures but doesn't work ;(

Daniel Stephens18:06:44

fixtures was going to be my suggestion, what did you have, something like:

(defn with-system
  (let [current-sys (component/start (start-test))]
    (component/stop current-sys)))

(use-fixtures :each with-system)


I'll try, thanks 😃


I try it, but the server still running 😕


I think the testing bit is missing your handler

(ns cracking.budget-test
  (:require [budget-calculator-api.components.routers :as routes]
            [clojure.test :refer [deftest testing is use-fixtures]]
            [ring.mock.request :as mock]))

;;; add your fixture defined above. looks fine to me.

(deftest testing-endpoint
  (testing "GET"
    (let [resp (routes/router (mock/request :get "/"))]
      (is (= (:status resp) 200)))))


Thank you! Im my run-jetty I create a warp-storage to inject in my route I don't know if this is good clojure practice. But I would like to know if I can easily replace the memory storage with a mock in my router?

(defn wrap-storage [f storage]
  (fn [req]
    (f (assoc req :storage storage))))

(defn create-server [port storage]
  (run-jetty (-> #'budget-calculator-api.components.routers/router
                 (wrap-storage storage)
                 (wrap-json-body {:keywords? true})
                 (wrap-json-response)) {:port port :storage storage}))


Are you creating your storage instance as part of your system start? If so, you could change your system map to point to the mock storage before starting the system in your fixture.


I did this, but if I use my system (start-test) it keeps running and doesn't call the test

(defn with-system
  (let [current-sys (component/start (start-test))]
    (component/stop current-sys)))

(use-fixtures :each with-system)

(deftest tt
  (testing "GET"
    (let [resp (routes/router (mock/request :get "/"))]
      (is (= (:status resp) 200)))))


So either start-test or component/start is not returning?


(start-test) return my system map, then I use (component/start (start-test)) tu run my system


I think I understand

🤯 4

Sorry, by “not returning” I mean you call it but it hangs, never returning a value.

✔️ 4

Yes.. (ps: sry my english)


Many Clojure devs use a little macro to debug things like this…

(defmacro dbg [x] `(let [x# ~x] (println '~x x#) x#))


Then you can write (dbg (component/start (dbg (start-test)))) to see what each function is returning.


(no problem, your English is fine!)


Thank you, I'll try debug to understand.


@UL618PRQ9 your run-jetty function is holding the process. You need to pass :join? false in the same map you configured the port. From the run-jetty documentation you can find:

:join?                - blocks the thread until server ends (defaults to true)

❤️ 4
🤯 4

I'll see it.. ty @UBSREKQ5Q

👍 4

Thanks! Worked well

parrot 6

Hey how can I prevent my program from closing, when I start it from the console?


I have a scheduled job in it that puts data on a channel, but it just closes instantly before processing any data. (while true) works but my pc doent like it. Is there a more lightweight way to do it?


yeah, while true is obviously not going to throttle in any useful way in-and-of-itself and will happily consume a CPU core. one way to go about this would be to have a second channel you take (`<!!`) on, and when you're done with what's happening in your go block, send a value (maybe an error), or just close that channel.


another way would be to use something like promesa, do very much the same thing, and deref the promise - and resolve that promise once you're done with your async work.


yet another way would be to just block synchronously - and that's the most simple option if you don't need multithreading. depending on what you're doing, async/multithreading can actually slow you down - or, at the very least, your async code will be dependent on your slowest execution path.


yet another way 😉 if you're using CLJS with Node - the Node event loop will block until all event handlers have been removed. so you could create some arbitrary event handler using once and trigger that event when done.


oh, and a crude way would be to add some Thread/sleep to your while true


i'm sure others will think of many other useful ways to do this as well!


rsrs at that point where you need more info to go further 🙂


I used a asynch channel with timeout but I swapped it out now with Thread/sleep inside the loop. That will work for now. Thanks.


I usually have a promise inside my (long-running) processes and just "wait" on it in -main (via a deref).

👍 4

Normally, that will just "wait forever" but if you start a REPL in the server, you can connect to it and deliver the promise to cause it to shutdown, or you could program some external action in your server that also delivered the promise to cause it to shutdown.