This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-29
Channels
- # aws-lambda (13)
- # beginners (4)
- # cider (6)
- # cljs-dev (1)
- # cljsrn (4)
- # clojure (134)
- # clojure-android (7)
- # clojure-dev (14)
- # clojure-russia (18)
- # clojure-spec (3)
- # clojurescript (81)
- # core-matrix (2)
- # datomic (9)
- # figwheel (1)
- # hoplon (11)
- # lumo (10)
- # off-topic (18)
- # onyx (78)
- # pedestal (5)
- # portkey (2)
- # re-frame (8)
- # reagent (3)
- # rum (1)
- # spacemacs (23)
- # yada (5)
Does ring's multipart-params
middleware turn binary application/octet-stream uploads into an ASCII string? How do I turn that into something I can serve as a file in an HTTP response? The byte-streams
library can't seem to do it with to-input-stream
. (like with a jpg image)
I've got
(defn stream->bytes [is]
(loop [b (.read is) accum []]
(if (< b 0)
accum
(recur (.read is) (conj accum b)))))
(defn body[resp]
{ :body (with-open [is (byte-streams/to-input-stream (:upload (:multipart-params resp)))]
(stream->bytes is)) }
)
And {:body (byte-streams/to-input-stream (.getBytes (:upload (:multipart-params resp)) StandardCharsets/US_ASCII))}
doesn't seem to render properly either
@bradford what is the type of (:upload (:multipart-params resp))
?
I would assume
would be a better function there as compared to byte-streams/to-input-stream
- just going on the fact that it takes a char encoding arg if nothing else
Why does clojure.lang.RT/canSeq
need to check both ISeq
and Seqable
when ISeq <- IPersistentCollection <- Seqable
?
static public boolean canSeq(Object coll){
return coll instanceof ISeq
|| coll instanceof Seqable
|| coll == null
|| coll instanceof Iterable
|| coll.getClass().isArray()
|| coll instanceof CharSequence
|| coll instanceof Map;
}
( (+ x 2) (+ y 3)) would be like (x+2) (y+3) Is there a structured way to convert sexp <-> math notation ?
@qqq yes, and it's a fun puzzzle
@qqq there's a few. Search for clojure infix
: Example: https://github.com/rm-hull/infix ,
in Rich's talk on Spec, https://vimeo.com/195711510, he mentions that vars are "fully reified" - what does he mean by that ?
@octo221 reified
=> It's data, not just syntax as with many other programming languages. You can inspect them, assign them, pass them around etc.
ah code-as-data
then around 37:15 he says he would reduce the amount of reification in the var system - why ?
does he mean that fns are too coupled to their implementations ?
I guess it's about wanting more late-binding right ?
short of using low level monitors on objects, have we a way to synchronize side-effecting functions across threads?
thanks. looking for synchronous operation, agents won't do, but I will be looking at core.async (go blocks) for establishing something like actor semantics
yes they're both asynchronous constructs if you need synchronicity, monitors are the way to go
yes but kind of ugly in clojure, feels like a java singleton, unless I'm missing something
now I kind of forgot why actors were designed to re-try rather than lock in the first place
@octo221 right now vars do way too much. Var metadata holds: doc-strings, information about when the var was added, inlining information, linking information, arglist info, etc. Most of that stuff doesn't need to be there, but over time var metadata has just been the place where we dump everything that needs to be named.
that's why spec has its own registry, the var registry is polluted enough as it is.
@matan don't do side-effects in go blocks they have a limited thread pool. Use clojure.core.async/thread
instead
@tbaldridge non-blocking side-effects are ok in go blocks right ?
@tbaldridge ahh right - cheers!
@leonoel yeah, that's fine, and side-effects in general are fine (like a println) it's just that if the tread blocks for awhile it can cause a deadlock, but not a problem unless your sideffects take longer than 100ms or so
@tbaldridge also the questioner referred to the var & spec registries as "databases"...I guess that's what they are in a way...one could add re-frame's event registry to that and others. Given that there's all these ways to manage naming of things, has there been much discussion about other ways to do it ? I remember there was once an experiment with immutable namespaces too
@leonoel not really, agents are given a separate thread per agent if you use send-off
yes, I mean you need to know if your call is blocking or not and choose the pool appropriately
I am trying to recap on atoms v.s. monitor locks (now that I'm using locking
for a side-effecting database operation that is called from many threads).
Is it correct that atoms can never run into deadlocks nor into very terrible livelocks?
atoms are not suitable for side-effecting operations because they can be run several times when run concurrently
leonoel: if you are using swap!
there's no code path with multiple swap! calls that leads to deadlock
compare-and-set is proven to be a lock-free programming technique, and the inability to cause deadlocks is literally the definition of "lock free" in cs literature - and compare-and-set is the only coordination used by swap! assignment
is deadlock a term specific to mutexes or is it generic to any situation where on thread waits for something forever ?
it's generic for any case where a thread never proceeds
ok got it, I was conflating deadlock / livelock / starvation, thanks for the reminder ๐
I've long forgotten why locking is more expensive though... might just take it as a given
matan: it's more expensive because using a lock is a multi-step process that isn't free. It also easily leads to subtle bugs that cause deadlock which is infinitely expensive
anyway, it's just a rule of thumb, if there is high contention you'll need to benchmark
thanks for all the support. working with a MySQL auto-incrementing key in code that needs to be synchronized was kind of a pain ๐
it is thread safe on the local JVM, but concurrency-unsafe for the system as a whole, if the database get-or-set is not synchronized
My experience is that if your database transaction needs support from its callers in order to maintain your isolation and consistency requirements, you probably need to rework the transaction. ๐
@donaldball you are probably right
@donaldball or rethink the schema ๐ญ
There is a #sql room which might be more appropriate for an exploration of that, but one place to start might be increasing your txn isolation level to SERIALIZABLE
, or if youโre doing an upsert use the mysql-specific syntax to do that in one statement
q: is it possible to dynamically load namespaces in clojure based on runtime state? I get ClassNotFoundException if I try to 'require' inside a function body
@dthurn to compile code that isn't available yet, you need to use a dereference to lookup the values at runtime, this is typically done with resolve
which returns a var (if it can be found)
anyway, that works in a repl
resolve prevents the language from helping you
@dthurn ns-resolve says "look this symbol up as if we were currently in some other ns" - it's usually not what you want
resolve is the simpler one
eg if you have (ns foo.bar (:require [baz as b])) you can do (ns-resolve 'foo.bar 'b/f) to find baz/f
Hey all, I'm trying to set up Cloud9 (https://c9.io/) to play about with Clojure, according to this gist: https://gist.github.com/vothane/6678578
@danp what about if you run lein run -m clojure.main
if clojure.main via run works, then the likely problem is permission to open a port - lein runs a client / server repl over a local tcp port
yes, that works - thanks @noisesmith
@danp from that run your cp is set up and you can require your project
so it's at least minimally usable - but you could also figure out what's happening with lein repl (eg. try using trampoline so it doesn't use a tcp port, or check configs for permissions)
You also might try increasing the timeout for lein in case its just slow to start: :repl-options {:timeout 120000}
oh right - lein times out, I didn't think of that
@noisesmith - lein trampoline works ๐
cool - then it's almost definitely a "permission to open a local port" thing
which I could totally see being an issue in a container
yeah - to be honest, I think this is good enough. We're off on holidays next week and I want to be able to play around on the Chromebook ๐
it just means no cider etc.
wouldn't be a deal breaker for me, but I know some people really like their editor connected repl
thanks again @noisesmith
WARNING: cat already refers to: #'clojure.core/cat in namespace: net.cgrand.parsley.fold, being replaced by: #'net.cgrand.parsley.fold/cat
That should be safe to ignore. Newer versions of Clojure added some new functions like cat
and many libraries that define functions of the same name have not been updated to :exclude
the Clojure functions which causes that warning.
donyorm: i won't address pros and cons, since it kinda broke my heart to move from leiningen to boot, but for the record they are completely
lein has good docs and it's declarative and slow; boot is less documented and imperative and faster
declarative vs. imperative: with lein you have configs that lead to build actions; with boot you write code that does your build actions
I prefer leiningen - for a large part because its been around longer and its what I know, some day I might actually try boot
if you are only going to know one build tool you'll have an easier time with lein, it is what most projects assume you use
You could also argue that lein is "easier" but boot is "simpler". There's a ton of magic in lein.
that's true
As a quick generalization, use lein for bog-simple OSS libs that donโt deviate from the norm. Use boot for big apps with complicated build/compile/deploy steps, or donโt do things in the standard way.
donyorm: i won't address pros and cons, since it kinda broke my heart to move from leiningen to boot, but for the record they are completely
boot brings clojurity to task pipelines - groovy immutability and lots more. there's really no comparison except for trivial stuff.
i've worked with about a billion build tools, from make to cmake, scons, ant, gradle, etc. etc. and of course lein. they all suck, in their own charming ways. why? because they are build tools - they treat building sw as a special kind of thing. boot is the first and only tool i've ever seen that solves the build problem - by recognizing that building sw is just programming. no fancy dsl, just ordinary clojure code.
just wondering -- what's the rationale behind require's syntax looking like (:require [x :as y] [z])
? and not just taking some map / vec of the namespaces and aliases
or not (:require [[x :as y] [z]])
(which is more let
y)? i mean you have to pick something so everything will be quite arbitrary but just wondering
let needs the extra [] to separate bindings from body
require has no such distinction
If I was starting from scratch, I'd probably try to learn boot first, since it's more powerful in the long run. But yeah, I already know lein, and it works, so just haven't gotten around to boot yet.