This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-07
Channels
- # aleph (8)
- # beginners (16)
- # boot (5)
- # cider (22)
- # cljs-dev (15)
- # clojars (10)
- # clojure (94)
- # clojure-dusseldorf (1)
- # clojure-france (57)
- # clojure-greece (1)
- # clojure-spec (9)
- # clojurescript (15)
- # core-async (6)
- # cursive (11)
- # datomic (10)
- # emacs (6)
- # funcool (1)
- # hoplon (1)
- # off-topic (5)
- # re-frame (8)
- # spacemacs (8)
- # specter (4)
- # unrepl (10)
- # vim (5)
(defn handler [req]
(let [resp ((bidi.ring/make-handler routes) req)]
(println (:request-method req) (:uri req) "->" (:status resp))
resp))
(defn start-server []
(jetty/run-jetty #'handler {:port 8080
:host "0.0.0.0"
:join? false}))
is how i define start-server
the serverand routes
is like
(def routes ["/" {"todos" {:get {"" list-todos}
:post {"" create-todo}
:options {"" options}
["/" [#"\d+" :id]] {:get get-todo}}
"" {:options options}}])
where get-todo
etc. are functions defn
dUse #'
on the symbols.
It introduces a layer of redirection through a Var
so the redefinitions are picked up.
That’s how I develop web apps and it works really well from the REPL.
According to https://clojure.org/reference/reader, keywords cannot contain .
but that is allowed by the reader and used in many projects (e.g. Datomic's :db.type/keyword
) - are we relying on undefined behavior there or is that possibly a documentation inconsistency?
within a namespace, ::x
means the keyword x
under that namespace, and outside that namespace, :ns/x
refers to the same keyword if ns
is a path to that namespace from this one
@gws if I understand correctly that is a limitation on the name part, not the namespace part
I could be mistaken though
@nikki yeah, I thought that too, and FYI the "prefix" here is called a namespace
yeah, but in context, namespaces are expected to always contain a dot, and the :: reader syntax attaches the current namespace to the keyword
so I think that :a.a is accidentally allowed, and :a.a/b is intentionally allowed
I could be wrong about that - but it would be weird if namespaced keywords belonging to every correctly designated namespace are in error
I agree that namespaced keywords are very intentional and almost certainly not in error, I'm just trying to get at what that part of the doc means, since I've never known .
to be disallowed in keywords (may predate my use of Clojure, though)
@gws the keyword reader has always accepted invalid keywords as literals
where "valid" means the spec and not the implementation clearly
(not to mention the keyword
function happily accepting any crap you can fit in a string...)
OK, I think that answers my question - I started looking at this because I had a short-lived notion that I'd make oauth scopes into keywords and was surprised to see :
accepted in the REPL
Is it possible to do the equivalent of JS spread operator in clojure for function args: e.g. fn(...args)
?
Hmmm. That might work.
apply worked.
are there ever a time when namespaces are implicitly loaded in the repl? or are procedures only ever loaded when they are called?
procedures are not loaded when called
a namespace is loaded if designated as the main ns, and clojure will run its -main function if any
there's also mechanisms like leiningen's :init-ns configuration, that run a repl and load a specific ns and put the user in that ns at startup
otherwise clojure.main (if it is run) will put you in the user
ns and you will need to use require
to make other namespaces available, and in-ns
to switch to another ns
is a function prints something to the repl, is it possible to wrap the function call in something which suppresses those messages? or redirects them to a log file?
anyway, with-out-str works in a real repl
it returns a string with everything that function printed in it
great! thanks 🙂
what’s the current state of the art in parallelized reduce? (I can write my fn such that it has an init val and produces n “todo” items); it seems like the answer is manifold streams/core.async rather than fold
not core.reducers?
maybe; they seem like mostly suffering from pre-transducer everybody-gets-a-mapcat; also I’m not super sure that what I have is actually a fold (maybe it is, but it has the weird property that processing an item can produce more items to process)
if you use core.async, just remember that go blocks are not for blocking tasks (which includes heavy CPU usage as well as io)
@noisesmith why IO is also not recommended ? I think that because its running on a OS thread, there is no problem when doing it, the Kernel will schedule it efficient
@elevi core.async uses a small thread pool, doing IO in core.async threads starves core.async, if it is done enough then no core.async code runs
if you mean non-blocking IO, non-blocking IO doesn't happen in the calling thread, so it is fine
@elevi right, my emphasis was on blocking - in most code the only things that block are io, sometimes occasionally heavy CPU usage
non-blocking io isn't something I see very often in jvm code (could be I'm looking at the wrong code?)
elevi: yes and no, http-kit
supports some form of async io, but the important parts of the implementation are undocumented. For example, sending to a websocket is a blocking operation
It's one of the reasons why I recommend using some other library for async http work, there's a few too many edge cases in http-kit
@U07TDTQNL didn't know that, thanks
yes, java.nio provides it, and it's wrapped by things like aleph and http-kit
what I'm saying is that I don't see people using it
Agree, I don't think anyone uses nio directly, its very low-level, but I think that all the modern clients, at least in Clojure, support some kind of async IO
I'm talking about app code (and library code if it does requests on your behalf) - I'm not seeing async oriented code bases
not like you'd see in js
I speculate that it's because outside bottlenecks the extra complication of the async apis isn't worth it, but I'd welcome an example of doing this properly that doesn't turn out more complex than the blocking code
having worked on a pretty complex app for a while, I've come to the conclusion that async is a problem - it makes code more complex, it causes failure cases that are harder to diagnose and fix; it's worth taking on if it fixes some other more important problem though
because the control flow is less clear, even with core.async
because the stack traces become nearly meaningless, the immediate parent of every function is the dispatching go thread (in core.async) or some random callee (regular callbacks)
because simple errors have strange and far reaching consequences that in my experience devs are bad at catching when reading code
because errors get swallowed by some consumer's try/catch and you never find out they happened
because data pipelines get locked up by some flaw in the middle and there's nearly no way to know why just looking at stack traces and printlns
example from just the other day: a coworker had some code that was taking 20 minutes to return, it should have returned in under a minute. It turned out he was doing a blocking take inside a go block. He didn't even know the take he was doing was blocking.
from just looking at the symptoms, we never would have guessed which part of the code was causing the behavior
he thought the remote api call was taking too long to complete
I'm not saying don't use async - I use it a lot! - I'm saying it makes code a lot trickier, and it isn't beneficial on its own - you need to have a reason to use it, some problem it actually solves
that was a great experience report, thanks @noisesmith
Yea, but core.async make it more simpler, at least for me, I tend to work with channels instead callbacks, my code feels much more synchronous with it.
About the data flow and encapsulation complexity, I think things are much easier in Golang
, their tools are great, every Goroutine
have its own stack and it's easy to see whats your code is doing right now. I don't think these tools can be ported to Clojure because how they implemented core.async
, e.g not using some-kind of thread mechanism
I think core.async is the best async option in clojure for sure - I'm talking about things that tend to go wrong with async code (in my limited expertise and experience)
async as in asynchronous, as in the paradigm, to be clear
I also think that, core.async is my goto when it comes to async. Did you tried other concurrency features like Agents ?
yes, I have code that uses agents and futures and claypoole/pmap and regular pmap, in the past I've also used refs
@noisesmith @elevi i've got a load of async code, mostly with promises (manifold Deferred) and streams (manifold Streams) - i use the promise monad courtesy of cats https://github.com/funcool/cats/blob/master/src/cats/labs/manifold.clj for structuring, which leads to async code which reads very similarly to equivalent sync code
stack traces, or the lack thereof, are sometimes still a problem, but not terrible - similar to working with lazy seqs
is there a builtin for string -> int which taxes a hexcode string and outputs a decimal int
@qqq you can certainly use java.math.BigInteger
to do that - https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#BigInteger(java.lang.String,%20int) ... calling longValue
on the BigInteger
will give you a primitive long &c
I believe I have seen a clojure library that will give you a "private" version of a library by copying its source code and renaming the namespaces
something to that effect; does anybody know what library I'm thinking of?
I have spent dozens of seconds on google trying to find this, to no avail
many millihours have been wasted
@bronsa perfect, thanks!