This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-03
Channels
- # announcements (12)
- # beginners (44)
- # boot (27)
- # calva (73)
- # cider (1)
- # clj-kondo (9)
- # cljdoc (9)
- # cljs-dev (15)
- # cljsrn (6)
- # clojure (90)
- # clojure-dev (5)
- # clojure-europe (4)
- # clojure-ireland (3)
- # clojure-italy (22)
- # clojure-mexico (2)
- # clojure-nl (8)
- # clojure-uk (32)
- # clojurescript (12)
- # core-async (2)
- # cursive (16)
- # data-science (10)
- # datascript (3)
- # datomic (44)
- # emacs (17)
- # events (4)
- # graalvm (1)
- # hoplon (5)
- # jackdaw (17)
- # keechma (11)
- # nrepl (7)
- # off-topic (24)
- # re-frame (19)
- # reitit (4)
- # rewrite-clj (2)
- # robots (9)
- # shadow-cljs (20)
- # sql (12)
- # testing (4)
- # tools-deps (23)
- # vim (55)
bash> clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.7.0"}}}'
Clojure 1.7.0
user=> (eval `(let [a 42]))
CompilerException java.lang.RuntimeException: Can't let qualified name: user/a, compiling:(NO_SOURCE_PATH:2:1)
How to execute system command using clojure? I mean I can call and write into command prompt using clojure. Any ideas
@michael.e.loughlin Thank you for the reply. I read that clojure doc but I'm not able to figure out how to write using all that in clojure
As @michael.e.loughlin says, we need more specifics about your question. The sh
function that he linked to is exactly what you need to interact with operating system processes. It is a thin layer on top of the underlying Java facility, Runtime.exec(), https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec(java.lang.String[],%20java.lang.String[],%20java.io.File)
This is one of those cases where you need to learn things beyond Clojure itself to understand the Java environment in which it operates.
If you can tell us exactly what you are trying to accomplish, for example the system command you want to run and the arguments, we can perhaps show how that would be formatted when calling sh
? But to be able to come up with the answer yourself will require understanding the Java mechanism, and the underlying operating system process mechanism.
@U0EHA00G1 Thanks for the reply. So I want to read and write on command prompt using clojure for Brl-Cad. Suppose I want to pass this command
(sh "mged" "-c" "test.g" "ls")
The problem is I'm not able to figure out how to pass this syntax in clojure programming.I tried this but it's not writing in command prompt
(ns brl-project.core
(:require [clojure.java.shell :refer [sh]]))
(defn test []
(:out (sh "mged" "-c" "test.g" "ls")))
I am confused by what you mean when you say “read and write on command prompt.” That is something that users do, not programs. Java (and your underlying operating sytstem, what are you using?) lets you execute subprocesses and pass them arguments and gather there responses. But there will be no window or “command prompt” associated with that. The value will come back as a response map, which you seem to have noticed in your example. When I invoke (clojure.java.shell/sh "ls" "/usr")
in a repl, I get back a map that looks like this:
{:exit 0,
:out "X11\nbin\nlib\nlibexec\nlocal\nsbin\nshare\nstandalone\n",
:err ""}
So, the result of running that command is available: The process terminated with an exit status of 0
, the output that was written to stdout
is available as a string under the key :out
, and the output that was written to stderr
(of which there was none) is available as a string under a key under :err
. This allows my Clojure code to run other programs and interact with them, and examine the results. Can you clarify what is missing from your perspective?
I do notice that in your example you seem to be trying to run two separate commands, mged -c test.g
followed by ls
. You can’t do that with a single invocation of sh
. If for some reason you really don’t want to call sh
separately from Clojure for each command you want to run, you can either put the commands into a temporary file as a shell script and run sh
with that file as an argument, or you can explicitly invoke the shell executable with a -c
argument followed by a string containing all of the commands you want parsed out, something like this:
(clojure.java.shell/sh "/bin/sh" "-c" "ls /usr ; ls /var")
{:exit 0,
:out
"X11\nbin\nlib\nlibexec\nlocal\nsbin\nshare\nstandalone\nagentx\nat\naudit\nbackups\ndb\nempty\nfolders\ninstall\njabberd\nlib\nlog\nma\nmail\nmobile\nmsgs\nnetboot\nnetworkd\nroot\nrpc\nrun\nrwho\nservermgrd\nspool\ntmp\ntmptmpdb5dLEX\ntmptmpdb5dLEX-journal\ntmptmpdblboqU\nvm\nyp\n",
:err ""}
Hey @U0EHA00G1, thanks for explaining the above concept.
i'm impementing a client library for an http api. part of the auth workflow is requesting a token, then you have to poll an endpoint while the user performs a second factor verification, once that is complete, the polling endpoint returns the token. What's the proper/clojure way to handle this in a library? I want to avoid blocking the consumer. Perhaps a channel?
so when you are destructuring a map using something like [{:keys [foo bar]}]
then does foo
and bar
have to coincide directly to the keys :foo
and :bar
? Because if not how does that work if maps are unordered?
Not sure, but maybe you are thinking that this will only work if you have a map of {:foo "footer" :bar "barter"}
? You are right @U9J50BY4C in that keys in maps are not "ordered", so the order you specify them as part of the :keys
vectors makes no difference.
Yep, I think it was just a brain fart where I was trying to think why aren't we just using the actual keyword instead. I just hadn't thought it through again to where it was binding the value of that corresponding keyword like lilactown mentioned.
yes, {:keys [foo bar]}
means "given a map with keys :foo
and :bar
, bind the value at :foo
to the local foo
and the value at :bar
to the local bar
"
is there a function that would turn something like [1 2 3]
into just 1 2 3
? might have been a macro or something
(str [1 2 3])
=> "[1 2 3]"
(apply str [1 2 3])
=> "123" ;; same as (str 1 2 3)
What’s the bigger issue you’re trying to solve?
I was just exploring the [& args]
portion of function parameters and what I could do with them. They get packaged up in a sequence right so you can do anything with them as you would in a sequence?
indeed
but what if you didn't want them as a sequence? You want them individually like "normal" parameters but you didn't know how many inputs you would have so you just went with [& args]
. I think my problem was this started as a random hypothetical thought exercise to check my understanding but I don't have a concrete thing I'm trying to do here. So I don't know if this would even ever come up
you could destructure args
in the function body
user=> (defn f [& args]
#_=> (let [[a b c] args]
#_=> (println a b c)))
#'user/f
user=> (f 1)
1 nil nil
nil
user=> (f 1 2)
1 2 nil
nil
user=> (f 1 2 3)
1 2 3
nil
you can also define multiple arities: http://clojure-doc.org/articles/language/functions.html#multi-arity-functions
Multiple arities is the best way to go if your use case allows for it.