Fork me on GitHub
#beginners
<
2021-12-03
>
Michaël Salihi02:12:29

Hi! I would to know if it exists a more idiomatic way to compare two nested values in a same map than this:

{:id 1 :name "item" :change-sets {:planned-end {:current "2022-01-12T12:21:32Z" :previous "2022-01-04T12:01:32Z"}}}

(< (get-in change-sets [:planned-end :current]) (get-in change-sets [:planned-end :previous]))

Cora (she/her)02:12:27

you could use a let for :planned-end and then (:prevous planned-end) and do the same for current

👍 1
Michaël Salihi02:12:50

Thank for your suggestion. So like that, right?

(let [planned-end (get-in items [:changes-sets :planned-end])]
  (< (:current planned-end) (:previous planned-end)))

Michaël Salihi02:12:14

or even better using deconstructing

(let [{:keys [previous current]} (get-in items [:changes-sets :planned-end])]
  (< current previous))

Drew Verlee03:12:52

(let [{{c :current p :previous} :change-sets} {:id 1 :name "item" :change-sets {:planned-end {:current "2022-01-12T12:21:32Z" :previous "2022-01-04T12:01:32Z"}}}]
    (< c p));; => false

Drew Verlee03:12:22

i missed a key

Drew Verlee03:12:55

(let [{{{c :current p :previous} :planned-end} :change-sets} {:id 1 :name "item" :change-sets {:planned-end {:current "2022-01-12T12:21:32Z" :previous "2022-01-04T12:01:32Z"}}}]
    [c p]);; => ["2022-01-12T12:21:32Z" "2022-01-04T12:01:32Z"];

👍 1
Cora (she/her)04:12:50

I'd probably do this:

Cora (she/her)04:12:53

(let [{:keys [current previous]}
      (get-in items [:changes-sets :planned-end])]
  (< current previous ))

Romit Gandhi07:12:24

Hello, I'm new to Clojure. I want to know what is the best way to implement the Cron Job in Clojure. Can anyone help me regarding that? Thank you.

walterl12:12:37

https://github.com/troy-west/cronut wraps the Quartz Java library. It's working well for us.

Cora (she/her)07:12:25

chime is a common choice, I think?

Cora (she/her)07:12:04

if you google "clojure cron" you'll find a lot of good stuff

Romit Gandhi07:12:56

Actually found many things, I was confused and not able to figure out which is simple and best way to do it

dharrigan08:12:55

I've also had good success with

Benjamin10:12:48

should I use namespaced keywords in argument maps?

