This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-06-11
Channels
- # admin-announcements (96)
- # beginners (102)
- # boot (51)
- # clojure (234)
- # clojure-art (1)
- # clojure-berlin (6)
- # clojure-brasil (1)
- # clojure-china (1)
- # clojure-germany (24)
- # clojure-italy (25)
- # clojure-japan (22)
- # clojure-russia (85)
- # clojure-sg (3)
- # clojure-spain (6)
- # clojure-uk (7)
- # clojure-ukraine (3)
- # clojurescript (108)
- # code-reviews (11)
- # core-typed (3)
- # datomic (6)
- # docs (13)
- # editors (121)
- # euroclojure (10)
- # events (2)
- # jobs (7)
- # ldnclj (77)
- # off-topic (27)
- # reading-clojure (8)
- # reagent (27)
- # robots (2)
- # slack-help (22)
Got bitten by http://dev.clojure.org/jira/browse/CLJ-1465 Has anyone used core.rrb-vector in production?
@bg the behaviour doesn’t seem too surprising to me, considering its using persistent shared data structures
@bg - not production, but it has been solid enough for me to recommend that you give it a try
@danielcompton: Just 'cause it's using a persistent data-structure doesn't mean we can't get the rest of the vector GC'd. I am not asking for mutability, mind you.
@bhagany: thanks. we are going to take it for a spin soon. And knowing Michal I know it can't be too bad
@pastafari: I want it to be better than O(n)
@pastafari: core.rrb-vector can do it in O(log(n))
@bg: ack, but its a fundamentally different data structure. The bug reporter seems to want the same from PersistentVector
Does anyone have a link to some words about ring’s use of threads? Defaults, pool sizes, how many per request, async settings, etc
@honza: that depends on which server you're using right? If you're using jetty, then I can point you at a thing…
@honza: ring doesn't talk about threads at all, it's just a standard that uses synchronous function calls and maps
@bg: meanwhile yeller explicitly depends on that subvector behavior for core performance concerns… welp
@tcrayford: ah, very helpful — that’s perhaps the reason why I couldn’t find anything. Will you point me at the jetty thing?
hah. I've only like, looked at the clojure code that calls it and the javadoc on the jetty side…
What are good reasons to migrate a 'normal' ring/compojure application to Pedestal - or start your next project with Pedestal?
borkdude: the routing is the big deal for me. I like pedestal's routing a lot more than I like bidi and a bunch of other routers out there
@tcrayford: why exactly? and can't you use Pedestal's routing as a library?
@tcrayford: I see, so Pedestal is a framework?
I wonder if I'm going to bump into missing parts of that 'framework' when I would migrate. Is it easy to integrate liberator with Pedestal for example?
@borkdude: yeah. The end of the request cycle is just a ring handler, so no reason liberator can't slow in there
@honza: http://stackoverflow.com/questions/10587660/how-does-jetty-handle-multiple-requests https://wiki.eclipse.org/Jetty/Reference/Jetty_Architecture https://wiki.eclipse.org/Jetty/Howto/Configure_Connectors
@borkdude: yeah, exactly. Middleware is different - they have an approach that allows for async middleware
also see http://frankiesardo.github.io/posts/2014-12-15-give-pedestal-another-chance.html
@honza: I just googled "jetty 9 threading model", you can prolly learn a bunch off there
@tcrayford: I'm kind of a n00b in the async web server things. What would be a good use case for it?
@borkdude: server sent events is a big one, otherwise, you can service a tonne more concurrent requests in the right scenarios (I personally don't care about it)
@tcrayford: Yep, thanks! I already have like 20 tabs with stuff to read. I think the biggest issue was not understanding that ring is basically the protocol, or a spec for Clojure web apps.
@tcrayford: I'll look at the sample of server sent events in Pedestal, thanks
the servers it sits on are nearly all java servers (even httpkit iirc is mostly java), so their docs are appropriate
@tcrayford: me neither, but always good to learn about it
@tcrayford: thanks!
@borkdude: another thing is that the routing dispatch (as of pedestal 0.4.0) is much faster than compojure's - in compojure if you're dispatching to the bottom of the routing table, the time taken to find that route is O(N) where N = number of routes. In pedestal it's likely to be much faster than that. That does lead to some restrictions about what kinds of routes you can construct though
same goes for bidi, which is a radix-tree like pedestal
(or so I believe)
bidi's routing is heavily influenced by pedestal, but I was frustrated that pedestal combines everything in one, that feels so wrong to me
@tcrayford: would be interested to know what you like about pedestal's routing and dislike about bidi's
@malcolmsparks: I like that bidi is a library a whole bunch - imo that's the right approach. I didn't like the fact that issues and pull requests filed against it seemed to be ignored, and the error messages it spits out were gnarly and painful to debug. I also dislike that it required me to construct the tree myself - I just want to give it a flat table of routes and have it figure out the tree from there (pedestal allows this just fine)
@tcrayford: that's fair enough - issues and PRs don't get ignored completely, I do get round to them eventually, just slowly - apologies for that
I agree that the debug needs a lot of improvement
@malcolmsparks: yeah. I'm like that with Yeller's open source as well, no real problem with it, just means I'm less inclined to use it.
I've never considered giving bidi a flat structure and having it create the tree, that's an interesting idea
it just is a tonne easier to construct, and likely the debug messages could be a bunch better
@malcolmsparks: keep in mind, this is me trying to convert Yeller, which has ~100 routes in play
@tcrayford: if you already have 100 routes you need to convert, I can see the advantage to having bidi construct the tree for you
but I also think that it's a data transformation you could do separately - which is the joy of data structures in the first place
also, having to specify the tree upfront in bidi means you can wrap parts of the tree in middleware etc.
if you had flat routes you might have a lot of duplication
if you need clarity, you can always 'denormalise' the bidi structure into flat routes
that's a new feature in bidi recently
@malcolmsparks: any docs on that?
it's called route-seq
you call route-seq on your bidi structure, much like you'd call tree-seq
and you get a sequence of routes back
useful for sitemaps and stuff
there - the documentation is in slack!
@tcrayford: sure, if you are holding a ref to the root vector and want to pass around views the current behaviour of subvec
is :thumbsup:
@malcolmsparks: yeah. I much prefer editing a seq structure to a tree structure. "flat is better than nested" and all that
@tcrayford: i'm not sure 'flat is better than nested', who said that? happy to be persuaded
trees compose nicely
modularity and all that
one of the python folk when writing the zen I presume. Not about routing at all, but possibly the most important general design guideline ever, IMO
if it is, I better understand why
dialelo: yeah. Bidi's data structure basically is source code from some perspectives
It was Tim Peters (zen of python). He was referring to trees of Classes.
I'd still like to understand the reasoning, even as a source-code thing
Smalltalk (which was the gold standard OO language of that time) has an especially deep tree of classes
which is harder to understand: (defn foo1 [blah] stuff) (defn foo2 [blah] stuff) (defn foo3 [blah] stuff) (defn do-the-things [blah] (->> blah foo1 foo2 foo3)))
or (defn foo1 [blah] (foo2 (stuff blah))) (defn foo2 [blah] (foo3 (stuff blah))) (defn foo3 [blah] (stuff blah)) (defn do-the-things [blah) (foo1 blah)
shouldn't that be deep 'graph' of classes - trees are a lot nicer than graphs
slack isn't helping with that one
in one of them, there's three helper functions called by a main function, via ->>
. In the second example, the three helper functions call each other in a tree
slack badly needs a paredit mode
@tcrayford: arguments aside, if you feel editing a route structure as a table (let's call it that) rather than a tree, is a valuable thing to do, then there's an argument for bidi to support that use-case
(you can do code blocks as in Github Markdown fwiw)
@malcolmsparks: consider that a super strong +1 from me then 😉
@malcolmsparks: with that and error messages being better, I'd likely use bidi over pedestal (when I finally get round to having a real router rather than my current awfulness)
that'll need some hammock time, so will get fixed at the usual bidi issue resolution speed
for me, it's better that projects like bidi go slowly in the right direction than quickly in the wrong direction - clojure is a 'long con' for me
@malcolmsparks: yeah totally agree with that
Shouldn't that be a "long cons"?
teehee
@malcolmsparks: I've been holding off actually choosing a routing library for ~2 years now, and will likely carry on for now, given our discussion today. A long cons indeed
@tcrayford: Instead of
> Tom Crayford: which is harder to understand: (defn foo1 [blah] stuff) (defn foo2 [blah] stuff) (defn foo3 [blah] stuff) (defn do-the-things [blah] (->> blah foo1 foo2 foo3)))
or (defn foo1 [blah] (foo2 (stuff blah))) (defn foo2 [blah] (foo3 (stuff blah))) (defn foo3 [blah] (stuff blah)) (defn do-the-things [blah) (foo1 blah)
surround code with three backticks to get:
(defn foo1 [blah] stuff)
(defn foo2 [blah] stuff)
(defn foo3 [blah] stuff)
(defn do-the-things [blah] (->> blah foo1 foo2 foo3)))
or
(defn foo1 [blah] (foo2 (stuff blah)))
(defn foo2 [blah] (foo3 (stuff blah)))
(defn foo3 [blah] (stuff blah))
(defn do-the-things [blah) (foo1 blah)
I deffo prefer the first one, since then I can easily test the functions in isolation
Also, I get two kinds of functions, those which do someting (the foos) and those which compose things (the do-the-things)
@slipset: thanks for the formatting heads up That's a dumb example of "flat is better than nested", but it scales a bunch
well, i couldn't tell what the heck he was talking about when formatted as he intially posted it 😛
I'd also prefer the first version. if the composition part becomes too complicated I'd replace the comp/->> with a prismatic graph so you can name the intermediate results and with some graph-wrapping get all intermediate results when an exception occurs
Does anyone happen to know the reason for preferring nil-punning over (when-not (empty? my-coll) ...)
in the clojure style guide?
@arcdrag: I much prefer the latter as well. Think the community consensus is just "wrong" on that 😞
So it is just purely a matter of style? There's no technical reason for one over the other?
I think it’s mostly consistency…. nil punning is idiomatic in (or ….) constructions, for example, so the extra empty? breaks the pattern.
@arcdrag: @tcrayford (when (seq) has the advantage that your brain has no negation to evaluate, which is easier most of the times, at least that's why I prefer it ( as long as I don' forget about it) 😄
@arcdrag: I don’t see the point of typing all that when (seq …)
will do. empty?
does more in that it does redundant nil
check and then a seq
and boolean complement. if
+ (seq …)
just does all that right away.
I see that argument. Perhaps my preference is just a relic of my Java days where code that reads similarly to plain English was often considered cleaner, even if that involves extra work.
@alexmiller: wrote about it a bit here: http://insideclojure.org/2015/01/02/sequences/, and this tooter thread discussed it: https://twitter.com/garybernhardt/status/557287229941235713
Nothing against Gary but I agree with very few things he’s ever said And especially when it comes to Clojure.
oh, was more pointing at the resulting discussion, alex had some good links in there
Similar discussion, which would be preferred? (remove nil? ...)
or (filter identity ...)
One a side note, being a midwesterner working for a company based out of SF, it is really nice to have people awake to ask clojure-y questions to before noon
I'm on the fence between (remove nil?)
and (keep identity)
. I think if i want to filter out nils And I have a filter to do, I'll use keep. otherwise I'll explicitly use (remove nil?)
That’s usually what I do, FWIW.
Don't macros support :arglists
metadata? At least defining (defmacro ^{:arglists '([[x y]])} foo [p])
will show the argument vector [p]
in (doc foo)
....
Hm, what works is using the optional attr-map
, though, e.g., (defmacro foo {:arglists '([[x y]])} [p] ...)
.
(keep identity)
will also remove false
@stuartsierra: Did this change recently? I’m seeing it keep false
but remove nil
in 1.6.0.
oh, sorry, I was thinking of (filter identity)
Oh right.
Hey, I am new to clojure. Can somebody tell me how to setup the necessary tools ? I have setup leinengen so far. I don't know how to go from there.
you’ve got the core of what you need — you can start off interactively by doing lein repl
@vramana: That particularly depends on what you intend on doing. If it’s just to mess around with the language, then definitely lein repl
is the way to go.
or lein new
to start a formal project. for other tooling, it depends on what you want to use; different editors and such
I use atom as my editor. I don't want to play in repl. I want to write in file and execute it
here’s a simple setup, then: lein new app blah
will create a new project folder called blah
.
under there, src/blah/core.clj
has a main
function that will be run if you do lein run
, so that’s where you’d want to start editing.
@vramana: I was an unbeliever until I experienced a connected repl. .
@masonbrowne: I have spent half a day trying to setup sublime repl thinking it would be easy.
@vramana: if you’re not tied to Atom, you might consider Light Table, which will evaluate code in the editor, kind of like repl integration
@vramana: Yeah I think there’s definitely a set of tools that work well together, and a set of tools that takes a bit more work to get working. Coming at it from the latter angle can be a PITA.
@aaronm: I wish I had been so enlightened so early 😞
when you get comfortable with the language and want to deal with editor integration, there’s an #C050AN6QW channel here as well
Is this https://github.com/functional-koans/clojure-koans a good way to learn clojure ?
@vramana: I bet folks in the #C053AK3F9 channel would have a bunch of good resources for you
@vramana please try to get lighttable running, especially for learning it is incredibly useful
@vramana: I am still using Lighttable for both Clojure and ClojureScript. For Clojure it is great, just shift-ctrl-enter, the whole page is evaluated inline.
@markstang: Probably that is what I was missing
I was trying to figure out how to evaulate the page. I was trying to find something in menubar somewhere but I couldn't find it
@vramana: Yeah, the “list of executable functions” listed in ctrl-space is overwhelming. ctrl-enter will evaluate the current function. I usually comment everything out and start with the ns (ctrl-enter) and once that works, I work my way down the list of functions, uncommenting as I go. Once it is stable, then you can do the entire file. Just remember it is updating the global memory of the REPL so each time you execute a function it updates the global memory. And if you ctrl-enter a defn then it replaces the existing one in the REPL.
@markstang: Thanks!!
In theory someone is still maintaining it, just not doing releases all that often...
So, I'm not sure how to resolve this; how can I ensure that Java compilation takes place before another target (such as repl or figwheel)? How can I ensure that the target/classes folder is on the classpath at runtime?
@hlship: also, I had a problem recently when a target dir of mine was not on the classpath, because it didn't exist before leiningen started
@borkdude: I'll try this and see. This is when I really miss Gradle. I have high hopes for Boot once there's a way to support it inside Cursive.
@hlship: you can use them alongside I guess. Use a simple project.clj to inform Cursive about the deps and do your dev process with boot: http://blog.michielborkent.nl/blog/2015/06/06/from-leiningen-to-boot/
@hlship: however, boot is a bit new/experimental I guess, I ran into some issues before I got the same workflow as I had with leiningen
@jonpither: try in #C053K90BR and I think the sift task may do that
@jonpither: sorry, it was just a wild guess, haha
it is easy to use boot in cursive, just like @borkdude said, a deps only project.clj is enough
A question of style regarding defrecord
: if you have a field x
, you can access as plain ol’ x
inside methods, or you can use (:x this)
, or (.-x this)
— is there a consensus on which approach is "better"?
(I didn’t try (.-x this)
but I assume that’s legal?)
I exclusively use plain ol' x
inside methods myself
That’s what I’ve been doing but it occurred to me this
is somewhat redundant-looking in most methods and that sort of bothered me.
If we're talking from within the defrecord, no need for anything but what donaldball says
@seancorfield: @arrdem: .-x was introduced in CLJS, because it can’t introspect to decide whether ‘x is a method or property
(.-x this)
works fine in CLJ and is portable to CLJS so...
Remember, I’m talking about inside method definitions inside a defrecord
form. Not outside access.
Outside I would use (:x thing)
So I’m getting the impression that inside method definitions folks don’t refer to this
just to access fields of the record which answers my question. Do folks then use _
instead of this
in such methods?
@placeboza: re: Clojure games, checkout Nightmod: https://github.com/oakes/Nightmod there's a good intro from last year's Conj too: https://www.youtube.com/watch?v=0GzzFeS5cMc
@seancorfield: wow, I didn’t know you could access fields w/o this
I use _
unless I need to pass a reference to the record to someone
Thanks @donaldball — my OCD doesn’t like a mix of _
and this
across methods but I’ll think about it
¯\(ツ)/¯
@seancorfield: to me, _
is a hint “I won’t be doing anything with this
in this fn"
@arohner: I wrote direct field access in my first few records without thinking about it and it was only later I thought "Wait… shouldn’t I be using this
for field access?"
outside of a defrecord :foo something
is optimized by the compiler with an inline cache
so if something
is always the same record type it will be exactly equiv to a field access after the JIT is done with it
@borkdude: Didn't fully resolve my problem, but have it working with some compromises and a lot of ugly warnings