I’ve always used parinfer. What’s a good alternative I should learn?
if you emacs …. with vim I use https://www.vim.org/scripts/script.php?script_id=3998
lispy for emacs https://github.com/abo-abo/lispy
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)
no mention of paredit
? that's the gold standard
It works on macOS as well, I will try in windows cmd.exe...
doesn't work in cmd.exe
with the native console, but it does work if you use the new Terminal app on Windows
search "vt100 clear screen"
so it seems to be fairly portable, assuming everyone will use the new terminal on Windows
Great, otherwise the alternative is to detect the OS, then run the appropriate shell command... This quasi oneliner is preferable
@adam678 On windows I think you can detect the new terminal usage using an environment variable
user=> (System/getenv "WT_SESSION")
"c1d08d7a-69ae-4dc2-93e6-8689e6789dd1"
I take it if you're NOT in the new terminal, this will return an empty string instead of a UUID, correct?
it will return nil probably
Yeah depends what editor you use. In my case it's Emacs/EVIL, so you go with Lispy/Lispyville. Lispyville integrates nicely with EVIL.
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?
get m k <pivot>)
check pivot
or find
first but it does not work for get-in
I guess I could just (get m k (Exception.))
.
@michael348 Yes, good idea!
Nope, did not work.
That will return a new exception
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)))))
Cool! I was hoping for something like that.
I guess I could add it to my dev/env.clj
:thumbsup:
providing not-found
in get
can be quite elegant: https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L7203
It should break libraries that use get-in
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?from a seq point of view, these are the same
Good point.
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 😅
in general, you should guard against this by using (seq ...) in the if condition (or seq'ing the result) if passing it on
What I've seen some people do is to just define sget
and sget-in
, which do the above. The "s" meaing "safe".
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.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?Thanks, will try tomorrow. No time today :thumbsup:
Worked wonderfully, thanks 🙂
I've tried reproducing what happens here:
(require '[babashka.process :as p :refer [process]])
(require '[<http://clojure.java.io|clojure.java.io> :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.(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.
What do you mean by "use of `tap>` is not the problem either"? Have you tried using it with e.g. Reveal?
to be clear, tap>
does not display any stack trace if it fails, it just silently fails
you need try/catch inside your tapping function if you need to know it failed
But if I remove the tap and just add a print it also fails.
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.
Thanks for the tip about reveal! I'll look into it
it sounds like one of the values in your collection is throwing an exception in its toString
method
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 itworks like regular str on values that don't throw
(ins)user=> (try-string 1)
"1"
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"
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"
I added the explicit locale because "AM" and "PM" are not universal to all locales
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
I would prefer to use java.time
in 2021
(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"
that's fair
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
or, more helpful probably, you need to use the formatter function of whatever library you are using, which I assume must be there
(`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!)
I'm glad I went with java.time
in babashka
I'm glad we have stopped using clj-time
altogether at work!
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
Thanks y'all 🙂
Straight from the source 🙂 https://github.com/clj-time/clj-time/commit/26e0f3ad066612336fce3050a3ea845072cf26aa
@seancorfield oh hah, I didn't realize you used to maintain that lib ;)
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).
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
there's also cljc.java-time (bb compatible): https://github.com/babashka/babashka/blob/master/doc/projects.md#cljcjava-time
I really wish assert
returned its argument, since (assert (get ...))
feels really natural. Of course you can write your own
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?
Yep.