(defn fo [#:my{:keys [:stuff]}])

bortexz10:12:14

You can do {::my/keys [stuff]} to destructure namespaced kw

roelof11:12:38

I try to install clojure tools but ran into a problem According to this page : https://clojure.org/guides/deps_and_cli I have to do these steps :

Soon you will want to build and save your own code that makes use of these libraries. Create a new directory and copy this deps.edn into it:

$ mkdir hello-world
$ cp deps.edn hello-world
$ cd hello-world
$ mkdir src

roelof11:12:56

but where can I then find the deps.edn I have to copy ?

Antonio Bibiano11:12:54

I think it's the same from the previous paragraph

1
roelof12:12:38

so there is no way to scaffold a clojure - tools project so I do not have to make the aliases as a beginner ?

walterl12:12:16

Maybe you're looking for something like https://github.com/seancorfield/deps-new?

dharrigan13:12:01

Yes, I use deps-new (with my own template)

dharrigan13:12:09

tis rather spiffingly good

roelof14:12:31

how do I get this working

clj -X roelof.aoc2021/-main "Roelof"
Key is missing value: Roelof

roelof14:12:49

I need somehow to use the :name key

walterl14:12:35

Args to fn executed with clj -X are passed as a map, so clj -X roelof.aoc2021/-main :name "Roelof"

roelof15:12:12

you sure with this code :

(defn greet
  "Callable entry point to the application."
  [data]
  (println (str "Hello, " (or (:name data) "World") "!")))
I expect to see Hello , Roelof but I get Hello, {:name Roelof}!

dharrigan16:12:17

Seems to be okay for me

dharrigan16:12:33

(defn greet
  [data]
  (println (str (or (:name data) "World") "!")))

dharrigan16:12:48

❯ clj -X online.harrigan.main/greet :name "David"
David!

dharrigan16:12:23

❯ clj -X online.harrigan.main/greet
World!

walterl17:12:02

@U0EGWJE3E I notice that you're invoking -main, but showed the code for greet. Are you changing data before passing it to greet perhaps?

roelof17:12:38

The whole namespace looks like this :

(ns roelof.aoc2021
  (:gen-class))

(defn greet
  "Callable entry point to the application."
  [data]
  (println (str "Hello, " (or (:name data) "World") "!")))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (greet {:name (first args)}))

walterl19:12:15

Command-line args are collected into a single map and passed to the invoked function as the only argument. Accepting that map as varargs (`& args`) wraps it in a list. That means (first args) is the args map, and {:name (first args)} becomes {:name {:name "Roelof"}.

walterl20:12:15

(ns roelof.aoc2021
  (:gen-class))

(defn greet
  "Callable entry point to the application."
  [data]
  (println (str "Hello, " (or (:name data) "World") "!")))

(defn -main
  "I don't do a whole lot ... yet."
  [args]
  (greet args))
clj -X roelof.aoc2021/-main :name Roelof
Hello, Roelof!

roelof20:12:44

very wierd that I see this again

clj -X roelof.aoc2021/-main :name "Roelof"
Hello, {:name Roelof}!

Benjamin13:12:32

Is there a way to cancel a future and get a stack trace of what it was currently doing? I know with cider nrepl I can say interrupt that does I think exactly this but now I have some other thread I'll try evaling my work with nrepl and interrupting

delaguardo14:12:29

future returns an object implementing java.util.concurrent.Future so you can use its cancel method

(.cancel (future (Thread/sleep 3000) (println "done") 100) true)

👍 1
Benjamin14:12:41

Yea, I was looking for a stacktrace of what the thread is doing at that moment though if that makes sense. Ah it threw interrupted exception 👀

delaguardo14:12:51

it is possible

(.cancel
 (future
   (try
     (Thread/sleep 3000)
     (catch InterruptedException e
       (prn e))))
 true)

partywombat 1
matthew15:12:49

Any nice patterns to log each stage of a pipeline? I like as-> but my timbre spy log now shows a reference rather than the output.

(defn run
  "Run the script, accepts a :url"
  [args]
  (as-> (args->url args) n
    (spy :info (url->imgs n))
    (spy :info (imgs->srcs n)) ;; Logs – [email protected]
    (spy :info (srcs->uris n)) ;; Logs – LazySeq etc.
    (spy :info (strings->urls n)) ;; Logs – LazySeqq etc.
    (spy :info (uris->out n))))

matthew15:12:13

Perhaps there is a helpful fix in timbre itself: https://github.com/ptaoussanis/timbre/pull/200 But I’m interested in good Clojure composition for this type of stuff. Thanks

Ben Sless15:12:36

(-> x (doto tap>) f ,,, )

3
matthew15:12:35

Simple, suits my needs. does the job. Thanks

🙏 1
pez15:12:48

If I have a LocalDateTime, how can I make a value from it that satisfies inst? Google fails me.

delaguardo15:12:19

(.toInstant (.atZone date (ZoneId/ofOffset "UTC" (ZoneOffset/ofHours 0)))) I have that line in one of my projects )

Alex Miller (Clojure team)15:12:20

Yeah, you'll need either an Offset or Zoned date time before it can be converted to an instant

delaguardo15:12:22

(inst?
 (let [date (java.time.LocalDateTime/now)]
   (.toInstant (.atZone date (java.time.ZoneId/ofOffset "UTC" (java.time.ZoneOffset/ofHours 0)))))) ;; => true

pez17:12:59

Ah, thanks!

pez16:12:42

Found myself this fantastic SO answer on the subject: https://stackoverflow.com/a/32443004/44639

roelof16:12:00

why is my recursion method takes very long to work

(ns collatz-conjecture)

(defn new-collatz-number[num]
 (if (even? num)
  (/ num 2)
   (+(* num 3) 1)))

(defn recursion-helper[num steps]
  (if (== num 1)
    steps
    (recur (new-collatz-number num) (+ steps 1))))

(defn collatz [num]
  (recursion-helper num 0))

emccue16:12:46

so first, == should be =. I don’t think that does anything or the right thing

emccue16:12:27

so perhaps if that condition always returns false then you always hit the recur

roelof16:12:52

Thanks, the problem was that some tests had zero or less , So 1 never gets hits

emccue16:12:51

== is actually okay - i just never saw that in code before

emccue16:12:00

its subtly different than = for numbers

tschady17:12:27

looks like exercism. might want to try getting this into just 1 function and using inc

roelof17:12:38

It is a challenge from exercism

tschady18:12:47

if it helps, i did all the problems a few years ago: https://github.com/tschady/exercism-clojure

dpsutton17:12:03

@U14K4HW3T map returns a lazy sequence. Nothing is forcing the realization of that lazy sequence so you are not seeing the results printed to the repl from the println function

☝️ 1
1
mateus.henrique.brum17:12:41

Thanks @U11BV7MTK makes total sense, dorun and doall made the job here… simple_smile

dpsutton17:12:53

there’s also run! that’s pretty tailored to this usecase. Lazy sequences should not be used for side effects like this, because you might or might not actually do any work

dpsutton17:12:24

the REPL probably made you think this would print everytime because of the “P” for print.

dharrigan17:12:02

I think also, you could try to use mapv as that is eager, would that be right?

mateus.henrique.brum17:12:50

run! worked perfectly for my case :

(defn -main []
  (run! pretty-out (play input-from-keyboard)))
A small game, just need to understand the differences now run! dorun doall Thank guys

Kevin Retzke17:12:37

doall causes the entire sequence to reside in memory so it can return it, but the difference between dorun and run! is much fuzzier for me. The former uses next/recur while the latter uses reduce (with a nil accumulator), but what’s the practical difference?

dharrigan18:12:51

This may help

thanks3 1
mateus.henrique.brum18:12:41

☝️cool, I will enjoy it …

sebastian17:12:01

if I'm inside a threading macro, what is a good way to do multiple things with the same value? So put something like a let block in the middle that is fed by the threading macro. Is that understandable what I mean?

(->> [1 2 3 3]
     (reduce +) ;; = 9
     (#(* % %)) ;; -> put 81 in x
     Math/sqrt ;; -> put 3 in y
     (* x y))  ;; should result in (* 81 3)

emccue18:12:32

(as-> [1 2 3 3] _
  (reduce + _)
  (* _ _)
  (Math/sqrt _)
  (* x y _))
      

ghadi17:12:38

don't try to do that much in a threading macro

sebastian18:12:02

and usually I agree. while doing advent of code, I try to do it all in one data pipeline (with a few little helper fns)

ghadi17:12:57

and especially don't mix ->> and #()

sebastian17:12:48

or do you mean that I should name my fns properly and then use them in ->>

ghadi18:12:27

It's an accident that it works and it is impossible to read

sebastian18:12:32

fair enough 🙂

tschady17:12:32

(->> [1 2 3 3]
     (reduce +)
     ((juxt #(* % %) #(Math/sqrt %)))
     (reduce *)
     int)

tschady17:12:53

but yes, a let is clearer for most things

ghadi17:12:53

Just because you can, doesn't mean you should™

tschady17:12:24

in this case, do just 1: (int (Math/pow (reduce + [1 2 3 3]) 2.5))

sebastian17:12:53

aha! the ominous juxt 🙂 I also found that I can do this with the as-> macro

...
(as-> x
  (let [foo (* x x)]...