Fork me on GitHub
#clojure
<
2015-06-11
>
bg05:06:38

Got bitten by http://dev.clojure.org/jira/browse/CLJ-1465 Has anyone used core.rrb-vector in production?

danielcompton06:06:58

@bg the behaviour doesn’t seem too surprising to me, considering its using persistent shared data structures

bhagany06:06:41

@bg - not production, but it has been solid enough for me to recommend that you give it a try

bg07:06:35

@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. simple_smile

bg07:06:15

@bhagany: thanks. we are going to take it for a spin soon. And knowing Michal I know it can't be too bad simple_smile

pastafari07:06:42

@bg: do you want subvec to be O(1) or not simple_smile

bg07:06:05

@pastafari: I want it to be better than O(n) simple_smile

pastafari07:06:37

@bg: that sounds difficult, considering you need to construct a new subvector

bg07:06:18

@pastafari: core.rrb-vector can do it in O(log(n))

pastafari08:06:37

@bg: ack, but its a fundamentally different data structure. The bug reporter seems to want the same from PersistentVector

honza10:06:04

Does anyone have a link to some words about ring’s use of threads? Defaults, pool sizes, how many per request, async settings, etc

tcrayford10:06:19

@honza: that depends on which server you're using right? If you're using jetty, then I can point you at a thing…

tcrayford10:06:00

@honza: ring doesn't talk about threads at all, it's just a standard that uses synchronous function calls and maps

tcrayford10:06:22

@bg: meanwhile yeller explicitly depends on that subvector behavior for core performance concerns… welp

honza11:06:01

@tcrayford: ah, very helpful — that’s perhaps the reason why I couldn’t find anything. Will you point me at the jetty thing?

tcrayford11:06:09

depends which jetty version you're on…

honza11:06:48

I’m looking for an intro simple_smile

tcrayford11:06:18

hah. I've only like, looked at the clojure code that calls it and the javadoc on the jetty side…

borkdude11:06:35

What are good reasons to migrate a 'normal' ring/compojure application to Pedestal - or start your next project with Pedestal?

tcrayford11:06:38

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

borkdude11:06:08

@tcrayford: why exactly? and can't you use Pedestal's routing as a library?

tcrayford11:06:09

@borkdude: you cannot, sadly 😕. It's tied into interceptors and dispatch etc

borkdude11:06:31

@tcrayford: I see, so Pedestal is a framework? simple_smile

tcrayford11:06:48

hahaha, yeeeup

tcrayford11:06:54

no databas there though

borkdude11:06:40

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?

tcrayford11:06:02

@borkdude: yeah. The end of the request cycle is just a ring handler, so no reason liberator can't slow in there

tcrayford11:06:10

(I mean, it's a thing that looks exactly like a ring handler)

borkdude11:06:30

(fn [req] ... response)

tcrayford11:06:52

@borkdude: yeah, exactly. Middleware is different - they have an approach that allows for async middleware

tcrayford11:06:27

@honza: I just googled "jetty 9 threading model", you can prolly learn a bunch off there

borkdude11:06:35

@tcrayford: I'm kind of a n00b in the async web server things. What would be a good use case for it?

tcrayford11:06:17

@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)

honza11:06:18

@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.

tcrayford11:06:38

@honza: guess that's it then. It's like rack or wsgi

borkdude11:06:59

@tcrayford: I'll look at the sample of server sent events in Pedestal, thanks

tcrayford11:06:00

the servers it sits on are nearly all java servers (even httpkit iirc is mostly java), so their docs are appropriate

tcrayford11:06:13

@borkdude: I honestly don't care about the async stuff at all though 😉

tcrayford11:06:21

(but that's more to do with my use cases etc)

borkdude11:06:28

@tcrayford: me neither, but always good to learn about it

tcrayford11:06:36

@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

malcolmsparks11:06:22

same goes for bidi, which is a radix-tree like pedestal

malcolmsparks11:06:30

(or so I believe)

malcolmsparks11:06:31

bidi's routing is heavily influenced by pedestal, but I was frustrated that pedestal combines everything in one, that feels so wrong to me

malcolmsparks11:06:07

@tcrayford: would be interested to know what you like about pedestal's routing and dislike about bidi's

tcrayford11:06:34

@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)

