#clojure log - Sep 02 2014

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

2:40 xy86: is anyone using friend with luminus?

2:55 mi6x3m: clojure how do I get the namespace qualifier in e.g. foo/bar ?

2:58 ,(namespace 'foo/bar)

2:58 clojurebot: "foo"

2:58 mi6x3m: ,(namespace 'bar)

2:58 clojurebot: nil

2:59 celwell: Does anyone know what's wrong with my regex? I trying to grab every group of text between "Registration" words in a document. (re-seq #"Registration([.\s]*)Registration" text)

3:00 TEttinger: well \s won't work inside a character group, celwell

3:01 ,(re-seq #"Registration(.*)Registration" "Registration TEttinger celwell Registration")

3:01 clojurebot: (["Registration TEttinger celwell Registration" " TEttinger celwell "])

3:01 TEttinger: did you want to guarantee a space being at the end?

3:02 celwell: no

3:02 does your regex cover whitespace in the midst of each group?

3:02 hmm... i'm getting nil

3:02 TEttinger: do you want to grab those as separate things?

3:03 celwell: no, just the groups (the content between each pair of Registration strings)

3:03 TEttinger: ,(re-seq #"Registration(\s+\w+\b)+Registration" "Registration TEttinger celwell Registration")

3:03 clojurebot: nil

3:03 TEttinger: ,(re-seq #"Registration(\s+\w+\b\s*)+Registration" "Registration TEttinger celwell Registration")

3:03 clojurebot: (["Registration TEttinger celwell Registration" " celwell "])

3:03 TEttinger: oh, so you do just want the first one

3:04 or possibly re-find

3:04 ,(re-find #"Registration(.*)Registration" "Registration TEttinger celwell Registration")

3:04 clojurebot: ["Registration TEttinger celwell Registration" " TEttinger celwell "]

3:05 celwell: I have a long document of a bunch of registration info and each one starts with "Registration". I just trying to chunk it by registration and then I'll do further parsing.

3:05 the "Registration" words are on newlines (there are other whitespace characters in the midst of each chunk as well)

3:06 TEttinger: and you want to keep the whitespace right?

3:06 celwell: yeah

3:06 TEttinger: ,(re-find #"Registration(.*)Registration" "Registration TEttinger celwell\nRegistration")

3:06 clojurebot: nil

3:06 TEttinger: ah ha

3:06 ,(re-find #"Registration(.|\n*)Registration" "Registration TEttinger celwell\nRegistration")

3:06 clojurebot: nil

3:06 TEttinger: ,(re-find #"Registration((:?.|\n)*)Registration" "Registration TEttinger celwell\nRegistration")

3:06 clojurebot: ["Registration TEttinger celwell\nRegistration" " TEttinger celwell\n" "\n"]

3:07 celwell: ah...

3:07 TEttinger: dammit that's supposed to ignore the find....

3:16 celwell: TEttinger: hmmm... that stack overflows pretty soon on my machine. Maybe I can't use regexes to tokenize my data here...

3:19 TEttinger: Thanks for the help anyways.

3:20 TEttinger: Yeah, if you take the "Registration TEttinger celwell\r\nRegistration" string and copy/paste that about fifty times, it'll overflow

3:21 I guess that capturing group is recursive and piling up

3:21 TEttinger: hm, maybe... there could be a better way

3:27 got it, celwell: ##(re-seq #"Registration([^\000]*?)Registration" (apply str (repeat 100 "Registration TEttinger celwell\nRegistration")))

3:27 lazybot: ⇒ (["Registration TEttinger celwell\nRegistration" " TEttinger celwell\n"] ["Registration TEttinger celwell\nRegistration" " TEttinger celwell\n"] ["Registration TEttinger celwell\nRegistration" " TEttinger celwell\n"] ["Registration TEttinger celwell\nRegistration" " ... https://www.refheap.com/89683

3:28 TEttinger: that uses a negated character class and the (can't remember what it's called, opposite of greedy) star

3:29 minimal, that's what "*?" is

3:29 celwell: wow, thanks, works well.

3:30 TEttinger: no prob, I used http://www.regular-expressions.info/charclass.html#negated for all this

3:30 that site is pretty great

3:31 celwell: kind of weird how something this common (i think) requires a negated character class (but I guess there are other ways too)

3:38 TEttinger: celwell, there's an interesting thing on there about "Dot"

3:38 http://www.regular-expressions.info/dot.html "the most commonly mis-used character"

3:40 celwell: ah, of course it always comes down to this: "This exception exists mostly because of historic reasons"

4:19 borkdude: sorry if I could have found this in the paredit cheatsheet, but how do I swap/toggle two sexprs? like option-t in normal lines

4:19 in emacs

4:27 maxthoursie: borkdude: C-M-t

4:29 borkdude: an, transpose-sexp, thanks

4:29 sexps even

5:09 amalloy: TEttinger: pretty sure the better solution to celwell's regex problem was to turn on the "dot matches newline" flag, not a weird capturing group

5:10 TEttinger: amalloy, I didn't know about that flag

5:11 is it an optional arg in re-seq?

5:12 the weird capturing group will have the same behavior though, since \000 (NUL) isn't allowed in strings anyway

5:12 or it might be in java?

5:12 amalloy: you can pass any regex flag to Pattern/compile, or include it inline in the regex with the flag-activating syntax. eg, (?s) activates the S flag, which is dotall

5:13 er, ?s is single-line. dotall is in there somewhere

5:16 ,(re-seq #"(?m)Registration (.*)" "Registration TEttinger celwell\nRegistration foo")

5:16 clojurebot: (["Registration TEttinger celwell" "TEttinger celwell"] ["Registration foo" "foo"])

5:17 TEttinger: ?m eh? that's new

5:17 well to me

5:18 $mail celwell amalloy's better solution uses a regex flag that allows newlines as part of . matches. (re-seq #"(?m)Registration (.*)" "Registration TEttinger celwell\nRegistration foo")

5:18 lazybot: Message saved.

5:19 TEttinger: although he specified that the Registration might not be followed by a space

5:19 (might be tab or newline)

5:19 amalloy: TEttinger: (?m) is a specific case of the general turn-on-a-flag syntax, which works for all regex flags (eg, (?i) for ignore-case)

5:20 (?M) turns a flag back off

5:20 TEttinger: cool, I saw it but didn't recognize its use on that regular expressions site

5:20 what time zone are you in, amalloy?

5:21 amalloy: heh, my client refused your ctcp?

5:21 pacific

5:22 TEttinger: same here

5:23 SagiCZ1: hi, could u just hint me a little bit how to do this?

5:23 [:a :b :c :d] -----> [[:a :b] [:b :c] [:c :d]]

5:23 TEttinger: ,(vector (reductions vector [:a :b :c :d]))

5:23 clojurebot: [(:a [:a :b] [[:a :b] :c] [[[:a :b] :c] :d])]

5:24 TEttinger: uh that's not right :P

5:24 jkj: (partition-all 2 1 [:a :b :c :d]) ?

5:24 SagiCZ1: ,(partition-all 2 1 [:a :b :c :d])

5:24 clojurebot: ((:a :b) (:b :c) (:c :d) (:d))

5:24 TEttinger: ,(partition 2 1 [:a :b :c :d])

5:24 clojurebot: ((:a :b) (:b :c) (:c :d))

5:24 SagiCZ1: not bad

5:24 amalloy: partition, not partition-all

5:25 jkj: (mapv vec (partition 2 1 [:a :b :c :d]))

5:25 TEttinger: that too if they should be vectors

5:25 amalloy: or ##(let [xs '[a b c d]] (map list xs (rest xs))), just for fun

5:25 lazybot: ⇒ ((a b) (b c) (c d))

5:25 jkj: and this for vectors

5:25 SagiCZ1: but guys!

5:25 jkj: damn.. i have bound , to / in irssi

5:25 SagiCZ1: i wanted "a little hint" !

5:25 TEttinger: heheh

5:25 it's a little task

5:25 SagiCZ1: heh

5:26 TEttinger: the regexes were a legitimate hard problem because they involve leaving clojure land!

5:29 amalloy: note, by the way, that javascript doesn't support inline flags, so (?s) or whatever won't work in cljs

5:30 though i think if you put them at the very front of the regex, the cljs compiler magically moves them to the global flags section, turning #"(?s)foo" into /foo/s

5:41 SagiCZ1: do we have square root in clojure?

5:41 how can i static import it from Math? so i can use (sqrt 3) instaed of (Math/sqrt 3) ?

5:45 notofi: SagiCZ1: (def qrt [n] (Math/sqrt n))

5:47 hyPiRion: SagiCZ1: https://github.com/baznex/imports

5:49 wjlroe: Here's a bizare implementation of fizzbuzz https://gist.github.com/wjlroe/90b00fda936fd510ddd6 that I based on one my friend wrote in Go https://gist.github.com/jcinnamond/34177e064e861704ac81 It uses types rather than control structures, if anyone is interested

5:53 hyPiRion: peculiar

5:58 mpenet: "no control structures" but very "goto"'ish

5:59 wjlroe: yeah, it's just a bit of fun

6:00 hyPiRion: Ohhh

6:00 no control structures

6:00 wjlroe: Also, I tried doing the same thing in Rust, which was pretty tricky https://gist.github.com/wjlroe/dec2b2d198161b8454d0

6:01 hyPiRion: wjlroe: have you been working with Rust much?

6:02 wjlroe: hyPiRion, that gist is the sum total of my time with Rust. It really made my head hurt and I kept wishing it was Haskell

6:02 mpenet: I dabbled a bit with rust as well

6:03 wjlroe: I would like to do more Rust but I don't have a suitable project for it at the moment.

6:03 mpenet: well, it's very different from haskell for sure. all the ownership/lifetime stuff for instance

6:04 wjlroe: I don't know about that, but it seems to want to be a faster more low level language

6:04 mpenet: yes

6:05 C with cool compile time stuff to prevent common mistakes, more or less

6:05 nice language imho

6:05 wjlroe: Like Go but with a better type system

6:06 mpenet: and no GC :}

6:06 hyPiRion: yeah, it feels like a sane C++ with guard rails for bad memory management

6:06 wjlroe: yeah that too

6:09 clgv: a statemachine for fizzbuzz? :P

6:09 wjlroe: yup. I hope that in the future I can come up with even more outlanding ways to do fizzbuzz

6:10 s/outlanding/outlandish/

6:10 clgv: wjlroe: how about a concise clojure version with "cond->" ? ;)

6:10 wjlroe: Too sensible

6:11 Fizzbuzz isn't business logic, it's a way to express your creative side

6:11 clgv: ok then try a version with dependency injection based on spring ;)

6:11 wjlroe: That's more like it

6:11 clgv: "enterprise fizzbuzz" ;)

6:20 mavbozo: i'm trying to solve this problem http://www.4clojure.com/problem/95

6:21 about recognizing binary tree

6:21 so far, I only found the solution with using ordinary recursion

6:21 but it might blow up the call stack if the tree is too big

6:21 is there any solution using recur?

6:22 wjlroe: mavbozo, if you can use recursion then you should be able to use loop+recur

6:25 mavbozo: wjlroe: i try to solve using loop recur, but i'm having trouble on putting the recur in tail position

6:26 wjlroe: mavbozo, oh. so your recursive solution didn't tail recur? Ok.

6:28 mavbozo: wjlroe: yes, i did not use recur at all in my first solution

6:29 clgv: mavbozo: well it cant blow the stack on the examples there - except you are running it on some kind of microcontroller ;)

6:33 mavbozo: clgv: yeah, but i can't help think about it. As I recall from my courses years ago--when using common lisp or scheme/racket, using recursion is a straight forward solution and I don't have to think about blowing up the stack because the compiler do some tail-recur optimization. But, now in clojure I have to think hard about it.

6:34 clgv: mavbozo: no you only have to think about it, when you have large data that causes large stack consumption. otherwise you couldnt use recursion in java at all ;)

6:47 mavbozo: btw it's not true that you dont have to think hard - in both cases the hard part is to come up with a tail recursion

6:48 the difference in clojure is that you explicitely declare it as tail recursion by using `recur`

6:53 hhenkel: Hi all, I got currently a hard time to change some code I wrote 2 months ago and I haven't touched clojure since then. Can someone please give me a hint how to change this code: https://www.refheap.com/89693 that it is not returning a vector but a hash-map with "unique" id?

6:54 mavbozo: clgv: i see what you mean. i find it hard to find the tail-recursion's solution.

6:54 hhenkel: I'm aware that I need to change the (vec), but I'm currently not getting how to have something like a counter added to the (hash-map) as a key.

6:56 clgv: mavbozo: for problems that are not inherently tail-recursive the general solution is to build the "stack" on the heap

6:58 mavbozo: clgv: so this binary-tree recognition is not naturally tail-recursive?

6:59 clgv: mavbozo: yeah, it is not. since you usually need to perform a recursive call for each branch of a node

7:00 mavbozo: but you can maintain a list of branches to investigate and thus make it tail-recursive

7:05 mavbozo: clgv: thank you for your explanation and suggestion

7:14 Duke-: hhenkel: this might work https://www.refheap.com/89697

7:15 clgv: Duke-: hhenkel: zipmap

7:15 (zipmap (range) (for ...))

7:16 Duke-: oh yeah

7:41 hhenkel: clgv: Thanks.

7:41 Duke-: ^^

8:11 Kneiva: wjlroe: http://thedailywtf.com/Articles/The-Fizz-Buzz-from-Outer-Space.aspx

8:14 bounb: ha

8:14 wjlroe: Kneiva, I haven't read dailywtf for years since it's a bit too close to reality for comfort

8:15 Kneiva: just thought it funny that you were talking about fizz buzz today and that just published

8:17 wjlroe: Totally, and that is the best logarithm I've ever seen

8:17 Kneiva: =)

8:18 wjlroe: I mean we laugh now, but in several hundred years these scraps of notepaper will be like Fermat's last theorem

8:18 mavbozo: i thought that fizbuzz solution without control structure is outer-space enough,then comes a solution only using arithmetic operators

8:20 clgv: I heard a salesguy advertise his project when he started talking of the clever "alogarithms" involved - a verbal typing error ;)

8:20 *product

9:30 lvh: Hm. I wrote a functio nwith a default argument (w/ destructuring), but it doesn't appear to compile, and I can't figure out why.

9:30 https://gist.github.com/lvh/4fb459d55f2e541765e3#file-fn-clj-L13

9:30 the arg line is [components & {:keys [dev-mode] :or {dev-mode false}}]

9:30 justin_smith: lvh: you provided the wrong number of arguments

9:31 lvh: justin_smith: this is one of those cases where you wonder about it for 15 minutes

9:31 then you ask, and suddenly realize, OH right duh.

9:31 justin_smith: so you figured it out? - that function as defined will always need an odd argument count

9:32 lvh: justin_smith: Yeah. I was passing dev-mode positionally, and expecting it to work anyway.

9:32 (Python leftover I guess)

9:32 justin_smith: positional: [components & [dev-mode]]

9:32 that will default to nil

9:32 which is as good as false, usually

9:39 lvh: hm. are let blocks supposed to work inside compojure routes?

9:39 (It seems they don't: only the last block works)

9:39 err, route

9:40 clgv: lvh: where do you put the let-block?

9:40 lvh: clgv: inside a context

9:41 clgv: lvh: well I guess the simple rules is, they are supposed to work everywhere where abody expr processing the request is expected

9:43 lvh: https://gist.github.com/lvh/dc967bc751edc30f429a

9:43 I hope that clarifies intent :)

9:43 I do think I understand why it doesn't work, yes

9:44 (not really side-effectful: just a macro that sees what children it has)

9:45 visof: hi

9:46 bounb: hi visof

9:47 clgv: lvh: remember that `let` does only return the result of the last form!

9:48 lvh: hence your GET is lost

9:49 lvh: you could have a look at how `context? works and build a different version that does not expect multiple routes but a list of routs

9:49 `context` ^^

9:54 doctorm: New to clojure, can someone tell me if this function is idiomatic or if it’s still has imperative feel - https://www.refheap.com/89701

9:54 mi6x3m: doctorm: welcome, sec

9:56 doctorm: it can go a lot shorter :)

9:56 i mean, it's idiomatic but nobody will write it that way

9:56 doctorm: mi6x3m: Thanks, would you mind telling me how?

9:56 mi6x3m: yes

9:56 doctorm: That’s what I was worried about

9:56 mi6x3m: 2 good ways

9:57 (<= low (count (str v)) high)

9:57 samflores: I think even in a non-functional using a if-else to return a boolean value is not idiomatic

9:57 wjlroe: doctorm, one point - (if condition true false) is the same as just condition

9:57 samflores: just return the value of the condition

9:57 doctorm: Well, there is a nil check there too

9:57 TimMc: mi6x3m: Are you saying to drop the ability to use nil bounds?

9:57 mi6x3m: ok, my bad :)

9:58 skipped the nil bounds visually

9:59 doctorm: samflores: Right, the if could definitely be gotten rid of entirely

9:59 mi6x3m: doctorm: well except for the if, seems ok

9:59 pretty ok

10:00 samflores: i'd put the string as the first parameter too, but it's just matter of taste :D

10:00 clgv: huh metrics-clojure has `start`/`stop` for timers in its docs but they do not seem to exist

10:01 maxthoursie: doctorm: the docstring goes before the args

10:01 doctorm: Ok, thanks for the spot check everyone. samflores: I don’t put the string as the first parameter because I need to use it with partial

10:01 maxthoursie: Missed that, thank you

10:01 karls: doctorm, mi6x3m, could you do something like (<= (or low 0) cnt (or high Integer/MAX_VALUE)) ?

10:01 samflores: it makes sense

10:02 TimMc: clgv: There are a few places the docs don't match.

10:02 The params for meter and defmeter are wrong as well.

10:02 clgv: TimMc: do you know if I can achieve that intended use case somehow else?

10:02 lvh: clgv: will do :) my first guess involved apply

10:03 clgv: doesn't work so well with macros unfortunately

10:03 clgv: lvh: ;)

10:03 maxthoursie: doctorm: and for future if statements, put the else on a new row

10:04 doctorm: maxthoursie: Will do, thanks

10:04 maxthoursie: doctorm: what seems to be ideomatic is to either put all arguments on one line, or to put all of them on new lines

10:04 clgv: TimMc: ah might be a versioning problem. latest master has thos functions

10:06 maxthoursie: karls: I think that's worse, you're introducing a unneccesary limit

10:08 TimMc: clgv: I suspect you can just call .start and .stop directly. :-)

10:10 karls: maxthoursie: true. depending on the context i would think it's ok.

10:11 clgv: TimMc: almost. it's `.time` and `.stop`

10:12 maxthoursie: karls: definitely could be, but wrapped up in a function like this, I would argue it's incidental complexity

10:13 lvh: When I use http-kit's server, it's awfully quiet. What's the easiest thing I can do to get some logging on stdout/err?

10:14 karls: maxthoursie: agreed. saving a few lines and introducing that limit is probably not worth it.

10:21 justin_smith: lvh: you could make a middleware that logs details about the request

10:58 lvh: tbaldridge: hi! just subscrubed to your pivotshare videos. Cool stuff :)

10:58 tbaldridge: I know you're probably swamped with requests, but have you done anything on core.async http *servers*?

10:59 the obvious thing is http-kit, but http-kit's server interface (being borrowed from ring) is either a) synchronously return a response (map) or b) use this channel abstraction that isn't core.async channels and ignores middleware

10:59 tbaldridge: lvh, I haven't yet, but I'll put it on the list

10:59 lvh: tbaldridge: Awesome, thanks :)

10:59 tbaldridge: lvh: right, while Pedestal supports full async from top to bottom. It'd be nice to compare/contrast the two

10:59 lvh: I may end up just trying to write a bunch of (thread ...) blocks in there

11:00 mpenet: shameless plug: https://github.com/mpenet/jet

11:00 it's jetty9 + core.async in short, has both client/servers

11:00 tbaldridge: mpenet: bookmarked, thanks!

11:00 mpenet: yw

11:06 lvh: mpenet: Thanks, that looks awesome!

11:07 rweir: mpenet, is jetty9 itself async, or is it getting wrapped in threads?

11:07 mpenet: it has an async api and it should be quite good at it

11:07 lvh: mpenet: I take it that means all my ring middleware Just Works(TM)?

11:08 mpenet: yes, the jetty-adapter is vanilla clojure adapter, the async part is done via the option map

11:08 rweir: ah nice

11:08 mpenet: so just change imports and your code works, then you can work on the ws part

11:10 lvh: mpenet: this is pretty cool; the thing I'm writing can essentially be described as "when a request comes in, do a ton of coordination based on ~20 other requests that you only find out at runtime"

11:10 mpenet: lvh: the tests for instance are basically a copy paste work from the jetty adapter that comes with ring + ws/clients tests

11:10 lvh: (i.e. I really really want core.async)

11:11 rweir: lvh, how're you liking c.a vs twisted?

11:12 lvh: rweir: it's like reinventing everything all over again ;)

11:12 sorry, not reinventing; discovering is the word I'm looking for

11:12 as in, I am trying to find out how to spell gatherResults

11:13 rweir: I think Clojure is a significantly better programming language than Python. Obviously Twisted has had some headway in terms of maturity.

11:13 rweir: Unfortunately my major gripe is the same: the default is blocking :(

11:15 pydave6367: lvh: How did you find the transition? Did you find any particularly good resources for someone coming from a Python background?

11:15 lvh: mpenet: So, I'm trying to figure out if this does what I think; does this mean that the ring handler can just return a channel that fires with a response map, instead of synchronously-a-response-map?

11:15 pydave6367: well, I used to be a schemer, so maybe it wasn't so hard for me :)

11:16 pydave6367: Sounds a better way to do it!

11:17 mpenet: lvh: yes kinda, if you look at the examples here https://github.com/mpenet/jet#websocket , the async handlers basically receive a map of 3 channels, one for input data, one for output (response) and a control channel (errors, deconnections)

11:18 lvh: so you have control at the rate of input from the clients via the :in channel, you can respond by putting stuff into :out and handle the rest via :ctrl. This plays nicely with core.async/alts!

11:18 lvh: mpenet: Gotcha. I am not trying to use websockets though; I just want to do regular HTTP requests with high concurrency and while the requests can potentially take a long time :)

11:19 mpenet: lvh: ah no, this is websocket only

11:20 lvh: mpenet: ah, alas :(

11:20 rweir: pydave6367, I've found 'joy of clojure' pretty good for me, coming from python - the biggest problems are that I can never remember how to destructure, and end up contorting my code to make the right thing end up as the final expression, until I remember I should just make more functions

11:22 lvh, have you used any mainstream-ish languages that make asynchronicity the default?

11:22 bounb: pydave6367: i'm loving clojurebook.com. just forget about python and dive in

11:23 lvh: rweir: Erlang doesn't count I guess?

11:23 mpenet: js either

11:23 pydave6367: rweir: Yeah I've been burned by destructiring a few times too. I've been reading the oreilly book but I'll order a copy of Joy of CLojure based on your recommendation. Thank you!

11:24 rweir: lvh, mpenet ah, both good points

11:39 reiddraper: gfredericks amalloy: new test.check fun, a 'shuffle' generator: https://github.com/clojure/test.check/commit/43377ed0954e0066a4bbfb1345cf28af9d28312a

11:41 gfredericks: reiddraper: hey hey nice nice

11:41 reiddraper: shrinks toward making fewer and fewer swaps, so [0 1 2 3 4] when shuffled, might shrink to [1 0 2 3 4]

11:42 gfredericks: righto

11:42 I have a subset generator in test.chuck

11:42 ...not sure why I felt that necessary to mention

11:43 reiddraper: oh neat. would love a pull request.. uh, i mean. jira ticket, for that :D

11:43 gfredericks: subsequence might be more accurate

11:43 i.e. it doesn't really use sets

11:43 I used it just yesterday to generate divisors based on prime factorization

11:45 clgv: reiddraper: :D

11:57 noncom: when installing prelude on emacs, what is more common - to let it settle fully in .emacs.d, when init.el is the prelude init.el, or do i better keep it in a subdir of .emacs.d and simply refer it from my own main init.el ?

11:58 ToBeReplaced: noncom: the former

11:58 technomancy: noncom: I would really recommend building out your own init.el and stealing things from other sources as you find them. it's a lot less disorienting and more debuggable when things go wrong.

11:58 we get a lot of people in #emacs who are confused about basic behaviour because they installed a starter kit like the prelude and don't actually understand why it's working the way it does.

11:59 noncom: i see.. :)

12:01 ToBeReplaced: valid point from technomancy -- as the counterpoint, i was someone who "drank from the firehose", and now i do direct updates from prelude with no modifications... maybe depends on your learning style?

12:01 rweir: whoever wrote the emacs-starter-kit eventually just changed it to be a set of uh better defaults, also ;-p

12:02 technomancy: rweir: yeah that was me

12:02 * technomancy waves

12:03 rweir: yeah, I know :)

12:05 noncom: ToBeReplaced: yeah, i guess it really depends on the usage pattern

12:05 rweir: fwiw I would highly recommend writing your own init.el too

12:05 noncom: but good to know that people have opinions regarding these points

12:06 rweir: i have a long way to go until i really imagine what my init.el should be... for now i guess i am just collecting all kinds of i-might-need-this things..

12:06 in the init.el

12:07 TimMc: Latest thing I am happy with: ace-jump-mode

12:07 It's a little hard to explain.

12:07 ToBeReplaced: ha, yeah... i'm in the "all of these other people really care about their environment... i'll just do what they do"... and, prelude in particular has been really responsive about issues/prs so gradually i haven't needed anything in my own personal.el

12:08 my only unhappiness with it is how wide it makes the attack vector for reading my home directory

12:09 noncom: the ace-jump-mode i am reading is a nice nav aid

12:09 mi6x3m: nth doesn't work on sets wtf?

12:09 noncom: mi6x3m: sets are unordered?

12:09 mi6x3m: noncom: first and rest work.....

12:10 noncom: haha

12:10 tbaldridge: mi6x3m: what is nth on a unordered thing?

12:10 mi6x3m: tbaldridge: what is first on an unordered thing?

12:10 tbaldridge: mi6x3m: that's because first and rest convert their inputs into a ordered thing

12:10 mi6x3m: tbaldridge: oh?

12:10 justin_smith: lvh: I don't think it is that the channel returned by ring ignores the middleware, rather the middleware is not written to wrap channels. But you could write your own middleware that does. Or am I missing something?

12:10 tbaldridge: first and rest are seq functions used for walking through a collection. Nth is a indexed operation.

12:11 noncom: ToBeRaplaced: i guess i'll have to experiment with init el, yeah, since th etopic is soo vast

12:11 *ToBeReplaced: sorry for mistyping the nic..

12:11 mi6x3m: tbaldridge: what is then the impact of making a set a sequence?

12:11 so it can be destructured

12:11 negligable I would guess?

12:11 lvh: justin_smith: That was about http-kit, not ring

12:11 mi6x3m: since the order is pretty random

12:12 lvh: justin_smith: the docs for that don't seem to suggest that middleware can be rewritten to do better

12:12 tbaldridge: mi6x3m: yeah, most things in clojure can become seqs, it's basically an immutable iterator

12:12 mi6x3m: ye though so

12:12 lvh: http://http-kit.org/server.html#channel

12:12 justin_smith: lvh: I fail to see how you couldn't write a function that takes a channel and returns a wrapped / modified channel. And if you can write that function, you can put it in a middleware.

12:15 lvh: oh, now I see in those docs that ring middleware is not applied to the channel. But you could put your own middleware in the on-receive / on-close blocks

12:16 lvh: justin_smith: Yes, but: 1) I'm not actually sure that you can write it as middleware, but whatever, I can wrap it 2) the channel isn't actually the abstraction I want (it wants to do a bunch of back-and-forth req/rep pairs, which makes a lot of sense if you're doing websockets or long-olling RPC, but I'm not doing that) 3) that would mean doing a bunch of work when there's clearly already an abstraction that does *almost* exactly what I wnat

12:18 justin_smith: the http-kit thing is a red herring because it's about long-held connections with a lot of chatter back and forth, like long-polling, http streaming, websockets, whatever

12:18 I don't actually want that

12:18 justin_smith: regarding 1), a middleware is just a function that returns another function - you can put a middleware stack inside that block - regarding the rest, you know more about this api than I do, and I frankly expected something better from http-kit than what I see so far

12:20 lvh: I think the long-polling example *kind-of* does what I want

12:20 tbaldridge: lvh: just going to throw out there that this is what Pedestal was designed for, not so much for WS, but middleware can be paused/resumed via core.async, as well as the response body itself.

12:20 server sent events are supported though

12:20 lvh: tbaldridge: I'm actually in the super simple case of "I want all of the middleware all of the time"

12:21 really the only difference between what I want and what ring's API gives me is that ring wants me to say "here you go have a response map"

12:21 I wnat to say "here's a channel, I promise I'll throw a response map on there and then close it"

12:22 the long-polling example is nearly there, modulo the somewhat displeasing parts (1. ignoring middleware, 2. doing the rendez-vous between channels and open HTTP requests with shared mutable state)

12:23 but, in the same spirit as what justin_smith said, I don't want to accept that the answer is that terrible ;-)

12:23 maybe I should just give up and use pedestal :)

12:23 tbaldridge: lvh: that's a problem with the way ring is designed, it ties the call stack to the request/response logic. You can't suspend ring handlers and "run them later" because they already exist on the call stack.

12:24 lvh: tbaldridge: I am chuffed to see that rack/wsgi brain damage has made clojure worse, too ;-)

12:25 tbaldridge: lvh: yeah, I mean it's kindof sad. Jetty supports async, it's just ring doesn't.

12:26 There's a reason Pedestal was created, and you've now found that reason.... :-)

12:28 lvh: tbaldridge: It's unfortunate because I was getting to like wrap-reload & prone.middleware.wrap-exceptions

12:29 SagiCZ1: whats the best way to do simple if (..) else if (..) else if(..) else (..) in clojure?

12:29 cond has no default action

12:29 tbaldridge: lvh: yeah, Pedestal has a bit of a learning curve, but after you learn it there's some real "oh...wow... I can do that?" moments.

12:29 mi6x3m: SagiCZ1: cond has a default action

12:29 SagiCZ1: :else?

12:29 mi6x3m: SagiCZ1: yes

12:29 SagiCZ1: ,(boolean :any-keyword)

12:30 clojurebot: true

12:30 SagiCZ1: thats just a trick

12:30 mi6x3m: SagiCZ1: well, it wil be evaluated last...

12:30 so it's half of a trick

12:30 justin_smith: by using a test that is always true, you create a default branch

12:31 SagiCZ1: if it works.. ok

12:31 justin_smith: ,(cond false 0 nil 1 :default 2)

12:31 clojurebot: 2

12:31 clgv: ,(macroexpand-1 '(cond (zero? n) :1 :else :2))

12:31 clojurebot: (if (zero? n) :1 (clojure.core/cond :else :2))

12:32 clgv: ,(macroexpand-1 '(cond :else :2))

12:32 clojurebot: (if :else :2 (clojure.core/cond))

12:32 clgv: ah cond could get rid of the last `if` but it does not seem to do that

12:32 justin_smith: ,(macroexpand-1 '(clojure.core/cond))

12:32 clojurebot: nil

12:33 justin_smith: the last part is not an if

12:33 clgv: justin_smith: I didnt say so. I referred to the last `if`

12:34 justin_smith: oh, since it knows at compile time the arg is always truthy

12:34 clgv: does the clojure compiler eliminate `if` for always `true` or always `false`?

12:35 technomancy: clgv: no, but hotspot might

12:36 clgv: technomancy: right

12:36 technomancy: always forgetting that awesome beast ;)

12:50 SagiCZ1: i have kind of off-topic question.. do you have any idea how can i find out the shortest distance from polygon to a point? i have already worked out the shortest distance from a line segment to a point.. but dont know how to put it together

12:51 mi6x3m: SagiCZ1: 3d polygon?

12:53 SagiCZ1: 2d

12:54 justin_smith: treat the closest edge of the polygon as a line segment?

12:54 SagiCZ1: but how to determine "closest" edge

12:54 mi6x3m: SagiCZ1: is it convext?

12:54 -t

12:54 SagiCZ1: mi6x3m: not necesarrily

12:54 mi6x3m: SagiCZ1: well then find the distance to all edges and get the min

12:55 SagiCZ1: define "distance"

12:55 it cant be the perpendicular distance

12:55 justin_smith: if it was convex you could walk it until a side is closer than both neighbors, but with the ability to have a concave shape, you could have a local minima that is not the true minima

12:55 SagiCZ1: because then if the point is on the same line as the linesegment.. the distance is zero now matter how far it actually is from the polygon

12:55 mi6x3m: SagiCZ1: distance is usually the perpendicular distance

12:56 SagiCZ1: then the "closest" edge doesnt have to be close at all

12:56 the point could be infinitely far away.. just on the same line as the edge

12:56 mi6x3m: well then, try to find the nearest intersection point

12:57 by checking the distance to each vertex

12:57 SagiCZ1: interesection point of what?

12:58 mi6x3m: SagiCZ1: of a vector through your point with the polygon

12:58 SagiCZ1: vector through my point in question and where is the other point, center of polygon??

12:58 lazybot: SagiCZ1: What are you, crazy? Of course not!

13:00 mi6x3m: SagiCZ1: the other point is some point on the polygon

13:00 though the shortest distance will always be perpendicular to an edg

13:02 TimMc: mi6x3m: Not true.

13:02 SagiCZ1: i think i have an idea

13:02 maybe its what u meant

13:03 mi6x3m: TimMc: oh?

13:03 SagiCZ1: i will connect all polygon vertices with my point in question.. determine all intersections of those connections with polygon segments, and then find closest intersection to my point

13:04 TimMc: Yeah, think of a triangle. Think of infinitely long rectangles sitting on each of the edges.

13:04 Everywhere those rectangles do not cover, the shortest line to the polygon goes to a vertex, and is not perpendicular to an edge.

13:05 e.g. a point that the triangle is "pointing at"

13:06 SagiCZ1: mi6x3m was right earlier, though -- just iterate through the edges and find the one that has the shortest distance to the point. You can add in optimizations later.

13:06 SagiCZ1: TimMc: that wont work

13:07 TimMc: Provide a counterexample.

13:07 SagiCZ1: distance point - segment is the same as distance point-line .. therefore the point can be anywhere on the line which the segment lies on, to have a distance of zero

13:08 TimMc: Then you've defined distance-to-segment incorrectly.

13:09 SagiCZ1: define it differently then

13:09 noprompt: bbloom, dnolen_: for cljs macros that use macroexpand-1 should i be using the analyzers macroexpand-1 instead of clojure's?

13:10 TimMc: SagiCZ1: Perpendicular distance to the segment's line *if* the perpendicular crosses the segment, else distance to the nearest endpoint.

13:10 aperiodi1: couldn't you just find the two closest points and then check the segment in between those to see if that gets any closer than the closest point?

13:10 nope

13:10 nevermind

13:11 SagiCZ1: TimMc: sounds reasonable..

13:11 TimMc: i will try to implement that

13:12 TimMc: SagiCZ1: Are you sure you want to reimplement collision-detection or whatever it is you're doing, or would you rather use a library?

13:14 mping: hi

13:14 SagiCZ1: TimMc: yes im doing a simple collision detection.. it is an exercise and i will always have only 2 objects colliding, ball-ground.. i understand that there are libraries that handle this well and are better optimized then what i will end up doing... but since i use one of them (JBullet) regularly i would like to try how it works inside :)

13:17 mping: hi guys can you give me some pointers?

13:17 I want to calculate the intersection and difference of two lists of maps based on a given key

13:18 TimMc: mping: That could mean many things, can you give an example or a more specific problem statement?

13:18 mping: sure, in javascript:

13:19 suppose I have

13:19 v1 = [{name "a" val 1}, {name "b" val 2}]

13:19 v2 = [{name "a" val 3}]

13:20 I want to calculate the intersection based on the 'name' key

13:20 so (intersect v1 v2) would be {name "a" intersection [{name "a" val 1 } {name "a" val 3}]}

13:21 justin_smith: mping: group-by

13:21 mping: and (difference v1 v2) would be [{name "b" val 2}]

13:22 justin_smith: I have to group-by and process the aggregation by hand?

13:22 justin_smith: hmm - maybe not

13:23 mping: if I were doing this, I would take each collection, and run group-by based on the "name" key

13:23 then use select-keys / dissoc to construct the union and difference

13:23 mping: hmm didn't remember select-keys

13:25 maybe I can do two for's, so I know what's missing in where

13:26 doctorm: When you have a function that’s uses a map to declare symbols, like (defn foo [& {:keys [bar]}]), what is that called so I can read the docs on it?

13:27 noprompt: i just got totally bit by this https://gist.github.com/noprompt/acf7327ba3b874d25e59

13:27 justin_smith: mping: to get the union, take the union of the keys of each grouped-map from the vectors, and then merge the selected keys

13:27 noprompt: why does the clojurescript analyzer expand it differently

13:27 justin_smith: doctorm: destructuring

13:27 doctorm: justin_smith: thanks

13:29 TimMc: noprompt: Looks like it didn't get expanded at all.

13:29 noprompt: right?

13:35 SagiCZ1: ,(min (range 5))

13:35 clojurebot: (0 1 2 3 4)

13:35 SagiCZ1: why "min" hates lazy-seqs?

13:35 ,(min [0 1 2 3 4])

13:35 clojurebot: [0 1 2 3 4]

13:35 SagiCZ1: ,(apply min (range 5))

13:35 clojurebot: 0

13:35 SagiCZ1: ooooooh.. got it

13:36 justin_smith: if you provided a second arg after the sequence, min would have given you an error

13:36 SagiCZ1: ,(min [0 1 2] [3 4 5])

13:36 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>

13:36 justin_smith: but it has a shortcut to return the arg, if it only has one arg

13:37 SagiCZ1: justin_smith: what is that useful for?

13:37 justin_smith: it allows a concise implementation

13:37 $source min

13:37 lazybot: min is http://is.gd/uqY0Pg

13:40 technomancy: works for clojure too: http://thisotplife.tumblr.com/post/96352585529/using-erlang-for-a-one-off-script

13:40 justin_smith: hah

13:40 SagiCZ1: so how would a simple lighter look?

13:42 python?

13:42 clojurebot: yes let's have another dict subclass

13:42 SagiCZ1: hahahaha that bot cracks me up

13:43 TimMc: technomancy: I think OSHA would have something to say about that. Possibly "HRRRK!"

13:43 justin_smith: those machines are nothing to fuck around with - worked with a dude, someone tried to lift him out of a collapsed trench with the bucket, cut him in half

13:44 technomancy: TimMc: OSHA?

13:44 justin_smith: occupational safety and health administration

13:45 technomancy: hehe

13:46 justin_smith: as in "get down off the fork of that lift, or osha's going to hand me another $20,000 fine"

13:49 TimMc: They set regulations to keep employers from endangering their employees (or enouraging the employees to endanger themselves.)

13:50 Some of the regulations get a little silly, but on the whole they do good work.

14:02 stompyj: how do I start a repl on an interface other then 127.0.0.1

14:02 example, I want to connect to a repl running on an ec2 instance

14:03 but, lein repl only seems to be able to connect to ec2’s local network interface, which is an internal network

14:03 justin_smith: stompyj: use an ssh tunnel

14:03 unless you just want to share the ec2 instance with the entire world

14:03 TimMc: Or port-forwarding in the policies, which you really don't want in this case.

14:04 stompyj: I’d prefer to just open that single port, to the specific IP of this office

14:04 TimMc: (what justin_smith said)

14:04 stompyj: but yeah, I guess I’ll ssh in this case

14:04 a bit messy

14:04 but will work

14:04 amalloy: so much less messy than allowing arbitrary code execution on a public port, though

14:05 stompyj: 50/50 :D

14:06 justin_smith: stompyj: with port forwarding, you just run ssh in a terminal somewhere, and as long as that remains running, you can connect to the repl port as if it were local

14:06 stompyj: so, the answer is there is no way via command-line to tell lein repl to listen on an alternative interface?

14:06 justin_smith: stompyj: oh, you can make it listen to the whole world, it's just a terrible idea (nrepl that is - dunno if lein exposes the options)

14:07 technomancy: you can do it, you just shouldn't

14:07 TimMc: What would that look like?

14:07 technomancy: lein repl :headless :host 0.0.0.0

14:07 stompyj: yeah, that doesn’t work

14:07 thats what I was asking about

14:07 technomancy: or maybe LEIN_REPL_HOST=0.0.0.0 lein repl :headless

14:07 stompyj: it just defaults to 127.0.0.1

14:07 I’ll try LEIN_REPL_HOST

14:07 thanks

14:08 technomancy: wait did I say that out loud

14:08 TimMc: You were tricked!

14:08 stompyj: I hope you don't care about that box.

14:09 stompyj: lol thanks :)

14:11 justin_smith: I hope you expect everyone that accesses that box to get rooted

14:11 noprompt: i sincerely hate clojure's error messages.

14:12 Caused by: clojure.lang.ExceptionInfo: nth not supported on this type: Symbol at line 24 src/xyz/core.cljs

14:12 cbp: that looks like clojurescript man

14:12 noprompt: it is.

14:12 i want to help improve these kinds of messages.

14:12 justin_smith: also, "nth not supported on this type: Symbol" may be awkwardly worded, but the error is clear

14:13 noprompt: 9 times out of 10 whenever there's an error to be thrown there's enough context to be prescriptive about it.

14:13 cbp: I think you can just use the browser debugger there if you have source maps on

14:13 noprompt: justin_smith: i've been at this for two and a half years, i'm sorry that message is never clear.

14:13 i know what it means but it doesn't give me any hope of figuring out *why* that happened.

14:13 there's zero context.

14:14 amalloy: noprompt: really, a stack trace, error message, and exact line number is zero context?

14:14 noprompt: amalloy: i can't *see* the environment.

14:14 technomancy: the line number might even be correct.

14:14 lvh: hm, when I watched the video for prone this morning, there was an emacs plugin that auto-sorted the requires/imports in ns

14:15 any idea what that thing's called?

14:15 noprompt: amalloy: the line numbers help to a degree but there's a point when that's not helpful any longer.

14:15 technomancy: lvh: sounds like slamhound

14:15 amalloy: noprompt: if you pasted the stacktrace and the source file, i bet it would take only a minute or two for someone unfamiliar with your codebase to figure it out

14:15 lvh: technomancy: sounds dangerous; I don't want to be assassinated

14:16 noprompt: imho programmers don't know how to create constructive error messages. error messages are a form of communication and most programmers simply fail to communicate the nature of problems when they occur through error messages.

14:16 technomancy: amalloy: "only a minute or two" sounds like abysmally low standards

14:16 amalloy: technomancy: i gave myself some wiggle room

14:16 noprompt: this is because, again imho, programmers do no understand that an error message is a form of communication with the consumer of a library.

14:16 amalloy: i really expect it to take a lot less than that

14:17 stompyj: actually, it’s not really lein repl’s fault, ifconfig and netstat return crazytown data on ec2 boxes now that I’m looking at tit

14:17 it*

14:17 noprompt: often there is enough contextual information to *help* the programmer solve the bug but it's often elided because they don't realize they can actually help the programmer they're trying to communicate with because they've lived in a world where only shitty error messages are ever printed to the screen.

14:17 * noprompt steps of the soap box

14:18 technomancy: noprompt: you could try to improve it with nrepl middleware

14:18 lvh: huh, slamhound is a dep not a plugin

14:18 technomancy: fixing the root of the problem seems really unlikely, but you could route around the brain damage

14:19 stompyj: noprompt: You’re probably right, but that’s a very large problem to solve

14:19 noprompt: technomancy: that was actually the direction i was going next, but i had to rant first. :)

14:19 cbp: in cljs at least you get a pretty decent debugger for free

14:19 dbasch: to be fair, "nth not supported on this type: Symbol" could come from deep inside some library

14:19 lvh: technomancy: thanks!

14:19 stompyj: I don’t actually find clojure stacktraces to be as bad as people say

14:19 noprompt: stompyj: it's not just with clojure though, it's with almost every programming language, operating system, or application i've ever used.

14:19 amalloy: dbasch: but in practice it usually doesn't. almost always, it's because you forgot some square brackets somewhere in let or defn

14:20 stompyj: noprompt: yeah, I agree, I just mean, thats a HUGE problem to solve

14:20 once you dig into it

14:20 noprompt: my sister asked me the other day what "Error: 404 not found" meant. turns out she's not an http expert.

14:20 dbasch: amalloy: first google result: https://github.com/LightTable/LightTable/issues/51

14:20 cbp: parse errors are pretty brutal though

14:20 amalloy: oh, in ns. that's right

14:20 cbp: UNABLE TO FIND CLOSING TAG {

14:20 noprompt: stompyj: like i said though, often there is enough information available to provide i really decent error message that's helpful. this is especially the case in clojure with ex-info, &env, etc.

14:21 "really decent". wow. extreme decency.

14:21 dbasch: noprompt: but 404 is almost pop culture at this point

14:22 noprompt: dbasch: that's assumptive.

14:22 mdrogalis: noprompt: dbasch just dissed your sister. Oooo.

14:22 amalloy: noprompt: it seems totally absurd to say "error messages are really easy to get right, and yet weirdly all software in the world gets it super-wrong"

14:22 dbasch: noprompt: type 404 into google, or error 404

14:22 if pasting an error verbatim into google gives you what you want, then it’s decent enough imho

14:22 noprompt: dbasch: not to mention, from a UX perspective where you're trying to communicate with the user through a dialog it's especially poor form.

14:23 dbasch: noprompt: just playing devil’s advocate

14:23 noprompt: amalloy: i never said they were. i said they could be better. notably, i was suggesting they could be prescriptive more often than not.

14:24 for example "You gave me the wrong kind of input" could be stated as "You gave me this kind of input but I expect this kind of input."

14:24 amalloy: i don't think users would appreciate that. prescriptive error messages sound too much like sass. "mircosoft.com not found. Try browsing to a website that exists."

14:24 noprompt: and occasionally you get lucky and you get that from someone who gives a shit.

14:25 amalloy: i simply do not agree.

14:25 technomancy: racket does a great job with this

14:25 noprompt: i'm sorry debugging an error message has only gotten more annoying the longer i do this.

14:25 technomancy: the beginner languages suggest "maybe add more parens?" and the regular ones assume you know what you're doing.

14:26 dbasch: technomancy: make sure your cable is plugged in

14:26 noprompt: how long have people been writing software? is it so rediculous to expect better error message out of all the technical advances we've made in the last 20 years?

14:27 tbaldridge: noprompt: sadly every error message that contains "better" logic often also contains unknown assumptions.

14:27 dbasch: noprompt: to me an error message is not as important as the debuggability of the cause

14:27 noprompt: seriously. if as much effort was put into making debugging software as making writing concurrent software easier debugging would be a snap.

14:27 technomancy: noprompt: massive indifference is the easiest explanation

14:28 noprompt: technomancy: fair enough.

14:28 tl;dr how can i improve these messages?

14:28 tbaldridge: I'd also argue that hard-to-understand errors can be the side-effect of badly designed code.

14:29 is the message cryptic, or is my program so complex I can't understand where the message is from?

14:29 noprompt: tbaldridge: and i'd argue you always need context to make that call.

14:29 TimMc: tbaldridge: Such as Clojure's compiler making it difficult to distinguish compiler bugs from syntax errors?

14:29 Oh, you mean the code-base being developed.

14:30 noprompt: the problem i'm having is from a macro which, in one project compiles fine and in another explodes with an "nth on Symbol" error.

14:30 justin_smith: tbaldridge: part of this scenario in clojure has to do with our tendency to not validate our input, and just pass it to another layer of abstraction, until finally something in clojure.core or some java interop does the actual work

14:30 Bronsa: TimMc: how many actual compiler bugs have you encoutnered to make that claim?

14:30 noprompt: i've checked macroexpand from the repl in both projects and the generated code is *exactly* the same.

14:30 technomancy: GIGO is a pretty deeply-baked-in assumption in Clojure

14:30 tbaldridge: justin_smith: agreed, sadly doing anything more complex would hurt performance

14:30 noprompt: but something else must be happening in one project and not in the other and i can't *see* it.

14:30 technomancy: witness contains? being problematic for N years

14:30 xeqi: I've hit errors where the compiler provided no info on what was missing. I think ns A depends on ns B depends on ns C and C couldn't be found was one of them

14:30 justin_smith: tbaldridge: so the error report is only going to be about the implementation details of the code we call at the top level (or the implementation details of the thing it calls, etc.)

14:31 tbaldridge: well, we do have these assertions that can be turned off in production after all...

14:31 ToBeReplaced: isn't there a project from GSoC that set out to improve error messages?

14:31 noprompt: tbaldridge: this is not that complex https://github.com/spellhouse/clairvoyant/blob/master/src/clairvoyant/core.clj#L115-L124

14:32 dbasch: I remember wishing I had a camera to take a picture of Windows’ BSOD back in the 90s. That was as cryptic as it comes.

14:33 noprompt: tbaldridge: and like i said it compiles and runs fine in one project but not in another with *identical* code. same clojurescript version etc.

14:34 TimMc: Bronsa: I'd call it a fine line between GIGO and failture to check assumptions.

14:34 noprompt: justin_smith: +100 to what you just said.

14:34 about not validating input.

14:35 justin_smith: especially given that we have assertions we can turn off

14:35 TimMc: dbasch: Hah, yeah, remember not everybody having cameras 24/7?

14:36 noprompt: tbaldridge: the question i have to ask is, is clojure core satisfied with the state of error messages in the language?

14:36 dbasch: TimMc: no camera and no way to save the pertinent data other than painstakingly writing down hex strings

14:37 stompyj: noprompt: I don’t think any language is happy with the state of their error messages, but I think all the reasons people are giving you is why nothing has happened

14:38 tbaldridge: noprompt: I'm not a person who makes such decisions so I can't answer that question, sorry

14:38 noprompt: tbaldridge: personally, are you happy with them?

14:38 dbasch: stompyj: java is pretty decent in that sense compared to most other languages

14:39 TimMc: Java has great error messages, yeah.

14:39 tbaldridge: noprompt: as long as I get an error, yes. The worst errors are those that cause silent problems.

14:39 noprompt: iirc error messages were noted as a key pain point for many in the clojure community.

14:39 tbaldridge: maybe you just have thicker skin. :)

14:39 tbaldridge: noprompt: I'd prefer "expected symbol, got vector" over "we just compiled code that will hack the FBI, oh is that not what you meant?"

14:40 noprompt: lol

14:40 TimMc: what

14:40 technomancy: M-x eyeroll

14:40 csd_: If I call `re-matcher` in clojure, how can I pass the matcher to Java's Matcher.start method?

14:40 tbaldridge: noprompt: my personal opinion is this, Clojure is a lisp, and lisps are extremely powerful languages, things like macros allow you to add logic to the compiler. That stuff is never going to be easy.

14:41 technomancy: tbaldridge: and yet somehow racket manages it with an even more sophisticated macro system

14:41 tbaldridge: I'd rather have transducers, core.async, macros, etc, instead of better error messages.

14:41 noprompt: tbaldridge: so what would you're approach be to "it compiles fine in project a but not project b"?

14:41 tbaldridge: you're only making my point.

14:42 dbasch: csd_: (.start (re-matcher …))

14:42 tbaldridge: noprompt: find the differences...you most likely have one you haven't found yet. Either a clojure version, cljs version, library, plugin, lein, jvm, something is different. Even left over aot class files or stale .class files.

14:42 I've seen all of those cause problems like that.

14:42 noprompt: technically, i love those things just as much as anyone else here and no one would pick better errors over those things. otoh that's still not admitting that the error messages are still a problem to be solve and, furthermore, is worth solving.

14:43 csd_: dbasch: so then why does this return an error? (.start (re-matcher #".*\[.*" "t[est"))

14:43 stompyj: noprompt: I’ll have to check out java errors again, i haven’t used it seriously since the late 90s

14:43 mdrogalis: noprompt: I dont think anyone disagrees that better errors would be nicer. But you're seeing reality play out in front of you. We value X, so we chase X, and we have limited time to do other things.

14:43 You dont have to take a poll, you know? People are going to work on what they want.

14:44 stompyj: but the error messages were not good back then, better then clojure, but I couldn’t call them good

14:44 technomancy: mdrogalis: are you using "We" to mean the core team?

14:44 mdrogalis: technomancy: Nah, I just mean everyone in general.

14:44 stompyj: I think he means programmers in general

14:44 technomancy: mdrogalis: that implies we have a say in what happens

14:44 noprompt: mdrogalis: i would love to help work on improving the error messages situation but it's not something i can do in silence because a) i don't know java well and b) guidance would be helpful.

14:44 stompyj: #shotsfired

14:44 tbaldridge: noprompt: classic example, someone recently submitted a patch that improved an error message. Awesome! Except there was one problem, it blew the JVM inline budget and caused existing code to become slower. That one single line of code took a ton of work/testing to get right.

14:45 I'm still not sure if it was worth it.

14:45 mdrogalis: technomancy: Ha! I was trying to keep it from getting dark. :)

14:45 noprompt: Understandable.

14:45 TimMc: csd_: The fact that it returns an error doesn't have anything to do with how you're calling it.

14:46 dbasch: csd_: because you didn’t call find first

14:46 noprompt: i just don't understand the attitude. the mentality is bizarre.

14:46 csd_: dbasch: find returns a string though

14:46 noprompt: where's the humanity?

14:46 technomancy: noprompt: usability is simply not a priority; seems pretty straightforward.

14:47 dbasch: &(def a (re-matcher #".*\[.*" "t[est"))

14:47 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

14:47 csd_: TimMc: I'm trying to emulate what's suggested in http://stackoverflow.com/questions/4194310/can-string-indexof-handle-a-regular-expression-as-a-parameter. Seems like what I'm doing should work

14:47 noprompt: tbaldridge: so does improving error messages, generally come at the expense of something else?

14:47 technomancy: weird.

14:47 tbaldridge: noprompt: there are always tradeoffs in software

14:47 dbasch: &(let [a (re-matcher #".*\[.*" "t[est")] (.find a) (.start a))

14:47 lazybot: ⇒ 0

14:47 dbasch: ^ csd_

14:48 csd_: dbasch: when you do that does the interop mutate a?

14:48 dbasch: csd_: yes, Matcher has state

14:48 stompyj: noprompt: lol @ where’s the humanity. You should try by writing proposed “better” error messages for errors you see

14:48 and poll people, and see if they think they’re better

14:48 noprompt: tbaldridge: maybe i'm being naive but it seems odd error messages could be so hard to get right in the context of the other technical achievements made by clojure

14:49 mdrogalis: tbaldridge: You're a champ for always jumping in on this argument. :P

14:49 stompyj: there’s probably a “lean startup” way to understand this problem may be more difficult then it seems on the surface

14:49 technomancy: actually cataloging the biggest WTFs would be a good project

14:49 csd_: I see. I was under the impression that re-matcher would return a Matcher object so that you could directly apply .start to it

14:49 dbasch: csd_: “start: Returns the start index of the previous match.”

14:49 zerokarmaleft: technomancy: something like java/scala puzzlers, I'd dig it

14:49 technomancy: zerokarmaleft: actually I was thinking more of a "hall of shame"

14:50 hey, it worked for getting Maven Central over to SSL

14:50 csd_: dbasch: thanks

14:50 gfredericks: technomancy: there'd be an interesting taxonomy for them

14:50 noprompt: stompyj: probably what i'm going to do is start cataloging these things with a description of what it generally means.

14:50 justin_smith: technomancy: we could call it ~@wat#

14:50 gfredericks: e.g., some things are confusing to n00bs but intentional and not too bothersome to experienced folkles

14:50 stompyj: noprompt: yeah, I think that sounds like a great first step

14:50 csd_: dbasch: do you know if a better way to get the index of where a RE match occurs using pure clojure?

14:50 gfredericks: such as clojure.core/contains?

14:51 stompyj: the art of error messaging feels like the art of describing by a chord by it’s notes

14:51 technomancy: gfredericks: http://blogs.msdn.com/blogfiles/cdndevs/WindowsLiveWriter/JohnUdellsinTorontoNextWeek_CC69/what_we_need_more_of_is_science_3.jpg

14:51 stompyj: seems liek if you ask x people, you’ll get x answers

14:51 :)

14:52 tbaldridge: noprompt: yeah, that's a good place to start, take your pet error, figure out what the cause is, figure out how to improve it, then hand it off to someone to critique.

14:52 You'll probably fine it either a) discards some data that could be useful to someone or b) has some other performance tradeoff

14:52 at least that's been my experience, YMMV.

14:52 gfredericks: probably half of the error messages if you try to fix them you will 3 months later start screaming about rewriting the compiler

14:53 noprompt: tbaldridge: fair enough. i mean the whole reason i started hacking on this clojurescript tracing project is because it's damn near impossible sometime to understand why things are breaking because of horrible error messages both from clojurescrip and from javascript.

14:53 you end up littering the planet with println.

14:53 tbaldridge: guess i'll start with this one.

14:55 tbaldridge: noprompt: I will say that macro input validation is pretty ripe for optimization, no runtime cost, no JIT costs (that anyone cares about). That'd probably be a easy place to start

14:55 gfredericks: didn't chouser or someone have a sophisticated project to tackle that?

14:55 technomancy: gfredericks: yeah, that looked really promising

14:55 noprompt: tbaldridge: i know you are a busy guy but would you have any time during the week to help get me started, guide me?

14:56 technomancy: gfredericks: nice to see someone putting some deep thought into the problem

14:56 noprompt: tbaldridge: not to put you on the spot. :P

14:56 tbaldridge: noprompt: no, I never help people, now get off my lawn. :-P

14:56 noprompt: ;_;

14:56 arohner: has anyone ever seen weirdness from emacs/nrepl where emacs locks up while typing? I type C-f or C-a, and emacs is just out to lunch until I C-g

14:56 gfredericks: tbaldridge helped me once he's a damn liar

14:57 tbaldridge: noprompt: sure, you can email me or ping me here.

14:57 justin_smith: someone should make a schema/input validator to run as a language middleware, and call it a nanny-state-machine

14:57 tbaldridge: noprompt: email may be easier due to my work schedule.

14:57 justin_smith: arohner: I have seen things like that with autocomplete of various types turned on

14:58 arohner: justin_smith: weird part is, it didn't do this yesterday in a different project, and I don't remember changing anything recently

14:58 justin_smith: arohner: is it a projectless repl?

14:58 arohner: no

14:58 cider-connect repl

14:58 into a 'normal' project

14:59 justin_smith: arohner: you could try turning off completion and see if the behavior improves - could be something about one of your namespaces or deps triggers a bug

15:00 technomancy: arohner: using autocomplete.el?

15:00 arohner: technomancy: I don't think so

15:00 and it appears restarting emacs has fixed the problem

15:01 technomancy: gotcha. it seems to be pretty buggy, and a large percentage of cider/nrepl problems can often be solved by just getting rid of it.

15:01 arohner: aha. C-f is fine, as long as nrepl isn't eval'ing long running code

15:01 llasram: Ah

15:01 arohner: but large numbers of text input stuff hangs during a long C-c C-k

15:01 even Tab

15:02 noprompt: tbaldridge: thanks. email you @ cognitect?

15:02 scratch that i'll simply message you

15:02 tbaldridge: noprompt: sure

15:03 Bronsa: tbaldridge: did you see http://dev.clojure.org/jira/browse/ASYNC-86 ?

15:07 SagiCZ1: can i supply (min) with my own comparator? or better yet how do i implement min to compare only certain keys of elements? using reduce?

15:08 llasram: SagiCZ1: It only works on numbers, but various utility libraries have Comparator-based versions

15:08 SagiCZ1: llasram: ok rather than using library, i would like to implement it myself

15:09 but idk how

15:09 llasram: SagiCZ1: Well, look at `min-key` and `compare`, and mix :-)

15:10 SagiCZ1: ty

15:10 doctorm: Anyone using vim-fireplace able to get stack traces? I’ve tried :lopen after a failed evaluation, but it gives me “No location list”

15:12 SagiCZ1: llasram: min-key is enough for me since the key i want to compare is number already

15:12 (inc llasram)

15:12 lazybot: ⇒ 37

15:13 mping: why can't I map over a lazy seq? I must be doing something wrong

15:13 justin_smith: mping: you can, you just have to access the result, or else the mapping never happens

15:13 that's what laziness means

15:14 mping: is there a way to force it?

15:14 even this does not work: (map #(println ">>>" %) all-paths)

15:14 justin_smith: yes - do you need all the results, or do you just need the action in the map to occur for side effects?

15:14 mping: well, can you tell me both ways? so I can learn?

15:14 this is in the context of a test

15:15 justin_smith: to get all the results, wrap it in doall or use mapv, to just force the action wrap it in dorun or just use doseq

15:16 mping: it works, tks

15:17 I expected the test to "unwrap" the lazy seq

15:20 SagiCZ1: i've watched a video about quick-test last night.. i dont understand how can i let the test know which results are correct and which are not.. since it throws 100 000 random tests.. ?

15:20 AeroNotix: SagiCZ1: you're thinking of it wrong

15:20 you describe the properties of what your function takes

15:20 and then it generates values which satisfy that property

15:20 so if your function takes even values betwen 0 and eleventy million, you describe that property and then it passes them to your function

15:21 stompyj: SagiCZ1: if you’re familiar with mathematical equations

15:21 SagiCZ1: AeroNotix: lets say my function takes a definiton of a 2 squares and returns boolean iff they intersect.. what properties would i define for my test then?

15:21 stompyj: where f(x) can take any “real number” as input and can output only “negative real numbers”

15:22 SagiCZ1: stompyj: oh math.. thats where the "forall" notation came from

15:22 stompyj: then you’d specify that your input are real numbers, and your output should be negative real numbers

15:22 melipone: hello! Any idea how I can capture a url that has a semi-colon in a line that is delimited by semi-colons itself? Here's an example: http://buddhayana.ru/2AB@5G8-A-@>A25B;5=85<-8AB>@88-87-687=8-1C44K.html&quot;;1;"db_unfetched";Tue Sep 02 14:46:47 EDT 2014;Wed Dec 31 19:00:00 EST 1969;0;2592000.0;30.0;0.01;"null"

15:22 stompyj: and quick-test makes sure those properties are satisfied

15:22 if I understand it correctly

15:22 SagiCZ1: stompyj: that does not sound very useful in my case

15:23 ok.. so i define ranges for which it should return some defined ouput..

15:23 stompyj: SagiCZ1: I’m sure there’s people here who understand it much better then myself who could help you, but that’s how I understood it when I checked it out

15:24 mahmoudmheisen91: then you’d specify that your input are real numbers, and your output should be negative real numbers

15:25 quit

15:25 SagiCZ1: what just hapenned? did he rage quit?

15:26 stompyj: LOL

15:26 I’m dying to see what a test suite using quick-check + simulation testing would look like

15:27 SagiCZ1: i cant imagine how could it test more corner cases than traditional unit testing

15:28 stompyj: SagiCZ1: I think unit testing is great for when you know what you want to test

15:28 but often times the errors happen on cases that you’re not thinking about

15:28 SagiCZ1: if you dont know what to test, you can hardly define properties for whole ranges of input..

15:28 stompyj: or composition of events that you didn’t expect

15:28 SagiCZ1: event composition sounds useful..

15:30 stompyj: I dont’ prefer TDD, but I do appreciate tests, esp. when refactoring

15:30 SagiCZ1: who doesnt..

15:30 im workin

15:30 on large scale Java EE app at work

15:31 we just started writing test.. 2 months into development

15:31 very painful

15:32 stompyj: ooff

15:32 brutal

15:32 is that stuff mostly EJB’s still?

15:32 or something different?

15:32 SagiCZ1: no beans.. no spring.. its vaadin and our own data model

15:42 mping: SagiCZ1: ouch

15:54 mi6x3m: any way to get the require mappings of a NS?

15:54 justin_smith: mi6x3m: ns-imports or ns-aliases

15:55 mi6x3m: justin_smith: aliases only returns what you have really aliased

15:56 justin_smith: so if you require without an :as it doesn't show up>

15:56 mi6x3m: yes

15:57 bbloom: mi6x3m: require is a side effect that just loads the namespace, alias (the :as keyword) is a side effect that modifies the current ns aliases table

15:57 mi6x3m: bbloom: so it's not kept in the books once the ns is constructed?

15:59 justin_smith: I guess that's another reason to always use :as

16:03 mi6x3m: justin_smith: you are actually right

16:03 easier to always use :as, especially in my case

16:03 (building source code for code demos)

16:12 TimMc: mi6x3m: There's also no guarantee that a :require form will be present when another namespace is used.

16:13 mi6x3m: TimMc: I am aware, this is just an internal contract so the demo framework works ok :)

16:13 TimMc: A great example is clojure.string. A bunch of namespaces use it, so occaasionally someone will write clojure.string/join and forget to :require it -- but it still works, because it has been loaded transitively. :-)

16:16 justin_smith: TimMc: or clojure.pprint - you don't need to require it in the repl, because the repl loads it at some point, but it can break in your deployed code

16:16 (if you forget to require it)

16:21 atyz: I'm trying to use an input stream twice, and I have found several ways to copy it to a bytearrayoutputstream using some java interop but is tehre a "clojure" way to do it?

16:39 amalloy: hugod: every time i run a benchmark with criterium, i see "WARNING: Final GC required 2.824425435800379 % of runtime" (obviously the percentages differ). am i doing something unusual that this warning comes up every time? or if it's not unusual, why is there a warning at all?

16:52 dbasch: amalloy: he shows a warning when the final gc takes more than 1% of the total running time, which is pretty much always for any meaningful benchmark I run

16:53 amalloy: right. so if it's totally normal, it shouldn't be a warning

16:53 dbasch: I agree, it should be more of an INFO

16:54 amalloy: "INFO: everything normal" is silly too. it should be quiet unless it's an unusual amount of time

17:03 martinklepsch: do transducers also take from channels or is that required to be done elsewhere?

17:04 hiredman: a transducer is a transformation of a reducing fuction there is nothing about channels in them

17:05 (so no)

17:08 martinklepsch: hiredman: are you aware of any more writeups combining core.async & transducers?

17:08 hiredman: martinklepsch: no

17:09 stompyj: martinklepsch: there are about 4-5 of them now

17:10 hiredman: I suspect the tricky areas of combining transducers and core.async are the same as the tricky areas of core.async, namely not blocking in a go block, closing channels when done, and reporting errors

17:11 I think core.async is light on documentation on how it applys transducer transforms to things passing through a channel, which can make it difficult to figure out if some operation will end up getting run in a go block or not, which is what you need to know in order to avoid blocking ops in a go block

17:12 but pulling up the code should answer those lingering questions pretty quick

17:13 martinklepsch: I had some rough idea about using transducers for something where map< seemed appropriate: https://gist.github.com/mklappstuhl/d6d776317171e01f1178 — maybe someone sees an obvious flaw?

17:17 hiredman: it is hard to know where to start

17:17 io is generally a blocking operation so it shouldn't be done in a go block, you should use thread or future or have your own threadpool blocking ops run on

17:17 upload-files pretty obsiouly does io

17:17 obviously

17:17 martinklepsch: hiredman: it's cljs

17:18 sorry for the wrongly named gist,

17:19 hiredman: you are also using upload-files before it is defed

17:21 mi6x3m: any way to use pprint to produce a string?

17:21 (sane way that is)

17:21 justin_smith: (with-out-str (pprint ...))

17:21 dagda1: Is there a way to tell if a var is a list, I don't mean vec?, list? or seq? but just a generic away that would be true for [1 2 3] '(1 2 3) etc

17:22 amalloy: sequential?

17:22 justin_smith: dagda1: coll?

17:22 martinklepsch: hiredman: upload-files returns immediately and takes callback — that's where I planned to put the result in result-chan

17:22 dagda1: justin_smith: nice one

17:22 martinklepsch: hiredman: that's what I've seen in some cljs ajax core.async examples

17:23 amalloy: coll? is unlikely to be what you want, because it returns true for maps

17:23 (which is why i said sequential?)

17:27 hiredman: martinklepsch: sure, but you are still using it before it is defined, which is not valid and I am surprised nothing is throwing an error about it

17:29 martinklepsch: the xform function you pass to (chan ...) when creating a channel is a transformation of values flowing through the channel, the transform won't happen unless values are flowing through

17:29 they won't flow through unless soming is produce values for the channel and something is consuming those values

17:29 hugod: amalloy: the question is how to define unusual

17:30 hiredman: something

17:30 amalloy: martinklepsch: what is the deal with these definitions like (def foo (comp f)). that is just (def foo f)

17:31 martinklepsch: amalloy: I wrote them earlier when they did multiple things

17:31 mdeboard: that bitrot tho

17:31 hiredman: martinklepsch: you are not consuming values from some channels

17:31 tadni_: https://www.kickstarter.com/projects/1751759988/sicp-distilled?ref=discovery

17:32 martinklepsch: hiredman: right

17:32 amalloy: hugod: sure. it seems to me that the bar for "unusual" is currently too low, because that warning is present in every criterium run i've ever seen

17:32 tadni_: So this says it's going to rewrite the examples of SICP in Clj, I wonder if that means they will distribute a virtual book.

17:32 hiredman: martinklepsch: so nothing happens

17:34 mi6x3m: is clojure automatically importing all of java.lang

17:34 tadni_: http://sicpinclojure.com/ Sadly has had very little progress.

17:34 mi6x3m: well, most of it anyhow

17:35 amalloy: mi6x3m: yes, just like java does

17:36 mi6x3m: amalloy: thank you

17:47 martinklepsch: hiredman: thanks a lot. I wasn't really aware things had to enter & leave the channel before the transducer is applied. I think I'm a lot closer to what I wanted to do now than before :)

17:49 amalloy: dakrone: it looks to me like cheshire uses jackson's lexer, but does its own parsing. is that accurate?

17:50 ztellman: amalloy: that's correct

17:55 sdegutis: What might cause a Clojure-Ring/Jetty website to just stop responding entirely and need to be kill9'd?

18:04 justin_smith: sdegutis: next time use jstack, that will tell you what all the threads are doing / where they are stopped

18:04 sdegutis: Thanks.

18:06 justin_smith: I don't know how much good we can do inventing scenarious that may bring a jetty server to a standstill. deadlock somewhere? trying to use some resource that was erroneously deleted or went inconsistent?

18:07 xeqi: fork bomb, cosmic rays

18:07 sdegutis: I have the simplest web app, a very simple shopping cart. The most complex part of it is that it sometimes talks to Datomic over TCP on another server.

18:07 danielcompton: sdegutis: could be hax0rs

18:08 sdegutis: I can't imagine this being caused by anything other than trying to communicate with the Datomic server and hanging.

18:08 The entire process becomes unresponsive and is spending 99% of the CPU.

18:08 justin_smith: yeah, then your best bet is to use jstack (or a full on profiler), and finding out what is looping so crazy

18:10 amalloy: sdegutis: whenever my web servers crawl into a hole, it turns out to be because it's stuck in a gc loop because i had a memory leak somewhere

18:10 sdegutis: Ahh, that could very likely be it!

18:11 amalloy: Does that go on for hours and hours?

18:11 amalloy: yeah. i don't totally understand why

18:11 sdegutis: amalloy: Thanks a ton :)

18:11 justin_smith: finalizers that use too much memory?

18:11 sdegutis: justin_smith: Thanks for the suggestion.

18:11 justin_smith: np

18:11 sdegutis: My site is written in Clojure, fwiw. But it is using a very old version of Datomic Free.

18:11 So there may have been bugs in it that have since been fixed.

18:12 I will take all this into consideration. Thank you.

18:12 hyPiRion: amalloy: is that a similar reason to why lazybot eats a CPU when it disconnects from an IRC server?

18:12 amalloy: justin_smith: my vague understanding is that it's more like "(1) needed to allocate 20 bytes, but the 10GB heap is full; (2) long GC, freeing up 5kb. (3) GOTO 1"

18:13 justin_smith: ahh

18:13 so not enough usage to crash the whole thing, but enough to make gc consume hella cpu

18:13 amalloy: hyPiRion: i dunno. i haven't put much effort into that one. i'd guess there's just something dumb in lazybot's irc retry code

18:13 hyPiRion: amalloy: yeah, that sounds like something completely different when you put it that way

18:14 ticking_: Hey it seems that record fields can be accessed through (:field self) (.field self) and field. Any thoughts on what's most idiomatic?

18:14 Bronsa: field

18:16 sdegutis: amalloy: LOL that's a funny loop :)

18:16 ticking_: Bronsa: thanks :)

18:17 danielcompton: Bronsa: is that only from within the record? Or is it also a function on a record?

18:18 Bronsa: danielcompton: only methods/protocol-functions defined inside the deftype/defrecord have access to those locals

18:18 if that's what you're asking

18:18 I didn't fully understand the question

18:18 danielcompton: Bronsa: so outside of the record you would use .field or :field?

18:18 Bronsa: yeah definitely

18:20 I mean, I don't understand how you'd expect a regular fn to figure out if a local should be a field access on some instance otherwise

18:20 danielcompton: Bronsa: neither

18:21 justin_smith: technomancy: regarding the conversation earlier, it's OSHA's job to make sure nobody's boss lets them do this on the work site: http://i.imgur.com/sQnrHFc.jpg

18:21 technomancy: heh, wow

18:21 amalloy: Bronsa: reminds me of http://stackoverflow.com/questions/9345056/in-clojure-how-to-destructure-all-the-keys-of-a-map

18:22 danielcompton: Is he also over powerlines?

18:23 justin_smith: danielcompton: hard to tell from the perspective, but looks like it

18:23 if you follow the fence, and see the pole's position relative to that.. yeah I think so

18:27 TimMc: justin_smith: Grabbed from https://pay.reddit.com/r/MenonUnstableLadders/ ?

18:27 justin_smith: no, but I like that this exists

18:28 TimMc: I like how it is specifically men.

18:28 technomancy: justin_smith: hey, if they can have one just for bezels...

18:28 TimMc: and of course https://pay.reddit.com/r/OSHA

18:29 justin_smith: TimMc: if you found a woman on an unstable ladder, I think you would need to start a new subreddit just for that

18:29 Bronsa: amalloy: ew the last answer

18:29 TimMc: Good luck, they're much less likely to get testosterone poisoning. :-P

18:29 amalloy: TimMc: are you linking to pay.reddit.com as a side effect of usine https everywhere, or what?

18:29 TimMc: amalloy: Yeah.

18:29 technomancy: justin_smith: http://www.penny-arcade.com/comic/2014/06/27/herstory

18:29 and http://www.reddit.com/r/bezels

18:29 TimMc: It's not, like... a subliminal message or anything.

18:30 Bronsa: eval is the worst function ever to make part of a core library

18:31 justin_smith: technomancy: well, 45° cuts on edges are really important after all

19:04 gfredericks: take et al return a "stateful transducer" on one arg

19:06 at least one function returns a stateful transducer but neglects to say so in the docstring

19:15 bounb: ,((fn [x] (if (= x 1) 1) (if (= x 2) 2)) 1)

19:15 clojurebot: nil

19:15 bounb: ,((fn [x] (if (= x 1) 1) (if (= x 2) 2)) 2)

19:15 clojurebot: 2

19:15 bounb: can someone explain these results please

19:17 amalloy: there's no such thing as early return in clojure

19:19 bounb: is the order of the evaluation of the ifs defined?

19:19 technomancy: bounb: what exactly did you expect?

19:19 bounb: i expected the first one to return 1 and the second 2

19:20 i can understand the result if the second if form is evaluated first (+ no early return)

19:20 i guess that's it isn't it

19:20 hiredman: why do you need both?

19:20 (second evaluated first and no early return)

19:20 technomancy: bounb: expressions in the non-tail position are discarded

19:21 bounb: hiredman: uh yes

19:21 i agree

19:21 alright nothing to see here folks. cheers

19:22 technomancy: yeah, the only reason fn takes multiple body args is for side-effects

19:22 justin_smith: bounb: it might help to know that fn has an implicit do block - each form in the body is evaluated, in order, and there is nothing like a "return statement" available for fn

19:22 bounb: good point. thx

19:23 justin_smith: ,((fn [] 1 2 3 4 5))

19:23 clojurebot: 5

19:23 technomancy: ((eval (apply #'fn (concat nil nil [] 1 2 3 4 5))))

19:23 oops

20:25 sdfgsdf: What editor do you people use for clojure?

20:26 jtackett: light table

20:26 danielcompton: sdfgsdf: emacs

20:26 although Cursive is on my list

20:26 sdfgsdf: never heard of cursive, will check it out

20:26 xeqi: emacs, but I've dabbled with cursive and its pretty good

20:27 amalloy: sdfgsdf: cursive is the intellij plugin or something

20:28 technomancy: the proprietary one

20:28 splunk: anyone know a good synonym for "get" for use in my own protocol?

20:28 amalloy: call it ----get-protocol---internal-for-real

20:28 danielcompton: technomancy: aka the maintained one

20:29 splunk: amalloy: ship itttt!!!

20:29 xeqi: acquire, obtain, grab

20:30 sdfgsdf: What is your protocol and what does get mean in it?

20:30 splunk: it's like s3

20:30 (defrecord S3Storage [cred] StorageProtocol (get [this k] ...))

20:31 but you can't use get with a defrecord because defrecords are already associative, i.e. normal clojure.core/get

20:31 It means to like, lookup / download, more than lock or reserve

20:32 justin_smith: copy? download?

20:32 ephemeron: Why not a traditional "fetch"?

20:32 amalloy: splunk: so make it a deftype instead of a defrecord? i can't imagine it's important to be able to treat it like a map, with only the one key

20:32 splunk: amalloy: I'm trying to copy the stuart sierra component workflow, which appears to advocate `assoc`ing stuff into a defrecord?

20:32 Jaood: "here-boy-catch"

20:32 splunk: ephemeron: that's a great candidate thanks

20:33 sdfgsdf: "acquire-the-thing-that-you-want-to-have"

20:33 joobus: has anyone here worked through clojure-koans?

20:33 technomancy: do you really need protocols for a function that's guaranteed to be I/O bound?

20:33 sdfgsdf: joobus I am in the process of doing that now

20:33 splunk: technomancy: just trying to make an abstraction over "get a thing out of storage"

20:33 joobus: what lesson are you on?

20:33 sdfgsdf: just finished 14

20:34 joobus: i'm on 13, and the answers aren't obvious to me. do you have any recommendations for reading/researching recursion?

20:34 splunk: technomancy: guess that could be done without protocols / records, though again with the `component` workflow it seems like a decent fit

20:36 sdfgsdf: Well it was already kind of intuitive to me, probably from earlier non-clojure lisp stuff.

20:36 Can you be more specific about what part of it you are having trouble with?

20:36 Jaood: john2x: the little schemer

20:36 err joobus ^^

20:36 technomancy: splunk: I guess if you have component then you work around all the crazy reloading issues around records, but do you know for sure all the consumers of your lib will have it too?

20:37 splunk: also: introducing semantically-useless arguments to your arglists simply for dispatch purposes is super annoying.

20:38 splunk: technomancy: haha, isn't that a critique of protocols in general?

20:38 technomancy: splunk: yes

20:38 sdfgsdf: joobus, are you having trouble with the first question or do your problems start later on?

20:39 technomancy: splunk: they're super useful for implementing clojure-in-clojure, which is the reason they were added to the language. in application-level code: not so much.

20:39 joobus: sdfgsdf: first, this is my first lisp. i peeked at the answer for the first one, and after seeing it, it made sense, but that's not how i want to solve the rest.

20:39 splunk: technomancy: as far as I can tell, the primary alternative to `(fetch my-s3-record my-key)` is `(my-s3-fetching-closure my-key)`, which I've totally done before, but got the impressions readers don't like it

20:40 amalloy: splunk: technomancy's fortune cookies all contain critiques of protocols in general

20:40 xeqi: technomancy: I've been playing with them as reified namespaces, do you have a different alternative for that?

20:40 technomancy: xeqi: actual reified namespaces? those would be great =D

20:40 splunk: amalloy: lolz

20:40 joobus: for the blanks at the top, there are maybe 3 underscores. i'm not sure how long the functions should be, or if they are elegantly simple.

20:40 xeqi: technomancy: dreamz

20:41 though I'd imagine that would have a similar argument for dispatch

20:41 joobus: i guess i just need to spend more time on them

20:41 sdfgsdf: Do you understand how loop and recur work, joobus?

20:41 joobus: no, not yet. i guess that's the place to start.

20:42 sdfgsdf: Yes

20:47 Here are some examples of loop and recur:

20:47 http://clojuredocs.org/clojure_core/clojure.core/recur

20:47 you still here joobus?

20:48 joobus: yes

20:48 looking through loop and recur docs right now

20:49 sdfgsdf: It's something I find that's easier to understand through examples than through an explanation of what it does

20:50 But in case the latter would help anyhow, it rebinds the variables in the loop to the values you give it in the recur

20:51 Basically you use recur wherever you would otherwise have a function call itself if you're doing the thing without loop and recur

20:52 With loop and recur it's evaluated differently so you don't get a stack overflow but it's pretty similar to how recursive functions work

20:53 joobus: so if i have 2 loop bindings, then if the recur has 2 arguments in the list, it will rebind the loop bindings in the order they were declared?

20:53 gfredericks: just like a function call

20:53 sdfgsdf: yes

20:55 splunk: amalloy: I take it you disagree re: protocols, e.g. I see a few of them in `useful`?

20:56 amalloy: i don't think they're toxic waste like technomancy does. it's easy to overuse them

20:57 joobus: i was curious about the answer to the first func in 13, is-even?... is that the quickest way to determine even and odd, or is this just an example? is decrementing from 1000 and alternating true/false the "clojure" way?

20:57 splunk: with the takeaway being "do dispatch using a different mechanism" (like multimethods) or "do less fancy dispatch"?

20:57 amalloy: of the three protocols in useful, i regard only one (Adjoin) as a reasonable idea

20:57 sdfgsdf: Notice that in the clojure koans you have the factorial function called with large arguments. This demonstrates the utility of loop and recur; if you did it without loop and recur you would get a stack overflow from all the nested functions.

20:58 The is-even function is a pretty contrived example

20:58 joobus: ok

20:59 gfredericks: ,(source even?)

20:59 clojurebot: Source not found\n

21:00 amalloy: ~def even?

21:01 bbloom: clojurebot: even? |is| do you even even?

21:01 clojurebot: Cool story bro.

21:01 gfredericks: ,(defn steven? [x] (contains? #{"steven" :steven 'steven} x))

21:01 clojurebot: #'sandbox/steven?

21:01 gfredericks: bbloom: I'm not sure those question marks are workable

21:02 ,(steven? "steven")

21:02 clojurebot: true

21:02 bbloom: ~even

21:02 clojurebot: Huh?

21:02 bbloom: clojurebot: even |is| do you even even?

21:02 clojurebot: I don't understand.

21:02 bbloom: *shrug* gfredericks oh well

21:03 amalloy: bbloom: clojurebot is allergic to question marks in factoids

21:03 bbloom: amalloy: does he break out in hives?

21:03 gfredericks: clojure hives

21:03 amalloy: what would live in a clojure hive? a swarm of )}] all buzzing around?

21:04 they look like they could fly for sure

21:04 gfredericks: contest: a readable string that looks like an insect

21:04 or at least like it can fly

21:06 no trivial use of line comments

21:06 or string literals

21:10 joobus: i've seen the variable acc used a few places. is this short for accumulator?

21:10 gfredericks: yeah

21:10 joobus: k

21:10 amalloy: i use it for accidents

21:11 gfredericks: accursed

21:11 amalloy: sometimes i see someone reducing and they claim it's accumulating data but i swear it looks like it's just accreting

21:11 gfredericks: accouterments

21:11 accordion

21:11 joobus: accelerando?

21:12 amalloy: gfredericks: accouterments is a misspelling that made me laugh

21:12 gfredericks: it's in my words file

21:12 wait

21:12 amalloy: did you put it there some time ago as a self-prank?

21:12 gfredericks: you're referring to re <=> er?

21:13 amalloy: yes

21:13 gfredericks: google says this is correct but only for plural

21:13 wiktionary has both with er

21:14 and another entry for both re

21:14 I wonder if google is confused.

21:14 amalloy: http://www.merriam-webster.com/dictionary/accoutrement has both RE

21:14 i trust MW over wiktionary or google, when it comes to defining words

21:14 gfredericks: my word file has both

21:15 amalloy: MW lists it as a variant

21:15 so I assume you owe me $50.

21:15 whoops hey wanna bet $50 on this

21:16 amalloy: "variant" is a euphemism for "hillbilly slang"

21:16 gfredericks: "hillbilly slang" is a dysphemism for "variant"

21:19 TimMc: gfredericks: My entry for the contest: ##(read-string "🐝")

21:19 lazybot: ⇒ 🐝

21:20 * gfredericks has no idea how to get that to print right

21:21 TimMc: U+1F41D HONEYBEE

21:23 gfredericks: okay you've successfully dismantled the contest

21:23 TimMc: That means I win!

21:24 catern: BEEEEEEEEEEEEES

21:28 sdegutis: gfredericks: it shows up right for me

21:29 gfredericks: somewhere in between my emacs->tmux->ssh->gnome-terminal

21:29 sdegutis: oh

21:29 gfredericks: the bee support is lacking

21:29 sdegutis: welp.

21:30 TimMc: It doesn't show up for me either. :-)

21:31 sdegutis: Shows up for me, using just LimeChat.

21:31 xeqi: gfredericks: I'm gonna blame gnome-terminal as thats what we have in common and it doesn't show up for me

21:31 sdegutis: Oh wait, you mean in CLojure.

21:31 Yeah, it shows up in Terminal.app using `lein repl`.

21:31 Doesn't work in Hammerterm though.

21:33 gfredericks: no I mean my irc client

21:33 xeqi: could it also be the font? I think I have inconsolata

21:34 catern: sdegutis: is.. this.. a port of st to *OS X*? seriously? gross. suckless would be ashamed

21:34 sdegutis: They are.

21:34 I told them.

21:34 xeqi: gfredericks: maybe, I can't remember if I have inconsolata or terminus

21:34 sdegutis: On the other hand, they made my job porting it needlessly hard by sloppily using globals.

21:34 blaenk: is there an accepted way of detecting whether the app is in dev mode or production, etc?

21:34 sdegutis: So we're even.

21:35 haha https://www.dropbox.com/s/9sc05upwygvdpnx/Screenshot%202014-09-02%2020.34.22.png?dl=0

21:35 xeqi: apparently inconsolata. so yeah, probably that

21:35 sdegutis: Hammerterm totally fails at Unicode.

21:35 catern: Also, X is something to be ashamed of.

21:36 Okay maybe that's a bit harsh.

21:36 blaenk: also anyone know of a good ring logger?

21:37 xeqi: (fn [f] (fn [req] (log/log (... req)) (let [res (f req)] (log/log (... res)) res))

21:38 sdegutis: Is log4j the best solution for logging in Clojure?

21:38 Or maybe Lumberjack?

21:38 boyscared: hello. how do i use cider-inspect to actually inspect stuff?

21:38 can't find any documentation on the feature

21:39 xeqi: sdegutis: tools.logging?

21:39 sdegutis: Ah.

21:40 xeqi: no idea if thats "best", but probably where I'd start

21:40 blaenk: all it does is delegate to an actual logging implementation

21:41 technomancy: wait, is this a terminal named after Captain Hammer from Doctor Horrible's Sing-Along Blog?

21:42 sdegutis: Sure why not.

21:42 technomancy: http://img3.wikia.nocookie.net/__cb20080731175820/drhorrible/images/5/50/Captain_Hammer.jpg not a bad mascot, eh?

21:43 blaenk: thats the guy from firefly too

21:45 xeqi: I think at this point he's the guy from castle

21:45 sdegutis: ha

21:46 I have no idea how Habbie came up with the name Hammerterm.

21:46 xeqi: from hammerpants ?

21:46 sdegutis: but anyway, http://stream1.gifsoup.com/view/980226/hammertime-o.gif

21:47 catern: how did you deduce so quickly that it was from st?

21:47 gfredericks: there's a link in the repo description

21:49 sdegutis: Oh.

21:49 But how did you find the repo?

21:49 I didn't post one.

21:50 xeqi: $google sdegutis hammerterm

21:50 lazybot: [sdegutis/hammerterm · GitHub] https://github.com/sdegutis/hammerterm

21:50 sdegutis: wow thats fast

21:50 they rejected my changes to extract the terminal emulation stuff away from the X stuff

21:50 oh well

21:50 justin_smith: ,((((((((((((((((((fn f [] f))))))))))))))))))

21:50 clojurebot: #<sandbox$eval25$f__26 sandbox$eval25$f__26@1fcb359>

21:51 technomancy: abstraction ain't free

21:51 Bronsa: ,(reify clojure.lang.IDeref (deref [this] this]))

21:51 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

21:51 Bronsa: ,(reify clojure.lang.IDeref (deref [this] this))

21:51 clojurebot: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #<sandbox$eval73$reify__74@189bd81: #>>>>>>>>>>

21:52 justin_smith: Bronsa: nice

21:53 sdegutis: look, you...

21:55 bounb: haha :)

21:55 justin_smith: is there a name in the lambda calculus for (fn f [] f) ? (the function of no args that returns itself)

21:56 sdegutis: technomancy: So are you in California now. Thanks in advance, ragards?

21:58 Bronsa: justin_smith: I don't think functions can refer to themselves in lambda calculus

21:58 justin_smith: OK

21:59 technomancy: sdegutis: I, um, yes?

22:01 sdegutis: Good I may ship my Atreus to you as a thank-you gift :)

22:01 I think you'll like it, it's got birch-wood etc.

22:02 technomancy: cool, I'll patch it right up then and you'll be right as rain

22:02 sdegutis: <3

22:05 lavokad__: guys, i now have a .clj file in one window, and repl(cider) in the other. When I do C-x C-e, the expression's evaluation result apears above my editing file. How do u make results apear in the repl window?

22:15 justin_smith: lavokad__: I like to keep a trail of what I evaluate in the repl, and for that to work I switch the repl to the namespace I am working on, and enter code into the repl

22:16 it is easy to select and copy whole defs at a time

22:16 joobus: is loop always used to make recursive calls?

22:17 justin_smith: joobus: that's what loop is for, yeah, but if you were feeling dumb you could never call recur and use it as if it were let

22:17 which, to reiterate, would work, but would be dumb

22:18 joobus: ok, but one doesn't necessarily need to call 'recur' specifically. one could also call the function containing the loop in the loop?

22:19 justin_smith: you don't need loop for that

22:19 you can call the function, or even call recur, without a loop

22:19 loop is for when you want a block that can recur

22:20 joobus: ok, thanks

22:20 justin_smith: ,((fn f [x] (if (> x 100) x (recur (+ x x)))) 10)

22:20 clojurebot: 160

22:20 justin_smith: example of recur without loop ^

22:20 joobus: i'm looking at the recursive-reverse function here: https://github.com/tomshen/clojure-koans/blob/master/src/koans/13_recursion.clj

22:21 and here: https://github.com/viebel/clojure-koans/blob/master/src/koans/recursion.clj

22:21 justin_smith: yes, one is tail recursive, the other is not

22:24 amalloy: justin_smith: loop without recur: a poor man's let

22:24 could totally avoid needing let* for bootstrapping!

22:24 justin_smith: lol

22:24 you could totally replace both with fn immediately followed by args :P

22:25 sdegutis: Hello.

22:25 Does anyone know what project this is referring to. https://twitter.com/technomancy/status/506146365941219329

22:25 Thanks in advance. Regards.

22:25 justin_smith: sdegutis: it was atreus, I checked when I first saw it

22:26 sdegutis: Do you have the link.

22:26 justin_smith: (when I saw the tweet that is)

22:26 nope, not handy

22:26 sdegutis: Looks like https://news.ycombinator.com/item?id=8247803

22:26 justin_smith: yeah. that looks right

22:27 sdegutis: Reminds me of when my project was on HN for a little bit. After that, I posted a link to the HN thread in my project's FAQ under the question "Where can I find a comprehensive list of alternatives to your app?"

22:28 justin_smith: nice

22:28 sdegutis: Same here.

22:28 But I guess there's not much else to talk about in HN threads besides alternatives to the topic?

22:29 bbl adding gui buttons

22:29 cataska: Hi, what "profiles" means in cljsbuild ?

22:30 blaenk: think of it like ruby environment configuration

22:31 cataska: I know nothing about ruby

22:32 mdeboard: me either!

22:32 joobus: me either!

22:32 sdegutis: I do.

22:32 Okay so it goes like this:

22:33 You've got an "environment configuration".

22:33 It's basically like Leiningen profiles.

22:33 And you can configure your environment.

22:33 You can use Gemfiles and Bundler for this.

22:34 Specify a "group" of :test or :development in your Gemfile.

22:34 That's not how it works in Leiningen though.

22:34 Anyway, it's handy.

22:37 lavokad__: why I see 4clojure package in the web http://melpa.milkbox.net/#/ using chrome, but when doing M-x package-install, it is not there..

22:37 cataska: How "profiles" triggerred when type "lein xxx" ?

22:37 sdegutis: Thanks in advance.

22:55 danielcompton: lavokad__: is melpa one of the packages in your emacs config?

22:56 package repositories that is

22:56 lavokad__: danielcompton: yes, i tried with both stable and the other

22:56 it is so weird

22:57 I see bunch of other but not 4clojure

22:58 xeqi: $google leiningen profiles

22:58 lazybot: [leiningen/PROFILES.md at master · technomancy/leiningen · GitHub] https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md

22:58 xeqi: ^ cataska

22:59 lavokad__: i did manually and its ok

23:00 but why the hell can't do it from package-install...:(

23:02 cataska: xeqi: Cool, thank you

23:54 Ceterizine: >_>

Logging service provided by n01se.net