Fork me on GitHub
#beginners
<
2024-05-17
>
ChillPillzKillzBillz07:05:42

Hello Friends, I have an issue running the clojure shell when deployed as a jar file. The code I am running is very simple.

(ns tstsh.shtst
  (:gen-class)
  (:require [clojure.java.shell :refer [sh]]))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println (:out (sh "ls"))))
When I run this in REPL I get the expected output. However when I build the this simple code into a jar, the code execution hangs after printing out the results of ls. I've tried to omit the shell command and run just a simple println string, in which case the jar executes as expected. Has anyone expected this before? Why does this happen? Any help will be appreciated. Thanks!

rolt07:05:55

There is probably a pending thread. You can add (shutdown-agents) after the println.

ChillPillzKillzBillz07:05:21

thanks! let me try that!

rolt07:05:17

If you want to force the termination of the program despite pending threads you can use (System/exit 0)

ChillPillzKillzBillz07:05:50

(shutdown-agents) worked just fine many thanks

rolt08:05:02

(though I'd use the return code of ls as return code of your program in this case)

Hoon Wee07:05:49

Hello folks, I am curious what's the difference between these two methods of accessing nested map fields:

(def simple-map {:hello {:world "Hoon"}})

;; Method one, using threading macro (->)
(-> simple-map :hello :world)

;; Method two, using `get-in`
(get-in simple-map [:hello :world])

daveliepmann07:05:42

Most of the time there's no appreciable difference.

šŸ‘ 1
dawdler07:05:26

For one, a get-in into a nested map is easier to read, imo. Afaik, both are linear time O(n), but in different ways: ā€¢ -> O(n) n number of forms (expansion time) ā€¢ get-in Both select-keys and get-in have linear behavior in the number of selection keys. If you need to select a huge number of keys from an even larger map, you might consider the option of dissoc the unwanted keys instead of selecting the wanted ones. Ref. Clojure the Essential Reference

šŸ‘ 1
Hoon Wee08:05:42

I see, thanks!

Ed08:05:55

If some of your keys are not executable as functions (for example a string) then the get-in form will be easier to work with.

ā˜ļø 1
phill09:05:34

In a hot loop, and depending on what's in the vector, the get-in technique might be slower. If the vector isn't a constant literal, your program has to allocate it and populate it and garbage-collect it. And in any case, get-in has to traverse the vector and do what your threading form does. In short, get-in is a wondrous tool but if you don't need that tool's killer feature (which is the vector) then get-in is a luxury.

Alex Miller (Clojure team)12:05:35

get-in is usually much slower, but has the benefit of being able to use a dynamic key set at runtime

šŸ™ 1
Alex Miller (Clojure team)12:05:30

The -> expansion happens once at compile time whereas get-in work happens on every execution

Leo E15:05:49

@U072P0JLYP2 Often you need to destruct n keys from each level, not only one and in this case can use this approach instead

(let [{:keys [payload meta] event}
      {:keys [key1 key2] payload}])

Hoon Wee09:05:09

@U0P0TMEFJ I see... I wonder what would be the case for using functions map keys?

Hoon Wee09:05:57

@U0HG4EHMH @U064X3EF3 So to summarize, I should use the -> most of the time except when there is a need to use get-in's superpower, I presume

Ed15:05:14

> I wonder what would be the case for using functions map keys? I didn't mean using literal functions as keys. Keywords like :hello and :world are executable as functions, that's how the thread-first macro -> works. It passes the result down the chain as the first argument to each function, it's not just for accessing data from a map. So (-> simple-map :hello :world) will macro expand to (:world (:hello simple-map)), before it is complied. That's one reason it's faster. But it also means that if the keys are strings or numbers (which are not functions) then that trick won't work.

(-> {"hello" "world"} "hello")
will only give you an error
class java.lang.String cannot be cast to class clojure.lang.IFn
. Make sense?

šŸ‘ 1
Hoon Wee00:05:04

Aha, got it! Thanks a million šŸ’µ

šŸ‘ 1