malcolmsparks11:06:14

@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

malcolmsparks11:06:59

I agree that the debug needs a lot of improvement

tcrayford11:06:18

@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.

malcolmsparks11:06:32

I've never considered giving bidi a flat structure and having it create the tree, that's an interesting idea

tcrayford11:06:58

it just is a tonne easier to construct, and likely the debug messages could be a bunch better

tcrayford11:06:49

@malcolmsparks: keep in mind, this is me trying to convert Yeller, which has ~100 routes in play

malcolmsparks11:06:46

@tcrayford: if you already have 100 routes you need to convert, I can see the advantage to having bidi construct the tree for you

malcolmsparks11:06:09

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

malcolmsparks11:06:41

also, having to specify the tree upfront in bidi means you can wrap parts of the tree in middleware etc.

malcolmsparks11:06:10

if you had flat routes you might have a lot of duplication

tcrayford11:06:21

I'm down with duplication if it leads to clarity

malcolmsparks11:06:32

if you need clarity, you can always 'denormalise' the bidi structure into flat routes

malcolmsparks11:06:26

that's a new feature in bidi recently

malcolmsparks11:06:28

it's called route-seq

malcolmsparks11:06:41

you call route-seq on your bidi structure, much like you'd call tree-seq

malcolmsparks11:06:50

and you get a sequence of routes back

malcolmsparks11:06:56

useful for sitemaps and stuff

malcolmsparks11:06:12

there - the documentation is in slack!

bg11:06:06

@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:

tcrayford11:06:04

@malcolmsparks: yeah. I much prefer editing a seq structure to a tree structure. "flat is better than nested" and all that

malcolmsparks11:06:19

@tcrayford: i'm not sure 'flat is better than nested', who said that? happy to be persuaded

malcolmsparks11:06:27

trees compose nicely

malcolmsparks11:06:42

modularity and all that

tcrayford11:06:05

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

dialelo11:06:25

i think they were referring to source code layout, not data structures

malcolmsparks11:06:32

if it is, I better understand why

tcrayford11:06:03

dialelo: yeah. Bidi's data structure basically is source code from some perspectives

mikethompson11:06:30

It was Tim Peters (zen of python). He was referring to trees of Classes.

malcolmsparks11:06:35

I'd still like to understand the reasoning, even as a source-code thing

mikethompson11:06:28

Smalltalk (which was the gold standard OO language of that time) has an especially deep tree of classes

tcrayford12:06:20

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)

malcolmsparks12:06:37

shouldn't that be deep 'graph' of classes - trees are a lot nicer than graphs

malcolmsparks12:06:15

slack isn't helping with that one

tcrayford12:06:22

yeaha ahahaha 😕

tcrayford12:06:56

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

malcolmsparks12:06:04

slack badly needs a paredit mode

tcrayford12:06:16

(I prolly really fucked up the parens 😕 )

malcolmsparks12:06:30

@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

martinklepsch12:06:34

(you can do code blocks as in Github Markdown fwiw)

tcrayford12:06:15

@malcolmsparks: consider that a super strong +1 from me then 😉

tcrayford12:06:36

@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)

malcolmsparks12:06:58

that'll need some hammock time, so will get fixed at the usual bidi issue resolution speed

malcolmsparks12:06:24

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

tcrayford12:06:51

@malcolmsparks: yeah totally agree with that

Lambda/Sierra12:06:53

Shouldn't that be a "long cons"?

tcrayford12:06:58

@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

dmich12:06:15

@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)

slipset12:06:12

I deffo prefer the first one, since then I can easily test the functions in isolation

slipset12:06:25

and I might also reuse them a bit.

slipset12:06:06

Also, I get two kinds of functions, those which do someting (the foos) and those which compose things (the do-the-things)

slipset12:06:30

I guess the do-the-things could easily be written as

slipset12:06:09

(def do-the-things (comp foo3 foo2 foo1 ))

tcrayford12:06:15

@slipset: thanks for the formatting heads up simple_smile That's a dumb example of "flat is better than nested", but it scales a bunch

dmich12:06:16

