This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-08-10
Channels
- # aleph (3)
- # architecture (3)
- # bangalore-clj (5)
- # beginners (75)
- # boot (75)
- # cider (2)
- # cljs-dev (48)
- # cljsjs (3)
- # cljsrn (17)
- # clojure (125)
- # clojure-belgium (1)
- # clojure-boston (1)
- # clojure-italy (20)
- # clojure-losangeles (2)
- # clojure-spec (73)
- # clojure-uk (34)
- # clojurescript (127)
- # cursive (8)
- # data-science (5)
- # datascript (128)
- # datomic (5)
- # emacs (4)
- # events (3)
- # fulcro (1)
- # jobs (1)
- # jobs-discuss (4)
- # jobs-rus (9)
- # keechma (79)
- # lein-figwheel (2)
- # leiningen (2)
- # lumo (31)
- # om (1)
- # parinfer (61)
- # pedestal (1)
- # planck (1)
- # portkey (31)
- # re-frame (34)
- # reagent (53)
- # ring (3)
- # ring-swagger (13)
- # rum (1)
- # spacemacs (14)
- # testing (1)
- # yada (2)
This made my day: http://clochure.org/
cljs/reagent users already use that https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/views.cljs#L44
@qqq have you already tried lisping (http://slidetocode.com/lisping)?
even tough it has no REPL support for Clojure (only Scheme), I like it for code editing and navigation.
Hey clojurists. I am using a library and need to bind a var a few times. Is there a way to do a 'one off' binding
for a whole namespace? push-thread-bindings
which is used internally by binding
has a creepy "WARNING: This is a low-level function" in the docs.
@ido you cannot guarantee, that nothing in ns will send some closures to another thread, and/or that if so – sending those ns-wide bindings will be actually ok, can you? Or is it ok for your use case?
is there any difference in having this top level form at the beginning of the specs ns, and having it declared and called as a macro?
(let [pairs [['foo 'x.y.z.foo]
['bar 'x.y.z.bar] ...]] ;; there would be like 10+ namespaces listed here
(doseq [[a n] pairs]
(create-ns n)
(alias a n)))
Are there any obvious problems with this, or any better alternatives? (intentions is just to get short aliased keywords for spec names, like ::foo/id
and ::bar/id
apparently, cursive's rename keyword feature does not see those create-ns/alias inside let, and renaming ::bar/id
will drop its namespace alias. cc @cfleming
swap!
is synchronous, right? It does not return until fn is successfully applied, does it?
Is there an equivalent of compare-and-set!
, but only for a sub-value in an atom (like single kv in a map)?
@lvh, I did this so far:
(defn lock! [!machine]
(let [m @!machine]
(if (:locked? m)
false
(compare-and-set! !machine m (assoc m :locked? true)))))
(defn transition! [!machine]
(when (lock! !machine)
(swap! !machine f)
I don’t understand what you’re trying to do, but I especially don’t get why you’d make that :locked explicit
I’d just use swap!
and if you really care about concurrent updates, 2 atoms if you don’t need coordination/transactionality between them, and 2 refs if you do
I want single atom, which accepts new events in a queue at any point in time. But has only 1 worker processing events at a time.
Another requirement: event handlers might contain side effects, so I can't afford to retry those. Probably this is where "single system-wide(?) worker at a time" comes from
because a single action is executed at a time from a queue agents never need to re-run actions
read all about it https://clojure.org/reference/agents
https://clojurescript.org/about/differences
Agents are currently not implemented
an agent is, basically, a persistent queue inside an atom. it's not very difficult to implement
since cljs is a single thread env (right?), very naive implementation will suffice, so it should be just an inconvenience to have 2 implementations, rather than 1
you will effectively never see a swap! retried in clojurescript unless the function that you pass to swap! also calls swap! on the same atom
if I use agent in a lib, how should I clean those up? shutdown-agents
is system wide, and is not appropriate for a lib's teardown function, I think. Should I just put a note in README?
I wonder if I should put any safety flag in an agent value, in case some user's event handler will emit events in an infinite (go?) loop. So that agent can reject any new jobs. Or am I overthinking it?
in general, I get the impression that people who work on clojurescript have never used clojure for a significant amount of time, so clojurescript often does what they think it does, and not what clojure actually does
is this a general observation, or for something specific above? (single threaded env does indeed atrophy "concurrency thinking" to some degree)
I need some type advice; I've used spec to describe a really big map of related data that is passed around between a bunch of functions. when there's a spec violation, the error message contains all the arguments, and emacs goes to a dark place
my initial idea is to create a new type with a different toString but leave it enough of a map to be a valid s/keys container. is that reasonable?
second idea is to remove specs from those functions and only put them farther down in the details where the world object has been broken up already
I don't know how to avoid dumping it all out, the cider error buffer gets the spec error, and the spec error ignores print-len
nice!
whats the most clojuric way of doing (for [item items] (do stuff))
but also binding the index
as well as item
(for [[index item] (map-indexed list items)] ...)
(map-indexed identity items)
, no?
@pesterhazy map-indexed
expects arity-2 function, identity
is arity-1, it'll throw in clojure, might work somehow in clojurescript
@misha, you're right!
I think I usually use (map vector (range) [:a :b :c])
@yedi In addition, if you can guarantee that items
is a vector, you can just use reduce-kv
@pesterhazy I prefer list
over vector
when the collection only gets created in order to pull it apart again - the difference between a couple conses and a 16 slot array
but that’s a personal preference of course, perf likely doesn’t matter here
@noisesmith the 16 slot array (and isn't it 32) doesn't get created at first. Vectors have a tail that grows by 1 until it reaches 32 elements, then it's pushed into the tree.
oh, cool
And clojure has some "borrow" semantics around arrays, so that [1 2] only allocates an array (needed for the vararg call) and then that array is wrapped with a vector object.
@javazquez define "streaming API". Streaming XML, audio, video? Is it streaming over HTTP SSE, long polling, websockets, etc.
@tbaldridge HTTP SSE
@pesterhazy @tbaldridge thanks for the info, vector
on two args benchmarks as 3x faster than list
so my only remaining argument is character count 😄
criterium results for anyone who cares
peregrine.circle=> (crit/bench (vector 1 2))
WARNING: Final GC required 10.2356120766764 % of runtime
WARNING: Final GC required 1.0077331583723619 % of runtime
Evaluation count : 4943172240 in 60 samples of 82386204 calls.
Execution time mean : 10.204242 ns
Execution time std-deviation : 0.301496 ns
Execution time lower quantile : 9.784033 ns ( 2.5%)
Execution time upper quantile : 10.777083 ns (97.5%)
Overhead used : 2.257806 ns
Found 1 outliers in 60 samples (1.6667 %)
low-severe 1 (1.6667 %)
Variance from outliers : 15.8380 % Variance is moderately inflated by outliers
nil
peregrine.circle=> (crit/bench (list 1 2))
Evaluation count : 1730757660 in 60 samples of 28845961 calls.
Execution time mean : 33.978224 ns
Execution time std-deviation : 1.770012 ns
Execution time lower quantile : 32.142992 ns ( 2.5%)
Execution time upper quantile : 38.101712 ns (97.5%)
Overhead used : 2.257806 ns
Found 7 outliers in 60 samples (11.6667 %)
low-severe 4 (6.6667 %)
low-mild 3 (5.0000 %)
Variance from outliers : 38.4645 % Variance is moderately inflated by outliers
nil
@pesterhazy BUT - map-indexed with list is twice as fast as map with vector and range - of course the (map-indexed vector coll)
version is fastest though - just a little bit faster than the version using list
interesting to know, thanks for running the numbers
Pipeing question, I want to do a basic pipe operation from clojure string into an application, the application in question can receive from stdin line this cat file.txt | app -
, insetead of the cat, would I use byte-buffer writer and send it to an exec of getRuntime. Maybe some code example would get me going..
here's an example I have handy
(defn run-command-stream-output
"Runs a shell command and streams the output.
An exception is thrown if the exist status is non-zero."
[command]
(log/info "headphones.common.shell/run-command-stream-output:: " command)
(let [process (.start (ProcessBuilder. (into-array String command)))]
(future (io/copy (.getInputStream process) (System/out)))
(future (io/copy (.getErrorStream process) (System/err)))
(if (not= (.waitFor process) 0)
(throw (Exception. (str "Failed command '" (clojure.string/join " " command) "'"))))))
you'd be wanting to getOutputStream instead of getInputStream but other than that pretty similar
no just send text into the app, the output is a side effect (no return value or stdout stuff happening)
yeah but what I mean is, the function to call on the process to get stream to write to it, is getOutputStream 🙂
it's kind of the opposite of what you'd expect. getOutputStream returns an OutputStream and anything you write to it will go to stdin of the proc. vice versa for getInputStream. it makes sense if you think about it for a bit but it's definitely surprising first up
it's defenitely confuseing in terms of what is going where. Of course the binary has its own stream mechanism, reading what you wrote, the binary would implement something on the lines of getInputStream.
But how does the clojure string become a stream, with the into-array and process builder above?
to move the clojure string into the stream of the process's stdin you'd do something like (.write (.getOutputStream process) (.getBytes string))
my app just hangs with this, maybe .getBytes needs to be some sort a buffer?
(ly-compile-from-string ["lilypond" "-"] basic-string)
(defn ly-compile-from-string
[command ly-str]
(let [process (.start (ProcessBuilder. (into-array String command)))]
(future (.write (.getOutputStream process) (.getBytes ly-str)))
(future (io/copy (.getInputStream process) (System/out)))
(future (io/copy (.getErrorStream process) (System/err)))
(if (not= (.waitFor process) 0)
(throw (Exception. (str "Failed command '" (clojure.string/join " " command) "'")))
(println "finished"))))
no, it just hangs, I se the print from stderr showing it starts just as expected, but it's waiting/hanging
well, it finished the same string if it's either echoed and piped or in a file cat piped.
the general pattern appears to work
user=> (def process (.start (ProcessBuilder. (into-array String ["read"]))))
#'user/process
user=> (future (.waitFor process) (println "finished"))
#<Future@ef0ece1 pending>
user=> (def writer (java.io.PrintWriter. (.getOutputStream process)))
#'user/writer
user=> (.println writer "bash")
nil
user=> (.close writer)
nil
finished
user=>
user=> (def process (.start (ProcessBuilder. (into-array String ["read"]))))
#'user/process
user=> (future (.waitFor process) (println "finished"))
#<Future@6d354b41 pending>
user=> (def writer (java.io.PrintWriter. (.getOutputStream process)))
#'user/writer
user=> (.println writer "bash\n")
nil
user=> (.flush writer)
nilfinished
this is what Im running, not finishing
(def basic
" \\version \"2.19.59\"
{
c' e' g' e'
}
")
(ly-compile-from-string ["lilypond" "-"] basic)
(defn ly-compile-from-string
[command ly-str]
(let [process (.start (ProcessBuilder. (into-array String command)))
writer (java.io.PrintWriter. (.getOutputStream process))]
(.println writer ly-str)
(.flush writer)
(future (.waitFor process) (println "finished"))))
the command line that succeeds
cat | lilypond -
cat http://test.ly | lilypond - will close the input stream once it's exhausted http://test.ly
what happens if you just do $ lilypond - and type the data in, do you need to hit ^D to make it stop?
so it would be a good move to write line by line and do close when the last line is written?
shrug I don't think it would make a difference. so long as you call .close when you're done
an example with cat, which has similar behaviour to lilypond by the sounds
user=> (def process (.start (ProcessBuilder. (into-array String ["cat" "-" ">" "foo.txt"]))))
#'user/process
user=> (future (.waitFor process) (println "finished"))
#<Future@204d0de5 pending>
user=> (def writer (java.io.PrintWriter. (.getOutputStream process)))
#'user/writer
user=> (.println writer "blah")
nil
user=> (.close writer)
nilfinished