This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-14
Channels
- # beginners (31)
- # boot (9)
- # cider (10)
- # cljs-dev (9)
- # cljsrn (16)
- # clojure (222)
- # clojure-austin (4)
- # clojure-france (13)
- # clojure-italy (21)
- # clojure-nl (2)
- # clojure-russia (71)
- # clojure-spec (9)
- # clojure-uk (39)
- # clojurescript (50)
- # cursive (16)
- # datomic (69)
- # dirac (2)
- # figwheel (1)
- # graphql (19)
- # hoplon (4)
- # jobs (1)
- # klipse (3)
- # leiningen (4)
- # liberator (3)
- # luminus (9)
- # lumo (9)
- # off-topic (3)
- # om (21)
- # onyx (11)
- # parinfer (2)
- # pedestal (8)
- # planck (19)
- # re-frame (17)
- # reagent (12)
- # remote-jobs (1)
- # ring-swagger (3)
- # spacemacs (17)
- # specter (23)
- # sql (1)
- # unrepl (64)
- # untangled (19)
- # yada (5)
Ahh, ok. I guess I can recall normally without TCO… As a trie, it’s not too deep. Will have to check.
Hi, I am learning the reader conditional, and I tried this code in repl. I found it not returned as I expected, as showed in the 3rd and 5th expression, I thought these will return “CLR”:
user> (read-string {:read-cond :allow :features #{:cljs}} "#?(:cljs \"ClojureScript\" :clj \"Clojure\")")
"ClojureScript"
user> (read-string {:read-cond :allow :features #{:cljs}} "#?(:cljs \"ClojureScript\" :clj \"Clojure\" :clr \"CRL\")")
"ClojureScript"
user> (read-string {:read-cond :allow :features #{:clr}} "#?(:cljs \"ClojureScript\" :clj \"Clojure\" :clr \"CRL\")")
"Clojure"
user> (read-string {:read-cond :allow :features #{:clj}} "#?(:cljs \"ClojureScript\" :clj \"Clojure\" :clr \"CRL\")")
"Clojure"
user> (read-string {:read-cond :allow :features #{:clr}} "#?(:cljs \"ClojureScript\" :clj \"Clojure\" :clr \"CRL\")")
"Clojure"
user> (read-string {:read-cond :allow :features #{:clr}} "#?(:cljs \"ClojureScript\" :clr \"CRL\")")
"CRL"
user> (read-string {:read-cond :allow :features #{:clr}} "#?(:cljs \"ClojureScript\" :clr \"CRL\" :clj \"Clojure\")")
"CRL"
user> (read-string {:read-cond :allow :features #{:clj}} "#?(:cljs \"ClojureScript\" :clr \"CRL\" :clj \"Clojure\")")
"Clojure"
user> (read-string {:read-cond :allow :features #{:cljs}} "#?(:cljs \"ClojureScript\" :clr \"CRL\" :clj \"Clojure\")")
"ClojureScript"
Why is this possible? Thanks.the doc https://clojure.org/reference/reader said “However, note that the Clojure reader will always inject the platform feature :clj as well.” Does that because of this?
That sounds like the most likely explanation.
Is there a good online resource for the subtleties of deftype? I’m trying to use a Java array as an unsycnhronized-mutable field, and getting some weird behavior when trying to use aset
(This is non-idiomatic, performance-sensitive code)
I get an ArrayStoreException when using aset
inside the the type, but similar code produces no errors at the REPL
kingmob: have you seen this? https://docs.oracle.com/javase/7/docs/api/java/lang/ArrayStoreException.html
it sounds like you need to respect the type of your array
Thanks, @noisesmith, yes, I saw that. I finally figured out the issue an hour later. The reason the code worked manually, but not in my fns must have been references to outdated definitions. This isn’t the first time I’ve noticed some weird evaluation errors when using records/types, forward declarations and external factory fns. Once I evaled everything in the correct order, the problem disappeared.
:thumbsup:
Is there some weird interaction between set!
and aset
going on?
Today in extreme overuse of Clojure: I wanted to pretty-print json in color from the command line. 7-line Python script with pygments only worked from local directory but not from $PATH for totally mysterious reasons. So I rewrote it in 11 lines of Clojure. Amusingly, it turns out that Clygments pulls in, among other things, all of Jython. So my 11 line trivial thing is a 40mb(!!!) binary. But, by god, it WORKS FROM THE PATH. https://github.com/paultopia/cloppjson
I am querying an integer array in postgres database using clojure.java.jdbc. The result is coming back as an org.postgresql.jdbc4.Jdbc4Array. Is there any simple way to get this to coerce back into a clojure vector?
kenbier: calling .getArray
on it should get you a Java array and then into []
should let you get Clojure vector?
@seancorfield hmm ok, thanks. I suppose I’ll have to do this for each query that returns an array? Leave the connection open and call .getArray
.
Check out this section of the java.jdbc
docs http://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql.html#protocol-extensions-for-transforming-values
sweet that works!! thanks @seancorfield
@gowder: That's amazing. I love it. I just spend like 30 seconds going, "Oh yes. Oh no. Oh yes. Oh no..."
@seancorfield hmm ok, thanks. I suppose I’ll have to do this for each query that returns an array? Leave the connection open and call .getArray
.
@seancorfield Hi, I still do not understand why the :clj
will intercept :cljs
and :clr
form. What does the inject the platform feature :clj
mean in “However, note that the Clojure reader will always inject the platform feature :clj as well.” ? Thank you.
cmal: It's as-if the set of features always has :clj
in it (as well as whatever you specify) -- so the reader goes through the list of conditional forms and picks the first one that is in the set.
So if :clj
is first, it will always match.
is there any project which provides erlang like processes on top of clojure via core.async (for the mailboxes)
pulsar I think, not sure how reliable this is tho. It's not easy to replicate these on the jvm
@gowder: FWIW, jq (https://stedolan.github.io/jq) also works for pretty-printing JSON with colors.
is there a cleaner way make a postwalk with state (without atom): https://gist.github.com/razum2um/b691ad0d760795efaeb886e6caf05122 ?
razum2um: I would prefer to reduce over tree-seq, rather than post-walk with a side effecting function - you can get the same result without needing to mutate anything
(reduce (fn [state el] (if-let [datum (:data el)] (conj state datum) state)) [] (tree-seq coll? seq x))
Hi, why does transducer here returns a vector rather than a list?
user> (def xf (map dec))
#'user/xf
user> (transduce xf conj (range 10))
[-1 0 1 2 3 4 5 6 7 8]
I thought it would return (-1 0 1 2 3 4 5 6 7 8)
instead.if you provided ()
you'd get (8 7 6 5 4 3 2 1 0 -1)
anyway not [], since seqs conj to the left
@cmal If you want a lazy seq as a result of applying your transducer, check out https://clojuredocs.org/clojure.core/sequence
@flowthing did not know that, thanks!
I was watching this talk of rich hicky https://www.youtube.com/watch?v=oyLBGkS5ICk
i didn't get exactly what he meant about the solution instead of semantic versioning for functions, NSs and artifacts
One takeaway from this is that the interface to your public functions which are used by others should not change as you release new code.
Much in the same way data is by definition immutable, and the lion who jumps is not the same lion who lands (paraphrasing here), the interface to your functions, once exposed, should not change. This also means they should not be removed if at all possible (or arities removed, or type of return change, etc). Better to call a function foo2
than to change foo
and break lots of other code which depends on it. @lxsameer
@lxsameer He's saying that sem-ver doesn't actually /solve/ the problem of breaking changes, it just brushes it under the rug. A better way to "solve" the problem of breaking changes is not to make them.
good , so basically for changing a namespace i have to create new one ( ofcourse it was not possible to change it and keep the old interface at the same time) , right ?
'artifacts' is a weird way to talk about it, I think. His example of python was good
If your library has changed so much it won't work with previous versions, it needs a new name
Because, let's face it, Python2 and Python3 are different languages, and both will have to be maintained separately until the end of time
changing a namespace is ok if the contract is respected adding new functions is ok correct a bug is ok improve perf is ok make a function accept less is ok make a function return more is ok etc etc...
e.g. it could return a map with extra keys
yes -- though this gets into hairy territory, and gets into what expectations the caller has, even if they aren't explicitly guaranteed by the callee. If a function has been known to always return {:a 1 :b 2}
and the function now adds a new k-v to this, then equality checks which expect only :a
and :b
(even if incorrectly, as they should select the keys they need) will fail ... it's not an unlikely scenario
This is a Leiningen specific question, but what's the difference between :dependencies
and :plugins
on the profile configuration file?
@rinaldi plugins are about modifying / enhancing leiningen itself. dependencies are your code's needed libraries
Where can I find a good writeup on the differences of cljs/core.async and clj/core.async . It seems like there should be some fundamental differences since browser js is single threaded; but I don't know enough about it to dcerive all tye implications.
@qqq I think the main difference is that thread >!! <!! alt!!
et al have no meaning, so you use go >! <! alt!
instead always. I found David Nolen's blog posts on core.async the best intro to it, and they're all written in cljs, so that might be a place to start
when usint (chan 10), this is a chan with at most 10 elements. is there a way to tell put! or >! on this channel to return an error instead of blocking ?
David Nolen has mentioned in the past that a certain layout was kept in cljs code to keep the diffs from clj simple
so there may not be explicitly shared code, but they at least look at the diffs in respect to the two repos
unless I totally misunderstood him
though I think in general, I'm okay with the 'taker' blocking, but the 'putter' sometimes need to tell stuff to backfoff
>!
will park on a full buffer, >!!
will block, and put!
will always succeed, unless the pending puts limit of 1024 is reached, which means that you are doing too many async puts @qqq
park means “let someone else use the thread your go is currently using”
@qqq pretty much, yes -- park means "save the state of this thead, and let another piece of code use it"
go blocks describe a series of continuations delimited by parking operations, and it’s helpful to avoid calling them “threads” since threads are real things that we use
noisesmith: are they green threads? fibers? thread-as-codepath v thread-as-execution context? maybe "continuation" is the best term, even if clojure doesn't have first-class continuations. i can never decide on the most appropriate terminology.
they depend on the JVM implementation, which on all but the most obscure systems are native OS threads
yeah, I’d avoid using “thread” to describe a code path in a language that uses actual threads and calls them such
there’s probably a less clumsy language to describe what’s in a go block, perhaps “state machine” or even just “program”
as in “a go block describes a program with steps executed in specified order, but is passed between threads at parking operation boundaries, and is erroneous if it fails to park or halt”
noisesmith: problem is it's so natural to think of the codepath as a thread. but the execution thread is a different animal. i have yet to find an explanation with clear simple language for this.
it’s a pragmatic choice to not use thread in this context; we have an object that is actually called a thread formally in the system, so calling other things threads is counterproductive
just like calling methods “functions” - it made sense to allow idiomatically allow calling methods functions in java before java 8
but in clojure where we have an actual function type, and java after java 7 where there is a Function type, using function/method interchangeably is just spreading confusion
I like that, especially since golang already calls them “goroutines”
and in line with what noisesmith just said, note that unlike preemptable native threads, code executing in a go
block must relinquish control (to other, parked code) in order to pause execution, so the semantics of threads and go blocks are not the same, even though threads are the vehicle used to execute the code in a go block
the go macro in particular is very different between cljs and clojure, the clojure one uses tools.analyzer
the clojure go macro tries to avoid splitting code that it doesn't have to, but the cljs just splits everything (if I recall)
the clojure one I read because I wanted to see how they decided to do it, the cljs one because I wanted to fix bugs in it
the fact that it is a macro isn't all that interesting, it is really a compiler from source language to target language
it is neat. just core.async effectively contains two different compilers. compilers tend to be complicated and have odd bugs and edge cases, and having two distinct ones mean bug fixes in one may or may not translate over
cljs core.async has other interesting issues, because macroexpansion in cljs can return what is effectively a blob of javascript, which the core.async analyzer cannot analyze
@lxsameer Yeah... I quite like the approach given by Carlo Pescio: http://www.carlopescio.com/2012/12/ask-not-what-object-is-but.html It's about: minimize the sum of the size of artifacts you change. - Or: don't change things, just add stuff
Simple rule, not always very simple to implement, but it's been very helpful to me ever since I read his blog.
just, given some code that running it under cljs with core.async and under clojure with core.async, what are the odds the code runs the same given that cljs and clojure don't share code, core.async cljs and core.async clojure don't share code, and whatever js runtime you pick may or may not share some amount of code with the jvm you pick
when an offer! fails, is there a way in a go-block to say: I'm going to chill for a bit, let other blocks run ?
@qqq more generally, you could just read from anything, even if you know it returns instantly, to give the go scheduler a chance to change things up
I think…
or write to something, for that matter
hi, is there any way to send a client certificate (.crt and .key) in a Get request? in clojure
@alricu I believe you have to create a keystore (client cert / key), and a truststore (CA). Then you pass it as an option to clj-http https://github.com/dakrone/clj-http/#keystores-trust-stores
creating the keystore involves a baroque set of cli commands that you have to look up even if you've made them 1000 times
grab lock
... do some work
release lock
is this primitive basically not available in clojure ?locking
there’s good reason to prefer lock free stuff, but locking does what you just described
the jvm lets any object used as a lock, called a "monitor", which is what locking does
https://clojuredocs.org/clojure.core/locking <-- whoa, was unaware of this
you usually are better off with a design that doesn’t use it
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/package-summary.html
I need an "atom" where the swap! is NOT re-entrant ... where (swap! a f) <-- f is called 0precisely once
you can’t really have correct code with precisely once can you? at most once is reasonable
(as opposed to swap! which is at least once)
well, you can’t have exactly once semantics over a network period
@noisesmith: you can't reason about computer programs unless you have 'precisely once execution of functions locally'
when a test.check run causes an exception, where does it say what value caused the error?
@qqq but we are talking about N threads, once you have that precisely once doesn’t really work out
@noisesmith: I think you are making untrue assumptions.
Imagine we have an initial state s0; imageine wse have a bunch of functions f1, f2, f3, f4, f5, .... each of which has type signature :: state -> state
@hoff how are you invoking test.check?
(defn exec [s f] (locking s (reset! s (f @s))) // this guarantess precisely once invocation
@qqq zero or once
because someone else could have the lock
@hoff it should print a map that has both the initial problematic value and the shrunken one
like I said, zero or once, they could hold on until exit
I'm just getting '{:result #error { :cause nil :via [{:type java.lang.StackOverflowError :message nil :at [clojure.lang.RT seq "RT.java" 525]}] :trace [[clojure.lang.RT seq "RT.java" 525]'
@hoff check below the stack
for a key :fail
@noisesmith : I don't think that is the official definitino of 'zero or once'
@hoff then you'll also see a top-level key :shrunk
with a key :smallest
by your argument, even sinl-gle threadced programs are also only zero-or-once, because, in theory, you could throw the computer out the window
@qqq it’s a basic rule of concurrent systems, you can have zero or one, you can have one or more, you can’t have precisely once.
once concurrency exists those are your conditions
found it, it was hidden at the end of the last line. (there was a stacktrace line shifting it off to the right)
@hoff some sort of default manner of printing exceptions by clojure proper has unfortunate effects like that
@qqq anyway, calling compare-and-set! and only calling f if the function returns true is an alternative but it doesn’t prevent calling on stale state, otherwise yeah you need a lock.
but compare-and-set! will respond false if your state is old
@bfabry : yes, f_i can have side effects; what I want is when I feed it f1, f2, f3, ... f9 (from possibly different threads) -- I want each f_i to execute precisely once, but I don't care which order they evalute in; here, "preisely once -- assumes no deadlock, no crashing"
compare_and_set! doesn'w ork , because by the time we reailze the state is old, we al4ready did the sideeffects
sounds a lot like an agent - they prevent a lot of the issues with using locking directly
any reason why one wouldn’t do what you want?
yeah so atoms (generally) are not the primitives you want to be using to do something like that. atoms are for coordinating modifications to the atom, not for coordinating arbitrary modifications to the world. I'd suggest core.async (or maybe agents but I dunno much about them)
@noisesmith @bfabry : agents would be perfect, if only they were synchronous
what about a send wrapper that passes in a promise that gets delivered so the caller can block on it? maybe that’s hokey
promises are blocking promises
@p will block until someone delivers to it
p being defined as (let [p (promise)] …)
await is for all pending actions, not just the one you just sent - but it is simpler, yes
depending on usage pattern await could be better
probably better
https://groups.google.com/forum/#!topic/clojure/hvc2fzYYAWc <-- is there no promise for cljs yet? (I'm trying to write files in cljc)
there are no promises, and no agents, in cljs
if your code needs to be cljc use core.async
Sorry for being pedantic about the “no such thing as exactly once” thing, it’s a peeve of mine in distsys and isn’t an issue for most single server code. Systems that are distributed and claim exactly once are typically doing something disasterously wrong.
and really, “at most once” isn’t so bad 😄
but I feel like in a single machine environment, even if it's multi core multi processed, unless the machine halts / crashes / inf-loops, it is possible to guarantee "exactly once execution" -- otherwise, we dcan't reasonab about programs
> we can’t reason about programs agreed!
for what it's worth Google Dataflow promises "exactly-once semantics" which means that it rolls back the results of extra executions (gets thrown out the window if you do side-effects)
Executing something once is possible in practice, with the usual caveats about being on a single machine and assuming reliable hardware/OS/VM.
But yeah, once you distribute stuff or get to the point where reliability of the underlying system has to be taken into account, all bets are off.
And the byzantine general problem rears its head.