well, i couldn't tell what the heck he was talking about when formatted as he intially posted it 😛

tcrayford12:06:31

apologies 😞

slipset12:06:51

That was not me suggesting the formatting.

dmich12:06:51

(you have to use Shift-Enter to insert newlines, instead of posting message btw)

tcrayford12:06:41

that's a lot better

gerrit12:06:45

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

arcdrag13:06:09

Does anyone happen to know the reason for preferring nil-punning over (when-not (empty? my-coll) ...) in the clojure style guide?

arcdrag13:06:32

I feel like the latter is easier to read.

tcrayford13:06:50

@arcdrag: I much prefer the latter as well. Think the community consensus is just "wrong" on that 😞

arcdrag13:06:04

So it is just purely a matter of style? There's no technical reason for one over the other?

curtosis13:06:57

I think it’s mostly consistency…. nil punning is idiomatic in (or ….) constructions, for example, so the extra empty? breaks the pattern.

sveri13:06:34

@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) 😄

dnolen13:06:39

@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.

arcdrag13:06:01

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.

dnolen13:06:25

@arcdrag: idioms are idioms, (seq …) is in fact plain English for Clojurians simple_smile

curtosis13:06:29

☝️ both simple and easy, in the parlance of our times...

dnolen13:06:04

Nothing against Gary but I agree with very few things he’s ever said simple_smile And especially when it comes to Clojure.

tcrayford13:06:46

oh, was more pointing at the resulting discussion, alex had some good links in there

dnolen13:06:53

ah right thanks

tcrayford13:06:30

(think y'all agree to disagree on language design, and that's just fine)

arcdrag13:06:10

Similar discussion, which would be preferred? (remove nil? ...) or (filter identity ...)

ul13:06:00

they act differently

ul13:06:16

filter identity will remove false

ul13:06:24

together with nil

arcdrag13:06:33

Ahh, true. I missed that.

tcrayford13:06:35

I think you nearly always want (remove nil?), and it reads better

micha13:06:10

(keep identity ...)

arcdrag13:06:06

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 simple_smile

escherize14:06:28

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?)

jeff.terrell14:06:59

That’s usually what I do, FWIW.

tsdh14:06:26

Don't macros support :arglists metadata? At least defining (defmacro ^{:arglists '([[x y]])} foo [p]) will show the argument vector [p] in (doc foo)....

tsdh14:06:13

