Fork me on GitHub
#clojure
<
2021-06-25
>
caleb.macdonaldblack11:06:40

I’ve always used parinfer. What’s a good alternative I should learn?

ghadi12:06:02

no mention of paredit? that's the gold standard

☝️ 4
Jakub Šťastný12:06:19

Yeah depends what editor you use. In my case it's Emacs/EVIL, so you go with Lispy/Lispyville. Lispyville integrates nicely with EVIL.

Adam Helins12:06:15

I saw this solution for clearing the terminal. It works on Linux (gnome terminal) but I am curious if it is portable:

(print "\033[H\033[2J")
  (flush)

borkdude12:06:25

It works on macOS as well, I will try in windows cmd.exe...

borkdude12:06:36

doesn't work in cmd.exe with the native console, but it does work if you use the new Terminal app on Windows

Apple12:06:06

search "vt100 clear screen"

👍 2
borkdude12:06:04

so it seems to be fairly portable, assuming everyone will use the new terminal on Windows

👍 2
Adam Helins12:06:47

Great, otherwise the alternative is to detect the OS, then run the appropriate shell command... This quasi oneliner is preferable

borkdude12:06:23

@adam678 On windows I think you can detect the new terminal usage using an environment variable

borkdude12:06:33

user=> (System/getenv "WT_SESSION")
"c1d08d7a-69ae-4dc2-93e6-8689e6789dd1"

💯 2
manutter5112:06:52

I take it if you're NOT in the new terminal, this will return an empty string instead of a UUID, correct?

borkdude12:06:07

it will return nil probably

Endre Bakken Stovner14:06:06

When developing I'd find it useful to have a get/`get-in` that errors in case the key isn't found. Is something like that built in?

Apple14:06:16

get m k <pivot>) check pivot

Apple14:06:42

or find first but it does not work for get-in

Endre Bakken Stovner14:06:11

I guess I could just (get m k (Exception.)).

Endre Bakken Stovner14:06:53

Nope, did not work.

potetm14:06:11

That will return a new exception

potetm14:06:25

since it’s dev-time only you could do something like:

(alter-var-root #'clojure.core/get-in
                  (fn [v]
                    (fn [m ks]
                      (let [v (v m ks ::not-found)]
                        (if (= v ::not-found)
                          (throw (ex-info "" {}))
                          v)))))

Endre Bakken Stovner14:06:16

Cool! I was hoping for something like that. I guess I could add it to my dev/env.clj :thumbsup:

souenzzo15:06:03

It should break libraries that use get-in

isak15:06:16

What I've seen some people do is to just define sget and sget-in, which do the above. The "s" meaing "safe".

👍 2
raspasov15:06:56

Might not be the most elegant solution, but you can use a library like timbre, for example:

(let [ret (get-in {:a {:b 42}} [:a :z] :not-found)]
 (timbre/spy ret)
 ret)
2021-06-25T15:38:24.354Z MBP.local DEBUG [ss.experimental.scratch:2] - ret => :not-found
=> :not-found
Then in production, you can:
(timbre/set-level! :trace)
… to skip the timbre/spy message.

😎 2
Michael Gardner22:06:56

I really wish assert returned its argument, since (assert (get ...)) feels really natural. Of course you can write your own

👍 2
thumbnail15:06:10

I noticed take always returns a collection, while take-last might return nil. For instance when the input is empty;

(take 1 [])
=> ()
(take-last 1 [])
=> nil
Is there a rational for this behaviour?

Alex Miller (Clojure team)15:06:57

from a seq point of view, these are the same

thumbnail15:06:44

Sure thing, i ran into this because I changed some code and now the api returned nil instead of an empty collection. Unfortunately not all our clients use languages with good nilpunning 😅

Alex Miller (Clojure team)15:06:55

