One returns a list, the other a string. I want both to return a string. How do I fix this?
user=> (apply merge-with (fn [& args] (str/join " " (flatten args))) '({0 ["abc"]} {0 ["def"]}))
{0 "abc def"}
user=> (apply merge-with (fn [& args] (str/join " " (flatten args))) '({0 ["abc"]}))
{0 ["abc"]}
(into {}
(for [[k vs]
(apply merge-with concat <list>)]
[k (str/join " " vs)]))
I'd probably make the merge or even group-by and then as a separate step join the strings (eg. clojure.walk or just reduce)
walk
I hadn't heard of. Seems cool, but feels kinda un-clojuric: "do this then that" in one function.
walk isn't "do this then that", it's "apply this transformation to each level of a nested structure", which is very "clojuric"
But you have one transformation you do at each level and then you have one you do at the end on the result, right?
(walk #(* 2 %) #(apply + %) [1 2 3 4 5])
This seems less complected to me:
(apply + (walk #(* 2 %) [1 2 3 4 5])
walk itself is rarely needed - it's a building block for implementing post-walk and pre-walk, and more elegant than the two being mostly copy/paste of one another
I'm trying the Clojure tools.cli
https://github.com/clojure/tools.cli#quick-start in the REPL and am getting these errors:
my.program> (parse-opts {:port 80} cli-options)
Execution error (ClassCastException) at clojure.tools.cli/tokenize-args (cli.cljc:34).
class clojure.lang.MapEntry cannot be cast to class java.lang.CharSequence (clojure.lang.MapEntry is in unnamed module of loader 'app'; java.lang.CharSequence is in module java.base of loader 'bootstrap')
my.program=> (parse-opts "{:port 80}" cli-options)
Execution error (ClassCastException) at clojure.tools.cli/tokenize-args (cli.cljc:34).
class java.lang.Character cannot be cast to class java.lang.CharSequence (java.lang.Character and java.lang.CharSequence are in module java.base of loader 'bootstrap')
What is the correct usage from the REPL?(parse-opts ["-p" "2020"] [["-p" "--port PORT" "Port number"]])
$ bb -e '(clojure.tools.cli/parse-opts ["-p" "2020"] [["-p" "--port PORT" "Port number"]])'
{:options {:port "2020"}, :arguments [], :summary " -p, --port PORT Port number", :errors nil}
Wonderful!
To use it my way I'll do:
(defn -main [& args]
(let [opts (if (map? (first args))
(first args)
(parse-opts args cli-options))]
(start-app opts)))
It's probably better to write another function, since by convention -main
functions receive string args
True! With a name like start-from-repl
or start-with-map
or something.
I have a callback function and it might use some of the dynamic bindings, which are not the same when the callback is called as when it was created. I was trying to solve it by using clojure.core/binding-conveyor-fn
but that thing is private. Whatβs the best solution for this (capturing bindings when making a function)?
you could simply use let
(def ^:dynamic *foo* 1)
(def ^:dynamic *bar* 2)
(def f
(let [foo *foo*
bar *bar*]
(fn []
(+ foo bar))))
(binding [*foo* 2 *bar* 5]
(f)) ;; => 3 not 7
Are there strings containing command line commands that might break because I have to split them?
(clojure.java.shell/sh "echo hi") ;; fails
(clojure.java.shell/sh (clojure.string/split "echo 'hi there'" #" ")) ;; works in this case, but will it do so for all?
@endrebak babashka.process has a function called tokenize
will will split shell strings for you
Since you also asked in #babashka I gave more info there
Thanks! I meant to delete some of the qs that weren't specific to bb, but I must have forgotten. Thanks again!
thank you so much flowthing
What am I doing wrong here?
user> (require '[clojure.java.shell :refer [sh]])
user> (sh "bash" "-c" "sleep" "1" ";" "echo" "hi")
;; => {:exit 1, :out "", :err "usage: sleep seconds\n"}
bash -c expect a string
this should work
(sh "bash" "-c" "sleep 1")
yes (sh "bash" "-c" "sleep 1; echo hi")
Yes! That actually made it a lot easier too π Thanks
How can I dispatch a shell/sh
job and then be notified when it is finished?
also, ProcessBuilder
/ Process
are not very hard to use, and support a lot of thinks shell/sh doesn't do
for example this runs lua and sends to its stdin after it starts:
let [pb (ProcessBuilder. ["lua"])
p (.start pb)
out (.getOutputStream p)
in (.getInputStream p)]
(spit out "print \"hello from lua\"\n")
(slurp in))
returns the string "hello from lua\n"
if you have lua installedThanks! I'll remember that if I ever need more advanced functionality π
This seems like one way: https://stackoverflow.com/questions/16349415/is-there-a-way-to-be-notified-when-a-clojure-future-finishes Would love to hear better suggestions π
Jeez, that was simple:
(future (computation) (callback))
Hi, I have a vector of keys and a value. How can I create a map where the vector turned into nested keys and the value is the value of those keys? For example: This is the vector
[:a :b :c]
And this is the value:
{:name "John"}
I want the result to be:
{:a {:b {:c {:name "John"}}}}
Thanks@rinam (assoc-in {} the-vector the-map)
@borkdude Thank you!
is there some magic config to help CircliCI understand test.check failures a bit better?
(defspec oops
(prop/for-all [x gen/int]
(even? x)))
And the output isI can get the output out of the "STEPS" tab, but would be nice if it was present in the "TESTS" report tab