Hm, what works is using the optional attr-map, though, e.g., (defmacro foo {:arglists '([[x y]])} [p] ...).

Lambda/Sierra14:06:33

(keep identity) will also remove false

jeff.terrell14:06:27

@stuartsierra: Did this change recently? I’m seeing it keep false but remove nil in clj 1.6.0.

Lambda/Sierra14:06:32

oh, sorry, I was thinking of (filter identity)

ghadi14:06:55

just to add to the mix, now there is some? as well

wuzhe15:06:32

does this slow the chat room a little bit?

akiva15:06:41

@wuzhe: Using pseudocode? Nope, not at all.

vramana16:06:56

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.

aaronm16:06:19

you’ve got the core of what you need — you can start off interactively by doing lein repl

akiva16:06:48

@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.

aaronm16:06:50

or lein new to start a formal project. for other tooling, it depends on what you want to use; different editors and such

vramana16:06:10

I use atom as my editor. I don't want to play in repl. I want to write in file and execute it

aaronm16:06:53

here’s a simple setup, then: lein new app blah will create a new project folder called blah.

escherize16:06:22

And you know what you're missing without using a repl?

aaronm16:06:29

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.

aaronm16:06:51

by the way, we also have a #C053AK3F9 channel here that you might find helpful.

masonbrowne16:06:24

@vramana: I was an unbeliever until I experienced a connected repl. .

vramana16:06:00

@masonbrowne: I have spent half a day trying to setup sublime repl thinking it would be easy.

aaronm16:06:13

I’ve been repl-obsessed since I started writing python in 1999 or so

vramana16:06:30

so at this point I am happy if I can get a small program running

vramana16:06:50

and I want to eventually use a repl that live reloads my programs

aaronm16:06:58

@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

masonbrowne16:06:11

@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.

vramana16:06:41

@aaronm: I tried LightTable but for some reason it didn't work for me.

masonbrowne16:06:46

@aaronm: I wish I had been so enlightened so early 😞

aaronm16:06:50

when you get comfortable with the language and want to deal with editor integration, there’s an #C050AN6QW channel here as well

vramana16:06:38

But LightTable development seems to be abandoned these days.

masonbrowne16:06:46

@vramana: I bet folks in the #C053AK3F9 channel would have a bunch of good resources for you

sveri16:06:15

@vramana please try to get lighttable running, especially for learning it is incredibly useful

markstang16:06:17

@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.

vramana16:06:54

@markstang: Probably that is what I was missing

vramana16:06:39

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

markstang16:06:33

@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.

markstang16:06:01

In theory someone is still maintaining it, just not doing releases all that often...

hlship18:06:33

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?

hlship18:06:59

Correction: seems to work for lein repl, but not lein figwheel.

borkdude18:06:27

@hlship: if in doubt you can chain tasks with 'do' maybe?

borkdude18:06:45

aliases {"build" ["do" "clean" ["cljsbuild" "once" "prod"] "uberjar"]})

borkdude18:06:43

@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

borkdude18:06:07

don't know if it's the same problem though

hlship18:06:53

@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.

borkdude18:06:50

@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/

borkdude18:06:44

@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

jonpither19:06:56

how do you copy files in boot?

borkdude19:06:38

@jonpither: try in #C053K90BR and I think the sift task may do that

jonpither19:06:56

I move stuff using sift but haven't managed to copy

borkdude19:06:48

@jonpither: sorry, it was just a wild guess, haha simple_smile

jonpither19:06:02

good guess tho

jonpither19:06:55

boot is an impossible thing to search for

sveri19:06:38

it is easy to use boot in cursive, just like @borkdude said, a deps only project.clj is enough

sveri19:06:48

apart from that, boot still does not work on windows -.-

sveri19:06:03

ok, and src folder declarations are needed

seancorfield20:06:50

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"?

seancorfield20:06:30

(I didn’t try (.-x this) but I assume that’s legal?)

donaldball20:06:02

I exclusively use plain ol' x inside methods myself

arrdem20:06:08

.-x is ClojureScript style… I don’t remember seeing it anywhere else first.

seancorfield20:06:26

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.

ghadi20:06:47

If we're talking from within the defrecord, no need for anything but what donaldball says

arohner20:06:03

@seancorfield: @arrdem: .-x was introduced in CLJS, because it can’t introspect to decide whether ‘x is a method or property

arohner20:06:29

therefore IMO, just use :x in CLJ, and .-x in CLJS

seancorfield20:06:28

(.-x this) works fine in CLJ and is portable to CLJS so...

arohner20:06:03

but it also breaks map-compatibility

arohner20:06:09

shrug tradeoffs either way

seancorfield20:06:22

Remember, I’m talking about inside method definitions inside a defrecord form. Not outside access.

seancorfield20:06:35

Outside I would use (:x thing)

seancorfield20:06:32

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?

rorydouglas20:06:00

@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

arohner20:06:28

@seancorfield: wow, I didn’t know you could access fields w/o this

donaldball20:06:43

I use _ unless I need to pass a reference to the record to someone

arohner20:06:59

I’ve always used this. I use _ when nothing refers to this

arrdem20:06:19

_ is a term you are discarding.

seancorfield20:06:27

Thanks @donaldball — my OCD doesn’t like a mix of _ and this across methods but I’ll think about it simple_smile

arohner20:06:53

@seancorfield: to me, _ is a hint “I won’t be doing anything with this in this fn"

seancorfield20:06:20

@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?" simple_smile

ghadi21:06:22

outside of a defrecord :foo something is optimized by the compiler with an inline cache

ghadi21:06:04

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

hlship23:06:16

@borkdude: Didn't fully resolve my problem, but have it working with some compromises and a lot of ugly warnings

bjarnagin23:06:55

can anyone describe what the advantage of using the :let modifier in the for function is, vs. just using let outside of the binding vector?

fhanreich23:06:23

you mean your let has nothing to do with items in the sequence in the for function?