in general, you should guard against this by using (seq ...) in the if condition (or seq'ing the result) if passing it on

2
Endre Bakken Stovner16:06:32

I have this super-weird behavior in my multithreaded code: When my error message is the following:

error-message (count missing-files)
My error message is printed: 1 But when I do error-message (str missing-files) nothing is printed (most likely because an error is thrown). How do I debug? The line in question is https://github.com/endrebak/everclear/blob/working/src/clj/everclear/state/jobs.clj#L128. Note that the use of tap> is not the problem either. It also fails when I try (println missing-files). Any ideas what might be wrong or how I can try to debug?

Endre Bakken Stovner16:06:47

I've tried reproducing what happens here:

(require '[babashka.process :as p :refer [process]])
(require '[ :as io])
(def bb-process (process ["bash" "-c" "echo hi!"] {:shutdown p/destroy}))
(def java-proc (:proc bb-process))
(defn post-process []
  (throw (Exception. "Hi")))

(.thenApply
           (.onExit java-proc)
           (reify java.util.function.Function
             (apply [this p]
                 (post-process))))

(defn read-process [proc] ;; babashka/process
  (try
    (with-open [rdr (io/reader (:out proc))]
      (binding [*in* rdr]
        (loop []
          (let [line (read-line)]
            (when (not (nil? line))
              (println line)
              (recur))))))
    (catch Exception e
      (println "ooops\n" (pr-str e)))))
(read-process bb-process)
But this actually throws an error.

p-himik16:06:37

What do you mean by "use of `tap>` is not the problem either"? Have you tried using it with e.g. Reveal?

noisesmith16:06:30

to be clear, tap> does not display any stack trace if it fails, it just silently fails

noisesmith16:06:53

you need try/catch inside your tapping function if you need to know it failed

Endre Bakken Stovner17:06:12

But if I remove the tap and just add a print it also fails.

Endre Bakken Stovner17:06:47

I should try to simplify my code. I just wanted to quickly throw together something that worked but I guess I need to simplify it to find the error.

Endre Bakken Stovner17:06:07

Thanks for the tip about reveal! I'll look into it

greglook17:06:34

it sounds like one of the values in your collection is throwing an exception in its toString method

noisesmith17:06:31

ins)user=> (defn try-string [o] (try (.toString o) (catch Exception e (pr-str e))))
#'user/try-string
(ins)user=> (try-string (reify Object (toString [_] (/ 1 0))))
"#error {\n :cause \"Divide by zero\"\n :via\n [{:type java.lang.ArithmeticException\n   :message \"Divide by zero\"\n   :at [clojure.lang.Numbers divide \"Numbers.java\" 188]}]\n :trace\n [[clojure.lang.Numbers divide \"Numbers.java\" 188]\n ..."
one way to approach it

noisesmith17:06:09

works like regular str on values that don't throw

(ins)user=> (try-string 1)
"1"

Endre Bakken Stovner12:06:59

Thanks, will try tomorrow. No time today :thumbsup:

Endre Bakken Stovner14:06:27

Worked wonderfully, thanks 🙂

👍 2
Endre Bakken Stovner16:06:33

(type missing-files) ;; clojure.lang.APersistentMap$ValSeqs and (count missing-files) ;; 1 work, but when I try to touch the contents of missing-files for example with (type (first missing-files)) my function goes mum again and nothing is printed.

jdkealy17:06:11

how can i parse a string to timestamp that has AM/PM in the string? I tried clj-time, but it seems to ignore the aa param in the formatter, Read instant date doesn't like the syntax either (def custom-formatter (f/formatter "yyyy-MM-dd HH:mm aa")) (str (f/parse custom-formatter "2021-06-28 03:00 pm")) => "2021-06-28T03:00:00.000Z" (str (f/parse custom-formatter "2021-06-28 03:00 am")) => "2021-06-28T03:00:00.000Z"

noisesmith17:06:15

it's not hard to do it with raw interop

(cmd)user=> (java.text.SimpleDateFormat. "hh:mm a" java.util.Locale/US)
#object[java.text.SimpleDateFormat 0xc4c0b41 "java.text.SimpleDateFormat@3264901b"]
(cmd)user=> (.parse *1 "11:30 AM")
#inst "1970-01-01T19:30:00.000-00:00"

noisesmith17:06:36

I added the explicit locale because "AM" and "PM" are not universal to all locales

noisesmith17:06:34

oh, your issue is that the resulting string doesn't have am/pm - you need to use the date format a second time to get that

borkdude17:06:50

I would prefer to use java.time in 2021

👍 5
noisesmith17:06:07

(cmd)user=> (java.text.SimpleDateFormat. "hh:mm a" java.util.Locale/US)
#object[java.text.SimpleDateFormat 0xc4c0b41 "java.text.SimpleDateFormat@3264901b"]
(cmd)user=> (.parse *1 "11:30 AM")
#inst "1970-01-01T19:30:00.000-00:00"
(ins)user=> (str (.format *2 *1))
"11:30 AM"

noisesmith17:06:34

anyway, it's doable with dateformat, you just need to use the format method to get the format back out in a string is all

noisesmith17:06:08

or, more helpful probably, you need to use the formatter function of whatever library you are using, which I assume must be there

noisesmith18:06:10

@jdkealy clj-time calls the function you want unparse, but I agree with @borkdude that you should use something based on java.time, clj-time is deprecated

seancorfield18:06:11

(`clj-time` is pretty clearly deprecated and has a big, bold notice at the top of the readme recommending folks use something based on Java Time instead!)

borkdude19:06:09

I'm glad I went with java.time in babashka

seancorfield19:06:40

I'm glad we have stopped using clj-time altogether at work!

borkdude19:06:13

we're still using it at work because I'm extremely lazy when it comes to rewriting something which works quite well for a long time already

👍 3
jdkealy19:06:58

Thanks y'all 🙂

borkdude19:06:23

@seancorfield oh hah, I didn't realize you used to maintain that lib ;)

seancorfield19:06:44

Yup, for years 🙂 because we used it at work. But recently I put in a "tech debt" Jira ticket to get us off it, mostly to raw Java Time, but some clojure.java-time wrapper code still exists. And we still have some date-clj code in play as well (I have another Jira ticket to get rid of that).

Lennart Buit19:06:56

We have clojure.java-time as well, but lately we’ve been using plain interop more and more. I don’t know, plain interop seems a bit more transparent to me

💯 2
Shantanu Kumar23:06:22

Not sure if I'm asking in the right channel; I want to know how do people upgrade the clj tool on Linux systems. Just download the new installer version and run?

seancorfield00:06:06

What I do is use linuxbrew (HomeBrew for Linux) so I can use the regular clojure/tools/clojure tap and install any version I want, as well as easily upgrading or downgrading.

👍 3
thanks3 3