This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-01-03
Channels
- # admin-announcements (91)
- # announcements (1)
- # beginners (5)
- # boot (228)
- # cljs-dev (9)
- # cljsrn (12)
- # clojars (13)
- # clojure (175)
- # clojure-art (6)
- # clojure-russia (46)
- # clojurescript (35)
- # core-matrix (62)
- # cursive (10)
- # datomic (5)
- # hoplon (119)
- # ldnclj (11)
- # leiningen (7)
- # mount (3)
- # om (21)
- # reagent (2)
- # slack-help (1)
- # spacemacs (1)
Anybody else having issues getting to clojars?
dig seems to be resolving, so it doesnt seem to be dns issues.
linode still under ddos attack in atlanta which is where it’s hosted
ahh righto. are there any mirrors around that we can fall back to?
thanks @adammiller ! I thought there might be one. Lucky we got that funding for clojars not very long ago right??
yep, hopefully everyone keeps funding every month to keep it going and help build out some redundancy
even stranger is that LEIN_OFFLINE claims a whole bunch of plugins are missing, but they are clearly in ~/.m2
hi guys, is there anyway to enable debug log in aleph to log out some information about the request so it would be easier to work in dev env ?
I am new to clojure, and doing the online mooc on clojure, I am trying to do an exercise, and I am trying to check if an argument is list, and return the length of the vector
(defn generic-doublificate [x] (cond ((list? x) "A") (number? x (* x 2)) (empty? x nil) :else true ) )
(defn generic-doublificate [x] (cond ((list? x) "A") (number? x (* x 2)) (empty? x nil) :else true ) )
I am able to check whether list on the repl, but when I add to condn, it gives error. Can somebody help me?
@ratnakar: you have an odd number forms in that example, in your cond every two forms are a pair
@flyboarder: Thank you, Ahh, I see you mean in my eg list? and number? are 1 pair, and empty? + something else should be another pair?
@ratnakar: correct, see examples here https://clojuredocs.org/clojure.core/cond
@flyboarder: Great Thanks
@nxqd: does (println “Hello World!”)
not work?
to be more clarify, the code is like this :
(defn wrap-connection [handler conn]
(fn [req]
(println "test") ;; this does not work
(handler (assoc req :datomic conn))))
(defn counter-om-handler [conn]
(-> (wrap-connection handler conn)))
(defn counter-om-handler-dev [conn]
(fn [req]
;; this prn works
(prn (clojure.pprint/pprint (-> req :body bs/to-string)))
(counter-om-handler conn) req))
@triss, cljs: (instance? Atom x)
clj: (instance? clojure.lang.Atom x)
cheers @pesterhazy
I've finished the draft of a guide to Threading Macros, for possible inclusion on
: https://github.com/pesterhazy/clojure-site/blob/threading-macros/content/reference/threading_macros.adoc -- I'd be happy to get feedback of all types!
If you file a PR, I will be happy to review in depth
@alexmiller: ok. I'll do another round of language fixes and open a PR then
mm I just realised that these two are equivalent
why leaving both ways, in the "Clojure Applied" book both styles are used in the same page even
@andrea.crotti: only the first one is valid, I think
they both work in the same awy
(with-doc2 232) 232 clojure-applied.store> (with-docstring 232) 232
ah wait but with this (defn with-doc2 [x] "hello" x)
doesn't go in the docs
ok just a mistake in the book then
boot.user=> (defn a [] "aaa" nil)
#'boot.user/a
boot.user=> (doc a)
-------------------------
boot.user/a
([])
nil
nil
boot.user=> (defn b "bbb" [] nil)
#'boot.user/b
boot.user=> (doc b)
-------------------------
boot.user/b
([])
bbb
nil
`the second is equivalent to (defn with-doc2 [x] (do "hello" x))
yeah I noticed thanks, I'll raise a bug report for the book\
the reason that the docstring goes first is that there can be only one docstring but multiple arities and thus multiple arglists
(I think)
I think there is already an errata for this
it's not particularly intuitive though: maybe defn
should have an assert
that the first expr (of several) in the defn
is not a string?
If you don't see it, feel free to log, thx!
ok done
I'm not sure when they are going to let us do an ebook update
Your cautionary tale for the day—first I put a (map <side effect function> lazy-input)
and expected to get the full result list... then when I finally put a doall
in front of it, I hit useless SQLExceptions about how my transaction had been aborted.
After a while, I realized that I was handling SQLExceptions in one of my model creation functions by returning nil
. I thought, at the time, "oh, it's okay to return nil
if a table-level constraint fails... Clojure is good at handling nils!" But obviously, in the context of a larger transaction, there's a Java/Postgres world down there that doesn't follow the same rules.
The moral of the story: if you think you're converting errors from outside idioms to Clojure idioms, make sure you really, really are.
The moral of the moral: If you wouldn't swallow exceptions in Java, don't swallow them in Clojure.
All good points @amacdougall . I’m coming to the conclusion that jdbc/sql libraries are one of those places where the Java under-layer pokes through in painful ways.
probably un-avoidable, given we’re piggybacking on jdbc
@nxqd: looking to your pasted code, you are missing a pair of parens in the handler, so the result of (wrap-connection conn)
is never called. It should be:
(defn counter-om-handler-dev [conn]
(fn [req]
;; this prn works
(prn (clojure.pprint/pprint (-> req :body bs/to-string)))
((counter-om-handler conn) req)))
By the way, anyone have a suggestion for test data generation? This mess all started when I tried to use a Prismatic Schema generator to whip out 100 randomly generated users based on a schema, but it was too easy for it to generate non-unique values for unique fields like username/email.
I can definitely screw around with it until it works, but I also suspect that it's meant for straight up function-based chaos-intensive property testing more than for simulating realistic user data.
A library that forces me to handle "\"^-.$$" as a legit username is valuable in one way; a library that can generate complex nested test data is valuable in another. (Gonna try out jFairy maybe? I mean, it's Java, so of course there are like a hundred possibilities...) (Also, should "\"^-.$$" be a legit username?)
@amacdougall, have you looked into test.chuck
and test.check
?
Hm, test.chuck
could be handy!
Ultimately it's not going to be that big of a deal to write a function which generates n
unique values given an infinite sequence.
So swallowing database errors would be normal and effective in an all-Clojure stack, but fails because Java doesn't play ball? Can someone explain?
@pesterhazy: The Eastwood Clojure lint tool will warn about misplaced doc strings in your code: https://github.com/jonase/eastwood
@davidg: It's probably a terrible idea there as well! But in Clojure, a lot of functions return nil
when given nil
, instead of crashing the whole program, so returning nil
when there's a failure seems to make sense.
Or to put it another way, if your database itself were somehow written in Clojure, maybe it would be reasonable to return nil
whenever it hits an internal constraint such as field value uniqueness—and devs would be expected to check their constraints beforehand instead of getting errors after the failure.
Philosophically, database writes are important. It makes a lot of sense to make sure you're doing the right thing beforehand and treat every error as an emergency. So really, swallowing the exception is bad in both cases; it's just worse in our JDBC system, because an SQLException in a transaction aborts the transaction, and if you don't handle the exception, your Clojure code will be none the wiser.
Anyone knows how to wrangle
(component/using (webserver/make immutant-params) [:application])
into
(-> (webserver/make immutant-params)
(component/using [:application]))
using paredit? I thought raise would do it, but it substitutes the surrounding form for the one I raise, while I want to keep it around.I suppose I could kill the sexp and paste it before the opening paren but that seems... crude.
Ah, because when JDBC throws, it expects the caller to stop what it's doing, either by handling the exception, or not handling it.
@davidg: exactly. Just returning nil
might make sense in Clojure, though it's debatable. But doing that in a JDBC-based system means that you're ignoring vital context.
Well, nil
is never a right option if you need more information that "I cannot return what you want for reasons that will remain a mystery".
But if it's not returned there's no additional information besides just that - that is nothing was returned.
If you need to signify what went wrong you need something else, like Either
for example - a value that either has a "right" value returned or optionally a value signifying what sort of error happened.
Or you can use exceptions, I suppose, but I'm not a fan of those, unless something so exceptional happens that aborting the application is probably the only recourse.
I spoke up because I've heard it said before that nil is used to mean "error" in Clojure and that this is an impedance mismatch with Java sometimes, but I didn't really know what that means. It seems as simple as that Clojure style is to avoid APIs that throw exceptions and require catching them to use properly. Exceptions can be clunky and are not very FP.
Well, the impedance mismatch is caused by the fact that most Java APIs can't deal with null
and will blow up with a NPE, while most Clojure APIs treat nil
like Haskell would treat Maybe
- that is a something signifying absence of value that functions should ignore and pass unmolested through your program without executing any computations on it.
But there are cases where nil
makes sense, and where it does not - for example (retrieve-user id)
returning nil
is pretty straightforward to understand - no user was found, but what would (establish-connection! host {:timeout 500 :secret "secret"})
returning nil
mean? Was the host wrong? Was the timeout reached? Was the secret wrong and server returned a 403?
I understand APIs returning nil instead of throwing BlahNotFound. I hadn't thought about nil propagation being like NaN propagation. So (first nil) returns nil... and going with this style, any function that destructures or operates on data and could possibly pass through a nil should do so...
Yeah. In my case, I was returning nil
in cases where I expected an SQL error due to violating a table-level uniqueness constraint... which, JDBC aside, is just not a good way to handle it.
I'm still doing it, to be honest! I might fix it later. For now, I'm relying on the UI to prevent users to choosing non-unique values, and on unit tests to verify that the constraint exists.
I'm not sure about the "right" way to do it. In many languages, you'd catch an exception, or do something like...
result = do_the_operation();
if (result.error) {
// handle somehow
} else {
do_useful_stuff_with(result.data);
}
But that's not very Clojurey.
(match (something-that-can-fail
[:success result] (use result)
[:error error] (report error)])
or return a “tuple”, e.g., [true, nil] or [false, error-map], then you could (let [[success error] (do-operation)] (if success …))
I never forget that I’m using a functional programming language, which means I should have an idea about the domain and the range of the function. Those are especially important at the corner cases (I almost test only those corner cases). And I also never forget that at the corner cases is where the fun start, at least in mathematics….
Well, without core.match
the tuple way is a bit verbose. But with core.match
it's pretty neat.
I guess I still prefer using the Either
monad a bit because they compose quite well, in case of the tuple you would have to check it in each function operating on such a value.
@jaen: Edit->Structural->Thread Form is what you’re looking for there, with the cursor right before the form to be threaded (`(webserver/make immutant-params)` in your case)
@cfleming: thanks, that works well for ->
, though that's tailored towards threading; is such a general raise-without-substitution not possible then?
Fun new question: I'm using the experimental generators in Prismatic Schema to whip up this test data, and—because of the uniqueness constraint I was talking about—I do need unique usernames and emails. But making a lazy seq which hashes with distinct keys is just a short step beyond my knowledge.
The distinct
function wraps a lazy seq and returns a lazy seq of only the distinct values from it; but I have a lazy seq of more complex hashes (`(repeatedly (partial generate NewUser))`, to be exact).
(map first (group-by :username (take 100 (repeatedly (partial generate NewUser)))))
easily knocks duplicates out of the 100-user set, but of course I end up with fewer than 100.
I have a feeling I'm missing a core language feature that would make this a lot easier... I'm messing around with lazy-seq
right now.
Looks like the implementation of distinct
uses (let [seen (volatile! #{})]
, so I'll try something like that.
Okay, the "volatile" was related to the transducer implementation, so that was irrelevant, but I think I modified it work with my situation. 🎉
@amacdougall: not 100% sure what you are trying to do but distinct
is a stateful transducer that keeps track of items it's already seen in a volatile set.
I think if you did something like (take 100 (distinct (whatever...
that you should end up with 100 items
The sets of known emails and passwords are simply passed to each further step in the generation. That's roughly what I intended, but I couldn't puzzle out how to write it.
This is based on the implementation of clojure.core/distinct
, but tailored to my specific needs. There may be a more general way of writing this—for instance, I could pass it a schema and the fields which should be unique. That would cover my own testing needs.
(take 100 (generate-distinct NewUser :username :email))
or something.
The ongoing saga here is that I gave my database a uniqueness constraint on some fields, but now I'm trying to generate test data which conforms to that, so I can test various pagination/etc.
Ah, that's because {:username "bob" :color "green"}
and {:username "bob" :color "blue"}
are distinct, right? The constraint is field-level, but clojure.core/distinct
is =
-level.
At any rate, my tests are all passing now, so I think I'm finally in good shape. Thanks to everyone who kibitzed on my 🦆 session!
that's all distinct is doing - memoizing previous items into a set and then checking against that set
Yep! In this implementation, I just had to make separate sets of known usernames and emails, instead of distinct
's default set of all values.
Then for each generated user hash, check both :username
and :email
against the known sets.
Oh, and the trick that I didn't realize is that you can recur
within a fn
—it just returns to the top of the function! I couldn't figure out how to keep trying generated values until one of them satisfied the distinctness constraint.
But it's as easy as (recur (next-value) usernames emails)
.
Or as you can see in the gist, more like:
(if (satisfies-constraint)
(cons item overall-list)
(recur ...))
recur goes back to whatever point you tell it (ie, loop
) or I guess defaults to the top of the fn
I should have remembered that from The Joy of Clojure, but I only used it in loop
for a long time. Guess I forgot!
I'm still getting a handle on some of the finer points. And by "some of" I mean "all of"!
Oh, I didn't realize that. Can you give an example?
I mean with a transducer. I've only ever used it to convert between collection types.
here's a fun, completely generalized fn:
(defn produce
"Returns a lazy sequence of colls from a recursive, axiomatic,
transformative process."
[seed prep-f get-xf]
(letfn [(process
[coll]
(lazy-seq
(when (seq coll)
(let [new-coll (into (empty coll) (get-xf coll) (prep-f coll))]
(cons new-coll (process new-coll))))))]
(process seed)))
Haha, I can look it up on my own! Just curious if you had one in mind.
so I use that produce function a lot in my generative code, passing in various tranducers
lots of examples of that in my ergo
library: https://github.com/decomplect/ion/blob/master/src/ion/ergo/core.cljc
Interesting—so into
composes transducers just like a map
/ comp
structure?
Also, that library is blowing my mind just skimming the doc comments. I don't know enough about procedural generation to even begin to use it, but I'm impressed.
transducers are composable and into
can take a transducer so if you want to give it a transducer that is made up of several you just comp them together.
this isn't using transducers, just regular functions with into
, but this is the kind of stuff I find myself preferring over loop/recur:
vnpf-map (into {} (for [vert verts]
[vert (into {} (map next-pf
(vert-npfs-map vert)))]))
Interesting. Definitely a more functional approach.
I'm using Clojure mostly because I like ClojureScript... but I'm still doing relatively simple websites. But it seems like the gain in expressivity really comes to the fore in other domains.
Another:
fcolors (into {} (for [face (mp/faces mesh)]
(let [color (get-fc mesh face)
color (if color-mod (color-mod color) color)]
[face color])))
These other examples are from a 3D polygon mesh generating/processing library I'm working on and finding the functional approach to be a real joy. And that's after many years of OO.
I've always wondered what language choice says about people. You look at some of the most beautiful and creative computer-generated art, and there's no telling whether the code behind it is a dog's breakfast of C++ or whether it's just as refined as the art itself.
I have long since come to the conclusion that the only person who really cares how my code looks is me and maybe 40% of my co-workers, of whom another 20% are sure to get a headache every time they see a higher-order function.
Check it out and tell me what you think my attitude is: https://github.com/pkobrien/cad/tree/master/src/cad/mesh
Just skimming a few files? I would say balanced. I don't see any obvious duplication; I see the classic FP single-letter variable names used only where there's a conventional meaning for them; I see a lot of the more complex logical steps embodied in long let
sequences, which makes them fairly self-documenting.
But at the same time, I see lots of uses of declarative and functional programming, where most things are built up from concepts defined earlier on.
We can assume that code like https://github.com/pkobrien/cad/blob/master/src/cad/mesh/polyhedron.clj is unavoidable...
I don't know what I should expect! If you're defining an icosahedron, why not as a nested array of vertices of faces?
It seems like it would be hell to edit, but once you get it right, it's not like the definition of an icosahedron is going to change.
I was just joking about the "sea of letters" effect.
And I'm definitely not usually in the business of analyzing people's personality based on their coding style; although maybe I could pick up some spare change running a fortune-telling booth at conventions.
"You put whitespace inside your parentheses... you will go on a long journey soon."
here's a transducer with distinct
:
(defn normal
"Returns the normal for the vertex as the average of the face normals."
[mesh vert]
(let [face-normal-map (mp/face-normal-map mesh)
vert-faces-map (mp/vert-faces-map mesh)
xf (comp (map face-normal-map) (distinct))
vnorm (fn [vert]
(->> (vert-faces-map vert)
(transduce xf + (mc/point 0.0 0.0 0.0))
(mx/normalise!)))]
(vnorm vert)))
Anyway, my test data generation is working and my tests are passing—so I'm going to sign off and enjoy what's left of the weekend! Tomorrow it's back to making cards happen.
Thanks for the advice.