#clojure log - Feb 05 2015

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

0:11 tomjack: interestingly metadata does not survive apply for vectors

0:11 generally, for proper seqables which don't copy their metadata

0:12 (fn [& args] (meta args)) is a user error I suppose

0:15 amalloy: tomjack: well, that's because vectors are never *actually* the arglists

0:15 rather, the arglist is (seq v), not v

0:15 i simplified a little for Lewix

0:19 tomjack: I thought I understood metadata, but I was wrong

0:20 amalloy: i mean, metadata lives on values, and if you construct a new version of the same value by modifying it a bit, eg via conj, you get the same metadata

0:20 if you construct a totally distinct object, eg via seq, you don't

0:21 tomjack: I understand what happens; I want to understand what it means

0:21 amalloy: well, i thought i was explaining that

0:22 tomjack: "same value" is reminiscent of "same electron"

0:22 you don't mean same as in =, right?

0:22 justin_smith: tomjack: same Object

0:22 not value, but identity

0:22 amalloy: well, the metadata is the same as in identity

0:23 i was talking about getting a new version of a value, which of course leaves you something which is not "same"

0:23 julianleviston: Lewix: a vector isn’t a seq, is it?

0:23 tomjack: I don't think you mean the same thing by "a value" as I do

0:24 justin_smith: tomjack: what is a value?

0:24 julianleviston: justin_smith: is it the content of something?

0:24 tomjack: or rather, when I say "what it means", I'm thinking in a context where, inside (let [x [1 2 3] y [1 2 3]] ...), x and y refer to the same value (regardless of any compiler tricks)

0:25 justin_smith: tomjack: right, that's the same value

0:25 different identities

0:25 tomjack: but I find that my variables actually seem to refer to a pair of a value and an identity

0:25 julianleviston: tomaw: do you mean memory location?

0:25 justin_smith: tomjack: vars have identities, you can get at it via resolve, (var x), #'x etc.

0:25 tomjack: s/identity/non-value/, I dunno what really

0:25 justin_smith: tomjack: metadata does not go with values, it goes with identities

0:26 tomjack: right

0:26 julianleviston: tomjack: this is going to get very existential. :)

0:26 justin_smith: julianleviston: there's a good hickey talk, I forget which one, about values state and identity that makes all this stuff very clear, he even references Whitehead

0:27 julianleviston: justin_smith: yeah, I’ve seen it a couple times. I love it :) Whitehead rocks… if not a little self-confusing at times.

0:27 justin_smith: I think it was actually the first exposure I had to clojure.

0:27 tomjack: so when working with values, I expect that, given I am careful in my code, I can put on "metadata-blocking glasses" and see a version of my code where the identities become irrelevant for understanding the meaning of the code

0:28 julianleviston: tomjack: I guess that depends if your code deals with meta-data or not!

0:28 tomjack: it's ok if the code deals with metadata

0:28 in certain ways

0:28 justin_smith: tomjack: sure, metadata is used as an implementation detail that you can usually ignore

0:28 tomjack: e.g. consider (defn identity' [x] (vary-meta x update :counter (fnil inc 0)))

0:29 I can put on metadata-blocking glasses, and then (= identity identity') as far as I'm concerned

0:29 justin_smith: tomjack: it wouldn't work on java Objects, or primitives

0:29 while identity does

0:29 tomjack: ah, yes, it's a restricted identity

0:29 to IObj

0:29 justin_smith: right

0:30 tomjack: ok, I guess I do understand metadata

0:38 not really though. I guess some fns should be able to get tickets which permit them to inspect certain metadata (and to use the result of the inspection in the return value, not just in the return metadata). e.g. eval needs to be able to case on :macro

0:40 justin_smith: tomjack: it does that by looking up the var

0:40 tomjack: eval doesn't get the var as an arg, it gets a symbol, it uses that to find the var, and uses that to find the metadata

0:41 tomjack: yes, but if I had metadata-blocking glasses, putting them on would break macroexpansion

0:41 well, no, though. because vars aren't values

0:43 I'll just wait until after I macroexpanded to put the glasses on :)

0:51 (fn constantly' [x y] (with-meta x (merge (meta x) (-> y meta meta))))

2:20 sobel: can someone help me understand what the idiomatic way to solve a little programming problem is with clojure? i have a simple row-data transformation to make

2:21 Empperi: shoot

2:22 sobel: nutshell: reading csv, i need to capture some header data and distribute it to body rows. target is more csv, eventually on disk

2:23 Empperi: first https://github.com/clojure/data.csv

2:23 sobel: i got as far as that library and it seems to read ok

2:24 Empperi: then I'd need a bit more information about "capturing header data and distributing it to body rows"

2:24 what do you mean with that?

2:24 take the first row then copy-paste that data to rows after that?

2:24 sobel: denormalizing

2:24 yes

2:25 Empperi: ok, so you have something like:

2:25 foo;bar

2:25 blergh;blorgh

2:25 and you want:

2:25 foo;bar;blergh;blorgh

2:25 ?

2:25 sobel: pretty much. the rows containing the foo;bar are identified by the content of the 1st element

2:26 Empperi: ok, wait a sec then

2:27 sobel: there will be >1 blergh;blorgh (body rows)

2:27 ibash: Blergh

2:32 Empperi: sobel: https://www.refheap.com/b8917f48546768a06cf6b0dcf

2:32 should get you started

2:33 definetly not what you need exactly

2:34 sobel: i can mung my way through the code if i have a decent design target. so, the header row will come after a row with a start token. so there's a couple state transitions there.

2:37 vas: Hi, is it possible to reload changed html without restarting my lein server?

2:41 julianleviston: vas: I thought that was the default?

2:45 vas: Assuming you have :reload true set, or whatever that option is...

2:47 vas: most files definitely follow that behavior, but my html files are not being reloaded. perhaps firefox is the culprit...

3:23 devll: How to get the port of REPL?

3:25 ggherdov: devll: probably not the answer you expect, but: `netstat -tulpn | grep java` on my ubuntu machine

3:26 (in your shell, not in the REPL)

3:26 don't know how to make clojure tell you that

3:30 devll: I know this command.

3:30 I have many Java threads

3:31 noidi: devll, lein repl creates a file called .nrepl-port

3:31 devll: noidi: thx

3:34 noidi: which dir ?

3:35 I cant find it from current dir.

3:36 my bad. C

3:36 I found it.

3:37 ggherdov: Hello. I need a function (update-or-insert map key val func default) which takes a map, a key-val pair, a function.

3:37 If key is already in map, gives a new map where key is mapped to (func (key map) val). If key not present, gives a map where key is mapped to (func default val).

3:37 Example: values are numbers. If key present, sum w/ new value. If not, insert value (default is 0).

3:37 Does it exist already?

3:39 julianleviston: ggherdov: update-in? I’m not sure

3:39 ggherdov: julianleviston: uhm, that one overwrite if key's already there.

3:39 basically is a mix of the behaviours of update-in and assoc.

3:40 noidi: ,(merge-with + {:a 2} {:a 1, :b 2})

3:40 clojurebot: {:b 2, :a 3}

3:40 ggherdov: noidi: very many thanks

3:44 julianleviston: ggherdov: haha I’m sorry I had no idea what you meant from your description. My deficiency, I’m sure.

3:44 (inc noidi)

3:44 lazybot: ⇒ 1

3:45 hyPiRion: ggherdov: usually you can combine update-in and fnil

3:45 julianleviston: ggherdov: I don’t see how that fits your “defaults” requirement, tho

3:46 ggherdov: but like I said, I don’t understand the problem, really.

3:46 hyPiRion: ,(map #(update-in [:a] % (fnil + 10) 1) [{:a 1} {}])

3:46 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap>

3:47 hyPiRion: ,(map #(update-in % [:a] (fnil + 10) 1) [{:a 1} {}])

3:47 clojurebot: ({:a 2} {:a 11})

3:47 hyPiRion: ggherdov: key is :a, 10 is default, func is +, val is 1

3:47 that is your goal?

3:48 julianleviston: hyPiRion: if you only have one key, you don’t need to wrap it in a vec, I don’t think.

3:49 hyPiRion: julianleviston: you can use update if you're running 1.7, but it's still in alpha

3:49 ,[(update {:a []} conj 1) *clojure-version*]

3:49 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

3:50 julianleviston: hyPiRion: no, update-in…

3:50 hyPiRion: oh dear, I need my morning coffee

3:50 julianleviston: that doesn't work

3:50 ,[(update {:a []} :a conj 1) *clojure-version*]

3:50 clojurebot: [{:a [1]} {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}]

3:51 julianleviston: hyPiRion: right you are… I read the doc wrong.

3:51 hyPiRion: SO MANY MISTAKES! Julian… lurk more!

3:54 ggherdov: hyPiRion: thanks for the hint about fnil. Yes that's it

3:55 hyPiRion: hurray!

3:55 julianleviston: (inc hyPiRion)

3:55 lazybot: ⇒ 66

3:56 ggherdov: lol for inc-ing users :) I think ##java has something like that too

3:56 (the channel)

3:56 hyPiRion: yeah, many have some sort of bot

3:56 ggherdov: then ...

3:56 (inc noidi)

3:56 lazybot: ⇒ 2

3:57 ggherdov: what's right is right

4:09 zacts: hum I need to improve my clojure style

4:10 I find myself using map / reduce / filter like I did regexes in Perl

4:10 I don't think I use them for what they are supposed to be used for

4:11 although it seems it's better to use higher order functions than a recursive equivalent

4:11 (loop recur) in this case

4:12 I need to unlearn perl for clojure, oh well. It'll happen eventually. lol

4:13 hyPiRion: zacts: Stuff like that happens with experience. I'd suggest not to stress it :)

4:14 zacts: heh, yeah

4:22 kir: Greetings all. Trying to understand Clojure namespace; thought I understood it, until I replaced (ns kir.funcs) with (in-ns 'kir.funcs) in a lib - resulting in an error....

4:23 "Unable to resolve symbol: defn in this context, compiling:(kir/funcs.clj:7:1)[...]"

4:24 I was under the impression the (in-ns) would create a namespace for the lib, just as (ns) did?

4:25 Btw, I'm including the lib with : (use 'kir.funcs)

4:26 michaelr`: cursive users here?

4:26 or the cursive developer? ;)

4:27 hyPiRion: kir: No, in-ns makes the barebones of a namespace only

4:28 You would at least have to do something like (clojure.core/refer 'clojure.core) to get core functions, and probably some more if you want to be on the safe side

4:28 My suggestion is to just use ns :p

4:29 julianleviston: michaelr`: I’ve been using it since yesterday a little...

4:29 kir: hyPiRion, thanks for the tip, going to test...

4:29 michaelr`: julianleviston: :)

4:30 cfleming: michaelr`: What's up?

4:30 julianleviston: michaelr`: can I help?

4:30 jinagarano: i'm trying to set up a postgresql db for use with clojure. i'm running windows 7, installed postgresql, added the dependencies to project.clj. when i'm trying to create a table, i get an error "org.postgresql.util.PSQLException: Connection refused." hostname, port and user/password are correct. what could be the problem?

4:30 julianleviston: michaelr`: ooh even better… the main man of all things running writing :)

4:30 michaelr`: configure identation parameters, it's not always working

4:30 cfleming: sometimes it does.. but a lot of times it doesn't

4:31 is there already an issue open on this or I'm doing something wrong?

4:31 julianleviston: jinagarano: stupid question, but is it on?

4:31 jinagarano: that happens to me often.

4:31 jinagarano: how do i turn it on? no stupid questino there :)

4:32 cfleming: michaelr`: What are you doing to adjust the parameter?

4:32 kir: hyPiRion, that worked. Previously I had tried (refer 'clojure.core) to resolve it. I can see my error now. Thank you :)

4:32 julianleviston: jinagarano: sadly I don’t know on win… on the mac, I open it. You can set it up to always run, but I haven’t done that… and I’m not sure that it’s the default, depending on your installation.

4:32 michaelr`: cfleming: Alt-Enter on defonce, for example and then select 2 from the dropdown menu.

4:33 cfleming: michaelr`: Ok, and that doesn't work?

4:33 jinagarano: julianleviston: well, i can find that out. thanks!

4:34 hyPiRion: kir: np :) If you want to know more about how the ns macro works, you can try (require '[clojure.walk :refer [macroexpand-all]]) and do (macroexpand-all '(ns foo)). You could also attempt to read the source, but that's not always as easy

4:34 michaelr`: cfleming:

4:34 https://www.refheap.com/31ab32048689327cabf9d10bb

4:34 nope, here is an example ^^

4:35 hyPiRion: I find macroexpanding to be helpful when I don't know what happens behind the scenes

4:35 cfleming: michaelr`: That's correct for a setting of 2, if you want the next line indented, you want to set it to 1, or even better to Only Indent

4:35 michaelr`: I need to put some text on the website explaining that parameter

4:36 michaelr`: indeed 1 worked :)

4:36 I though it was about the number of tabs/characters to indent

4:36 cfleming: michaelr`: Here's how this works - this is designed for macro forms. They generally have a number of parameters, and then a body.

4:36 michaelr`: oh cool, i get it

4:37 this is the number of params

4:37 cfleming: michaelr`: That number is the number of elements after the head symbol that Cursive will assume are parameters

4:37 michaelr`: Right.

4:37 michaelr`: great

4:37 wish I knew that earlier

4:37 ;)

4:37 cfleming: michaelr`: The parameters get lined up, and the rest of the elements are assumed to be the body and are indented by 2

4:37 kir: hyPiRion, cheers, I was actually wondering how macro expansion works.

4:37 michaelr`: ok

4:38 cfleming: michaelr`: Yeah, my doc requires a little inventiveness, sadly

4:38 michaelr`: btw, thanks for Cursive

4:38 Especially the wonderfull debugger

4:38 it's a life saver

4:38 cfleming: michaelr`: If you set it to only indent, then everything after the head symbol will be just indented by 2 spaces - this is good for defn-like things

4:38 michaelr`: No worries, I'm glad it's working for you!

4:38 clojurebot: Cool story bro.

4:39 cfleming: michaelr`: More bugfixes in the next drop, expression eval should be more reliable

4:39 michaelr`: the debugger really improved in the last version

4:40 cfleming: michaelr`: Yeah, I totally broke it in the previous one, and while I was fixing that I fixed a lot of other things.

4:40 michaelr`: I use the debugger all the time, I wish I'd done that a year ago, it only took two days ;)

4:40 michaelr`: heh

4:41 hmm

4:41 cfleming: michaelr`: Now that expression eval works, it's a small step to a debug REPL when you're stopped at breakpoints

4:42 michaelr`: used it yesterday, it actually works :)

4:42 cfleming: The eval?

4:42 michaelr`: yes

4:42 cfleming: Yeah

4:42 michaelr`: Alt-F8

4:42 cfleming: I can't believe I lived without it for so long, or at least with a seriously broken version

4:44 IntelliJ 14 has some really nice debugger enhancements in Java, I have to see how many of them I can make work

4:44 michaelr`: Is there an option somehow to set up a shortcat to eval (user/reset)?

4:44 shortcut

4:44 julianleviston: cfleming: is there a good video walkthrough on cursive?

4:44 cfleming: michaelr`: Unfortunately no, see https://github.com/cursiveclojure/cursive/issues/85

4:44 julianleviston: Sadly there isn't even a bad one

4:45 julianleviston: It's somewhere on my to-do list

4:46 julianleviston: cfleming: delegate! :)

4:46 cfleming: julianleviston: Hehe. There are a couple that help with getting it set up, but they don't go into great depth.

4:47 julianleviston: cfleming: I watched an install video the other day… can’t remember where it was but apparently there was a second video but I can’t remember where it was

4:47 michaelr`: cfleming: good to know that other people experience the same pains and needs as I do..

4:47 julianleviston: cfleming: ah yes.

4:47 michaelr`: cfleming: +1 mouseless jump to repl

4:47 julianleviston: jony epsilon…

4:47 http://vimeo.com/103808402

4:48 cfleming: michaelr`: Yeah, I think I'm pushing 300 open issues these days. Whatever your heart desires is probably in there somewhere.

4:48 julianleviston: Yeah, Timothy Baldridge has one too

4:48 julianleviston: cfleming: is it all self?

4:48 cfleming: are you going to do all of this stuff yourself?

4:48 cfleming: julianleviston: Well, mostly.

4:49 julianleviston: I'm working on an extension API, in the short term that will be for adding symbol resolution for 3rd party libs

4:49 julianleviston: cfleming: I don’t want to be rude about jony but it’d be nice if he edited his videos a bit… and I find his audio could do with some compression

4:49 cfleming: julianleviston: In the long run people will be able to add more complex functionality, but developing a good API takes time

4:50 julianleviston: Try Timothy's and see if it works better for you

4:50 julianleviston: cfleming: it’s purchase?

4:50 cfleming: julianleviston: There's one free and one non-free on CLJS

4:51 I have 305 open issues. Fortunately I have 421 closed issues, so I'm still winning.

4:52 julianleviston: cfleming: god I wish I would hurry up and finish the project I’m working on so I could start on my the pedagogical project I really want to do.

4:53 kir: michaelr`, " cfleming: +1 mouseless jump to repl" - only possible, through custom keymap

4:53 already*

4:58 michaelr`: kir: please share :)

5:00 julianleviston: cfleming: I really wish that the REPL was even more tightly integrated with the IDE…

5:00 cfleming: generally, not specifically to cursive.

5:01 cfleming: I want the forms I’m editing to be the live forms in the “REPL”.

5:01 kir: michaelr`: Settings -> Keymap -> In the keymap list there is "Other" -> in that list there is "REPL" - I've set mine to alt+0

5:02 michaelr`, press esc when you're in the REPL to get back to your code

5:04 TEttinger: (inc kir)

5:04 lazybot: ⇒ 1

5:07 cfleming: julianleviston: You mean like a LightTable style instarepl?

5:12 julianleviston: cfleming: Sort of. LT still has a separate process than the source. I mean that the “source” *is* the live data structures. So if you have a (def x 5) and you change that 5 to 10, it does a reload… to do this, you’d have to mod clojure quite a bit, I imagine… stuart sierra was barking up this tree a bit with his component workflow… I’d like my “source” to be actual live data within a VM… and for it to

5:12 able to describe itself rather than the opposite 2 - step process which is REPL driven development.

5:14 cfleming: so… editing that 5 to a 10 is changing the value in memory first… and only then serialising it to display and/or text for the source… if that makes sense. It’s really not possible at the moment, AFAIK… but we could get there… and it’d be… amazing. Because then you really could use the full power of LISP on the data structures that comprise the program, if that makes sense...

5:15 cfleming: julianleviston: Sure - I'm not sure what the practical difference of that is from modifying the text and have it update though

5:16 julianleviston: cfleming: when your “source” isn’t text, interesting things can happen (as I’m pretty sure you know). A lot of errors would be impossible… like creating an invalid data structure, or a syntax error...

5:17 cfleming: You’d effectively get live linting for free.

5:18 cfleming: and a whole raft of different kinds of editors would be pretty trivial… like the gorilla REPL… because you could simply plug functions into your editor, right? :-) it’s all just functions.

5:18 cfleming: I think macros break things, tho… because they’re inherently tied to reading… perhaps. Anyway, it’s just an interesting idea, really :-)

5:19 cfleming: The problem is that you still have to represent your program somehow, probably as something similar to the text we use now. And it's still a two step process since that doesn't get evaluated directly, it gets compiled.

5:21 julianleviston: cfleming: yep. It depends how you view your source of truth. Smalltalk VMs are an interesting example… file in / file out… of pure true data structures that can’t be “broken”.

5:21 cfleming: I think shifting as much of our “stuff” (as programmers) into data as possible is the best idea… given that that’s where flexibility lies.

5:22 cfleming: but yeah, good points, as always.

5:25 cfleming: julianleviston: I definitely think it's good to think about these things, but I struggle to see a useful path to actually making a real editing environment out of them. I haven't looked closely at Eve, I should take another look at it.

5:25 julianleviston: cfleming: I guess we’ll see what chris granger’s next project eventuates as ;-)

5:25 cfleming: oh yeah, that’s what it’s called? Last time I looked it was called aurora… does it have a way one can look at it now?

5:25 cfleming: last time I looked (preview video) it had gone too far, IMHO…

5:26 a lot of times when people try to simplify, they go a bit too far.

5:26 “Lovely, but limited” springs to mind.

5:26 cfleming: I think the language is Aurora and the environment is Eve?

5:26 Not sure.

5:27 michaelr`: kir: i mean, I have the repl tool window mapped to Alt-6 and there is

5:27 F12 but often it wouldn't go to the command prompt. another thing

5:27 is that I would often like to switch to the console in the repl in

5:27 order to examine a long exception

5:27 sorry, was disconnected

5:29 cfleming: michaelr`: Yeah, the solution is basically what kir said right now. Alt-num to go to REPL, and esc to go back

5:32 kir: cfleming: Btw, I really appreciate the multi-line-input REPL; thanks.

5:32 cfleming: kir: No worries, glad you're liking it. I use that a lot too.

5:34 julianleviston: cfleming: this is the only thing I’ve seen of aurora: https://www.youtube.com/watch?v=L6iUm_Cqx2s

5:34 cfleming: julianleviston: Yeah, me too

5:34 julianleviston: cfleming: I had an almost visceral reaction to the tonal quality of his voice.

5:36 cfleming: julianleviston: More than that, I just wasn't very excited by the video

5:36 I guess sooner or later someone will reinvent programming, but I haven't seen anything that shouts that to me yet.

5:38 julianleviston: cfleming: yeah, it just seemed like another mathematica to me… and it seemed to not be building on the past, but kind of clearing it out… which made me a bit sad… the main thing I dislike, though, is that the system can’t be modified from within itself, or applied to itself… it’s not homoiconic… not that most interfaces are, but I expect that…

5:38 cfleming: I feel that frank (VPRI) or even seaside are more advanced.

5:39 but hey, what have I done latel? :-) they’re doing good work.

5:39 latel*

5:39 lately* (sigh)

5:39 cfleming: as are you! :) <3

5:40 TEttinger: you've made typos lately :D

5:40 julianleviston: TEttinger: boy have I! :)

5:40 cfleming: Absolutely, kudos to them for trying. I'm interested to see more of what they come up with. I'd just like to feel more optimistic about it.

5:41 TEttinger: it's interesting how a number of questions have popped up in ##fsharp about clojuresque usage of the language (code as data and calling things by string name), which seems very difficult in such a strictly typed language

5:42 julianleviston: cfleming: if they can get simple while keeping advanced capability (or some way of traversing them) then it’ll be cool… that’s (interestingly) what my primary interest is.

5:52 Is a vec of 3 elemet vecs the best way to represent a tuple?

5:53 Acutally nevermind. It’s small. I’ll just use that.

5:53 Glenjamin: it is the simplest

5:53 julianleviston: Glenjamin: I really meant a collection with three elements. If it were large, I’d use a vec of records, yeah?

5:54 Glenjamin: large number of elements, or large number of items?

5:55 actually, i don't really know the answer either way

5:55 julianleviston: Glenjamin: elements… all good. Depends what the criteria are. HeHe :)

5:55 Glenjamin: i know there's an optimised tuple implementation available if you need high perf short-tuples

5:55 julianleviston: Glenjamin: thanks, I’ll keep that in the back of my mind.

6:16 luxbock: what is the etiquette for using someone elses work in your own library? I'm building a REPL util library for myself, and I'd like to use print.foo but do some changes that might not jive with the author, though I haven't asked yet

6:16 I'd obviously give attribution to the author, but is there something beyond that I should do if I'm just going to rip a huge part of someone elses useful library and do some tiny tweaks?

6:18 julianleviston: luxbock: you’d probably be best advised to ask him. Different folks have different ideas of what’s reasonable.

6:18 (or her)

6:18 luxbock: alright, I'll ask him how he'd feel about the changes I'd like to make

6:18 Glenjamin: if all else fails, you'll want to follow the license terms

6:19 luxbock: yeah, it's MIT license

6:21 TEttinger: MIT doesn't even require attribution IIRC

6:21 you can't change the license on the MIT-licensed files, but that's about it

6:22 luxbock: yeah I know the license allows me to do what I want, but I was more curious about the etiquette :)

6:22 TEttinger: tell him, thank him, change your fork at will?

6:22 luxbock: yep I'll do that, thanks

7:58 justin_smith: TEttinger3: rubyists giving f# a go? (regarding using code as data)

8:15 NhanH: Is there anyway you can format ring stacktrace with lein plugin like ultra ? (Ie when I'm running as `lein ring server-headless` and error popup, it formatted nicely)

8:15 justin_smith: NhanH: you could replace the wrap-stacktrace middleware

8:17 NhanH: do you mind elaborate a bit? (I have no idea how lein plugin work), so basically, I need to replace the wrap-stacktrace middleware without whatever the plugin is using to format the s tacktrace, right?

8:17 justin_smith: it's not a lein plugin

8:17 but yeah

8:18 NhanH: what is not a lein plugin? Middleware?

8:18 justin_smith: right

8:18 lein is for build time

8:18 NhanH: yeah I know

8:18 justin_smith: a lein plugin could only help with errors during dep resolution / startup

8:18 it can't help you at runtime

8:19 NhanH: okay thanks. So I guess the follow up question would be: is there any middleware to format ring stacktrace?

8:20 justin_smith: like I said, wrap-stacktrace does that, and if you don't like its formatting, you could make your own based on what ultra does

8:20 https://github.com/mmcgrana/ring/blob/master/ring-devel/src/ring/middleware/stacktrace.clj

8:22 NhanH: this is what wrap-stacktrace does: http://i.imgur.com/67oFIEf.png

8:23 NhanH: I tried that earlier, and I think that's the default behaviour of ring even if you don't put the middleware in. But yeah, that stacktrace is still a bit annoying

8:23 Thanks anyway

8:24 justin_smith: NhanH: ok, so we have the other option, making some other handler based on wrap-stacktrace, with behavior more like ultra

8:26 NhanH: seems like time to read ultra source! :-)

9:46 vas: is there an idiomatic way to serve a favicon with compojure or ring?

9:46 justin_smith: vas: typically I use a middleware that special cases "favicon.ico" no matter what the leading path is

9:48 vas: justin_smith: coo. thanks for your <input>

9:48 =]

9:51 i'm not really sure what the favicon request even looks like to write code to handle it in my barebones routing..

9:51 justin_smith: vas: https://www.refheap.com/96939

9:52 it's a bit convoluted (those abstractions make sense with my other custom middlewares) but it works

9:53 refer-favicon is a middleware that can be used in the same way you use any other ring middleware

10:02 vas: just updated that paste with a simpler version at the bottom https://www.refheap.com/96939 that doesn't rely on the other defs

10:13 thesaskwatch: Hi .. anyone knows how to disable emacs prompt asking about file save before evaluating file via cmd+c cmkd+k ?

10:13 the_frey: M-x customise might present an option to disable it?

10:16 thesaskwatch: the_frey: clever ;)

10:19 ordnungswidrig: thesaskwatch: you can defun a function that calls save-buffer and cider-eval-buffer

11:05 acron^: hey all

11:05 I'm having trouble reading from a file

11:05 https://www.refheap.com/96945

11:05 I only want to read the first 5 lines

11:05 but I keep getting Caused by: java.io.IOException: Stream closed

11:06 Exception in thread "main" java.io.IOException: Stream closed

11:06 if I only inspect the first line, it work fine ...

11:06 justin_smith: acron^: map is lazy, you need to force the results you use before leaving the "with-open" context

11:06 julianleviston: acron^: is LF what you think it is?

11:06 ordnungswidrig: acron^: I guess that line-seq is lazy. Until you try to evaluate the whole seq the reader is closed

11:06 julianleviston: justin_smith: ah… cool :)

11:07 justin_smith: acron^: what happens is that by the time the map tries to do its thing, you are outside the with-open block

11:07 ordnungswidrig: acron^: (doall lines) might help

11:07 justin_smith: acron^: use (doall (take 5 (map ...))) if you need to use with-open

11:07 or yeah, actually just adding a doall

11:08 acron^: also, (nth (take 5 sq) 5) will always be nil

11:08 ordnungswidrig: it's actually when `map` want's to do it's thing but when (nth lines 1) forces seq

11:08 julianleviston: that code could deal with some reformatting

11:08 ordnungswidrig: that should read "actually not when `map`..."

11:09 acron^: julianleviston: i am really open to suggestion

11:09 i'm pretty new to clojure

11:09 julianleviston: it’s not immediately obvious where the let block bindings ends.

11:09 justin_smith: ,(nth (take 5 [1 2 3 4 5]) 5)

11:09 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

11:09 justin_smith: oh yeah

11:09 not even nil, it's an exception :)

11:09 ,(nth (take 5 [1 2 3 4 5]) 4)

11:09 clojurebot: 5

11:10 justin_smith: ,(nth (take 5 [1 2 3 4 5]) 5 nil)

11:10 clojurebot: nil

11:10 acron^: sorry

11:10 the 5 was an error

11:10 justin_smith: (if you don't want the exception behavior, you can provide a default)

11:10 acron^: should be 4

11:10 justin_smith: right

11:10 ordnungswidrig: acron^: #(convert-line %) can be simplified to convert-line, unless that's a macro

11:10 acron^: ordnungswidrig: face-palm, oh yeah :)

11:11 sorry im still not 100% where i need to add thi9s doall

11:11 julianleviston: acron^: this is what I’d write it as… https://gist.github.com/JulianLeviston/c5def8e78eeca9f1eaba

11:11 acron^: around the with-open

11:11 ?

11:11 justin_smith: acron^: (doall (map ...))

11:11 acron^: once you leave the with-open, it's too late, the with-open is closed

11:12 so you need to force the result before the with-open exits

11:12 acron^: ahhh

11:12 that worked perfectly

11:12 ok

11:12 so

11:12 justin_smith: it's as if you opened the gate, said "when I ask for an apple, get one from that tree, closed the gate, and then asked for an apple

11:12 missed a close " up there

11:13 acron^: nice analogy :)

11:13 ordnungswidrig: acron^: make sure that you "take" within the "doall" or you will force the whole file even if you process only the first n lines

11:13 acron^: nice analogy :)

11:13 oops

11:13 justin_smith: ordnungswidrig: yeah, in the original the take is inside the map call

11:14 acron^: new version: https://www.refheap.com/96947

11:14 works a treat :)

11:14 justin_smith: the first 4 should maybe be a 3? just a guess

11:15 acron^: you'd have thought so, wouldn't you?

11:15 actually the file format author decided to put 2 vars on that line, space-separated

11:15 ordnungswidrig: n acron^: a more idiomatic version https://www.refheap.com/96946

11:15 acron^: and leave blank the line above

11:16 what's the ->> notation?

11:16 ordnungswidrig: acron^: a very importand short cut to avoid (nested (deep (burried (whatever (function calls)))))

11:17 acron^: (->> [1 2 3 4] (map odd?)) => (map odd? [1 2 3 4 5])

11:17 julianleviston: acron^: it’s the human centipede of clojure…

11:17 justin_smith: ,(let [nums [1 2 3 4 5] [a b c] nums] c) ; acron^ - this is another trick that may help you

11:17 clojurebot: 3

11:17 acron^: julianleviston: oh god, i hope not!

11:18 ordnungswidrig: acron^: ->> takes the first argument and inserts it as the last argument in the following expression. Then it takes the result and inserts it as the last argument to the next expression and so on.

11:18 it a so called "threading macro".

11:18 julianleviston: acron^: there are two variants… -> feeds the output into the first arg of the next form… and ->> feeds the output into the last arg of each form.

11:18 justin_smith: acron^: the threading macros (-> / ->>) are for propagating data through expressions

11:18 acron^: Ah ok, how does it differ to just -> cs ive seen that too

11:18 Aha

11:18 ordnungswidrig: -> inserts as the first argument, ->> as the last

11:18 acron^: Got it

11:18 julianleviston: acron^: :) so pretty.

11:19 ordnungswidrig: some-> stops as soon as there's a falsey value (typically nil)

11:19 where handy for, e.g. (some-> x inc)

11:19 julianleviston: ordnungswidrig: better explain as-> as well! :-)

11:20 ordnungswidrig: and there are cond-> and as-> which are advanced variations

11:20 justin_smith: ,(some-> {false :ordnungswidrig} false str)

11:20 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn>

11:20 justin_smith: hrmph

11:20 ,(some-> {false :ordnungswidrig} (get false) str)

11:20 clojurebot: ":ordnungswidrig"

11:21 justin_smith: that never returned false though, I need coffee

11:21 lol

11:21 ordnungswidrig: hahaha

11:21 (inc coffee)

11:21 lazybot: ⇒ 1

11:21 ordnungswidrig: no wonder...

11:21 justin_smith: (some-> {:a false} :a)

11:21 ,(some-> {:a false} :a)

11:21 clojurebot: false

11:22 justin_smith: ,(some-> {:a false} :a inc)

11:22 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number>

11:22 justin_smith: as expected

11:22 ,(some-> {:a nil} :a inc)

11:22 clojurebot: nil

11:22 justin_smith: ordnungswidrig: as we see, only nil short-circuits some->

11:22 false does not

11:22 fortruce: if I want to map a function with side effects over a seq, is there a way to do it such that I don't have to hold the entire seq in memory as it's being done?

11:22 acron^: justin_smith: https://www.refheap.com/96948

11:23 justin_smith: fortruce: dorun

11:23 fortruce: or use doseq instead of map

11:23 fortruce: justin_smith: thanks, i'll check those out

11:23 justin_smith: acron^: yeah, destructuring is pretty cool, huh

11:23 ordnungswidrig: justin_smith: oh, I did not know that. I wonder why.

11:23 justin_smith: ordnungswidrig: some-> is specifically for nil

11:23 ,(doc some)

11:23 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

11:24 justin_smith: ,(doc some->)

11:24 clojurebot: "([expr & forms]); When expr is not nil, threads it into the first form (via ->), and when that result is not nil, through the next etc"

11:24 ordnungswidrig: I can live with that ;-)

11:25 julianleviston: oooh

11:25 oh nevermind.

11:25 lol @ self

11:25 justin_smith: acron^: you could also replace the binding of lines with the destructure directly, but that's a style decision

11:26 julianleviston: acron^: you could also use interpose “\n” if you get bored of all those \n repetitions.

11:26 justin_smith: julianleviston: it's a little trickier with a 3 item pattern though - unless there is some interpose / concat trick

11:28 ,(apply concat (interpose ["\n"] [[:a :b] [:c :d] [:e :f]]))

11:28 clojurebot: (:a :b "\n" :c :d ...)

11:28 justin_smith: that works, kind of, but a little clumsy

11:29 tcrayford____: so yesterday I open sourced a clojure webapp profiling tool: Clojure Miniprofiler: http://yellerapp.com/posts/2015-02-04-miniprofiler.html (in case anybody here does webapp server performance work in clojure). I'd love to hear any feedback anybody has

11:30 justin_smith: tcrayford____: COOL, I'll definitely check that out

11:30 lunk: hello, is there a more idiomatic way to do fall-back tests for resolving parameters/environment variables? http://pastebin.com/Ef2d66QY

11:30 apparently beanstalk says env, but means params, for their tomcat container

11:31 havenwood: tcrayford____: ooh, nifty!

11:36 julianleviston: justin_smith: I love clojure… ## (apply str (map #(apply str %) (let [newlines-every-second-element (comp (partial interpose "\n") (partial partition 2))] (newlines-every-second-element ["a" "b" "c" "d"]))))

11:36 lazybot: ⇒ "ab\ncd"

11:37 julianleviston: justin_smith: very silly of me, I know… but I like that I can build my own custom function to do whateve I like quite efficiently as if it was a first class function. Not that my version there was particularly elegant, but yeah :)

11:40 acron^: justin_smith: https://www.refheap.com/96948

11:40 oops

11:40 sorry

11:40 keep pressing up-enter

11:41 julianleviston: ,(defn interpose-nth [n i coll] ((comp (partial interpose i) (partial partition n)) coll))

11:41 clojurebot: #'sandbox/interpose-nth

11:41 julianleviston: ,(interpose-nth 2 "\n" [1 2 3 4])

11:41 clojurebot: ((1 2) "\n" (3 4))

11:42 julianleviston: not *quite* what I was after hm.

11:42 acron^: Random question - how do I specify mutiple things in :require ?

11:42 julianleviston: (:require [om.core :as om :include-macros true] …)

11:42 replace the … with as many of those bracketed sections as you like...

11:42 acron^: assuming you’re talking about the ns require?

11:43 dnolen: cfleming: ping

11:43 acron^: julianleviston: yes, thanks

11:43 it's giving me grief

11:46 thanks, i was doing something weird

11:46 julianleviston: just looking at the interpose source humbles me.

11:46 acron^: lol

11:47 julianleviston: :)

11:59 is there a thing like when-let which has a separate predicate function instead of the first binding?

11:59 (uknown-fn predicate [bindings…] (fn body)…)

12:00 I guess I could just do what I usually do: wrap a let in a when...

12:00 justin_smith: julianleviston: that would be an easy macro to write

12:00 llasram: julianleviston: You want the maybe monad from algo.monads

12:00 (although I do think it'd be nice if `maybe`-specialized version of it were in core)

12:01 julianleviston: I basically want (when-not empty? [x thing] ...)

12:02 gfredericks: julianleviston: use seq

12:02 julianleviston: i want when to be predicate-pluggable hehe :)

12:02 gfredericks: (when-let [x (seq thing)] ...)

12:02 justin_smith: gfredericks: or (when-let [x (not-empty thing)] ...) so that you still get the original datatype if it isn't empty

12:02 julianleviston: gfredericks: ooh cool :)

12:03 justin_smith: ,(not-empty [1 2 3])

12:03 llasram: (am/domonad am/maybe-m [x (f), :when (pred1? x), y (g), :when (pred2? y)] [x y])

12:03 clojurebot: [1 2 3]

12:03 julianleviston: justin_smith: mind being bent. ;-)

12:03 ,(not-empty [])

12:03 clojurebot: nil

12:03 gfredericks: justin_smith: not-empty is a funny function

12:03 justin_smith: gfredericks: I am very fond of it

12:03 julianleviston: ,(empty [:a :b :c])

12:03 clojurebot: []

12:03 gfredericks: it smells wasteful to my prematurely-optimizing gut

12:04 justin_smith: gfredericks: for example, (when-let [x (seq {:a 0 :b 1}] ...) - not-empty is a clear winner here

12:04 gfredericks: since it has to make a whole seq just to find out if something is empty

12:04 julianleviston: justin_smith: it *is* more sematically explanatory

12:04 justin_smith: gfredericks: "make a whole seq" doesn't neccessarily mean doing much work

12:04 julianleviston: justin_smith: as well

12:04 thanks both!

12:04 (inc justin_smith)

12:04 lazybot: ⇒ 181

12:04 julianleviston: (inc gfredericks)

12:04 lazybot: ⇒ 116

12:04 gfredericks: justin_smith: I know it's just an object allocation that feels silly

12:05 justin_smith: gfredericks: sure, but (when-let [x (seq y)] ...) doesn't improve on that much does it?

12:06 gfredericks: justin_smith: oh no, I wasn't making that comparison

12:06 julianleviston: I’d still prefer do have (when pred let-bindings) tho

12:06 justin_smith: OK, got it

12:08 ontoillo1ical: Is it possible for me to import testing namespaces from another project? I.e. I want to import his ns https://github.com/clojure-liberator/liberator/blob/master/test/checkers.clj, is there anyway to do that?

12:08 gfredericks: ontoillo1ical: tests aren't normally packaged with libraries, so you couldn't do that in any normal way

12:08 justin_smith: julianleviston: this does what you want (defmacro pred-let [cond bindings & body] `(when ~cond (let ~bindings ~@body)))

12:09 ontoillo1ical: gfredrick: thanks, I guess I'll just copy it into my own lib

12:09 julianleviston: justin_smith: I’m macro-averse…

12:09 andyf_: ontoillo1ical: If licenses are compatible or you get author's permission, you can copy the source

12:09 justin_smith: julianleviston: the macro is already done, and let and when etc. are macros already :)

12:09 julianleviston: justin_smith: but thanks heaps… I know half the language I use is macros… :)

12:09 justin_smith: julianleviston: it's a simple macro, it just works

12:10 julianleviston: justin_smith: macros also scare me from cljs… only because I’ve never built one and had it work

12:11 justin_smith: OK. If you want a better syntax, the answer is going to be a macro (though sometimes you can express something more elegantly in the existing syntax (using the macros that exist already))

12:11 csd_: ,(let [[f s] (clojure.string/split "split me" #" ")] [f s])

12:11 clojurebot: ["split" "me"]

12:11 andyf_: arrdem: Have you by any chance asked ClojureDocs folks if they mind if Grimoire tracks updates made to ClojureDocs in the future? Or were you planning on letting them gradually diverge?

12:12 Well "planning" might not be the most precise use of language there :)

12:12 csd_: The clojure.string/split docstring is misleading

12:12 bbloom: ignore the crazy transducer version... the source is just (drop 1 (interleave (repeat sep) coll)) :-)

12:12 andyf_: csd_: How so?

12:12 csd_: Optional argument limit is the maximum number of splits => ["x" "y"] is one split, not two

12:13 ,(let [[f s] (clojure.string/split "split me" #" " 1)] [f s])

12:13 clojurebot: ["split me" nil]

12:14 llasram: (doc clojure.string/split)

12:14 clojurebot: "([s re] [s re limit]); Splits string on a regular expression. Optional argument limit is the maximum number of splits. Not lazy. Returns vector of the splits."

12:15 {blake}: I take that "split" as a noun, not a verb.

12:15 llasram: csd_: I think the fact that it "returns a vector of the splits" clarify that "split" here refers to one of the resulting split-off strings, no the split-point

12:15 {blake}: i.e., "number of splits" <> "number of times I will split this" but "number of pieces resulting".

12:15 julianleviston: {blake}: split is the gap between things, not the things

12:16 llasram: I've always found it weird in Python you specify the number of split points

12:16 julianleviston: {blake}: if you split wood in two, you’re splitting it once into two pieces… or… it is a single piece of wood with one split in it.

12:16 arrdem: andyf_: "planning" is pretty generous for me :P

12:17 justin_smith: it's just verb vs. noun, in clojure you clearly specify noun (how many results) in python the verb (how many times to perform the splitting action)

12:17 arrdem: andyf_: the plan such as it is was to at some point go through all the examples and copy edit everything rather than just mirroring the clojuredocs examples

12:17 andyf_: reality is that other things were and are higher priority :c

12:18 julianleviston: justin_smith: yeah but “pieces” would be a better word. The noun split means gap between pieces

12:18 andyf_: arrdem: Yeah, that is a big job

12:18 {blake}: julianleviston: If you're dividing up loot from your heist, you each get a split. =P

12:18 arrdem: andyf_: it's much smaller than it sounds, but yeah it's just time with a text editor and thinking about each fn

12:19 justin_smith: {blake}: exactly

12:19 andyf_: Well, maybe I am slow at it, but there are over 600 vars in Clojure alone

12:19 {blake}: julianleviston: See definition "split (noun)" 2, 3b, & 5. http://www.merriam-webster.com/dictionary/split

12:19 justin_smith: "a piece or part separated by or as by splitting"

12:19 julianleviston: {blake}: it’s not the primary definition…

12:19 arrdem: andyf_: done with HW for the week so I'm gonna try and get all the ox stuff out of my head and crunch on Grimoire before SimpleDB takes the site down again. I'd be happy to talk to the clojuredocs folks if you think it'd be useful.

12:19 {blake}: That's English for ya. There is no noun that cannot be verbed! And vice-versa!

12:19 justin_smith: {blake}: if only we could make string/split give you an ice cream sundae containing a banana

12:20 julianleviston: justin_smith: now I’m hungry :)

12:20 {blake}: justin_smith: Ha! That would be...python-esque somehow.

12:20 justin_smith: clojure.banana could have other useful functions in it too

12:20 {blake}: Homonyms, man. I tell ya.

12:20 andyf_: I only ask because if they don't mind you periodically updating the parts if Grimoire from there to the latest, it might be nice.

12:21 s/if/of/

12:22 {blake}: Homonyms really suck in other languages. "I already learned this means 'criminal gang', whaddayamean it's also "893"?"

12:22 arrdem: yeah. that would be nice... but getting a real editing workflow added would be nicer.

12:22 justin_smith: {blake}: that's why on the chinese internet they always call politicians "mud horse"

12:22 julianleviston: {blake}: grass mud horse...

12:23 justin_smith: that's the one, yeah :)

12:23 julianleviston: {blake}: it’s a homonym for something really rude about your mother.

12:23 {blake}: Nothing makes me happier than a defiant populace.

12:23 andyf_: arrdem: Your edit examples link could go to ClojureDocs :)

12:23 justin_smith: http://chinadigitaltimes.net/space/Grass-mud_horse

12:23 arrdem: andyf_: rofl then I may as well just close down Grimoire

12:24 justin_smith: "Originally conceived as a zebra, the grass-mud horse is now an alpaca."

12:24 arrdem: andyf_: which isn't on the cards since I just made it into gigasquid's book :P

12:24 julianleviston: {blake}: irrespective, the word is ambiguously used. Which was the problem.

12:24 andyf_: Currently you do have info they do not, e.g. Thalia content (not a lot, but something)

12:24 julianleviston: {blake}: change it to piece, and it wouldn’t be.

12:25 andyf_: Which gigasquid book is that?

12:25 arrdem: Living Clojure

12:25 http://shop.oreilly.com/product/0636920034292.do

12:25 {blake}: julianleviston: I'm all for doc improvement.

12:26 arrdem: andyf_: thinking of which I probably owe you a lib-grimoire backed thalia version...

12:26 {blake}: So..."Joy of Clojure 2ed" is over $40?

12:26 justin_smith: {blake}: following some more links there, I found the delightful euphamism "death by hide and seek"

12:26 {blake}: worth every penny!

12:26 julianleviston: {blake}: yeah.

12:26 arrdem: something something datastore duplication.

12:26 {blake}: totally worth

12:27 julianleviston: {blake}: makes me sad, too. I don’t have $40 to spend on it and I’ve wanted it for about a year.

12:27 {blake}: justin_smith: If that were French, I'd guess it was sexual.

12:27 julianleviston: {blake}: let alone 50+ which is what it is here...

12:27 matzie: hi, noob qn:- given a map like {:a "apple" :b "banana" :c "cherry"} , how would I create a string joining the values for some of those keys with a period, eg for :a and :c I’d want the output “apple.cherry” ?

12:27 justin_smith: {blake}: reminds me of soviet humor

12:27 bbloom: talk to your employer about starting a company library

12:28 julianleviston: matt_c: SOME of them?

12:28 matzie: bah sorry if that got emoticon’d for you

12:28 {blake}: So far I haven't had much luck with Clojure books. They tend to caught up in the weeds. Although, I'm now at the point where I can appreciate some of those weeds, and am grateful the books exist.

12:28 bbloom: ask other employees to donate their books

12:28 julianleviston: matt_c: you want “:a,:b,:c” ?

12:28 justin_smith: ,(map (fn [[k v]] (str (name k) \. v)) {:a "apple" :b "banana" :c "cherry"})

12:28 clojurebot: ("c.cherry" "b.banana" "a.apple")

12:28 matzie: I want to pick some keys from the map and construct a string from them

12:28 justin_smith: ahh

12:28 llasram: ,(let [m {:a "apple", :b "banana", :c "cherry"}, keys [:a :b]] (clojure.string/join "." (map m keys)))

12:28 clojurebot: "apple.banana"

12:28 {blake}: justin_smith: In Soviet Russia, the joke's on you?

12:28 justin_smith: oops!

12:28 julianleviston: matt_c: ah… well

12:28 matt_c: select-keys will get you specifc keys...

12:29 oops

12:29 justin_smith: {blake}: no, I mean actual jokes from soviet russia (like the one about the man who stole stalin's pipe)

12:29 julianleviston: matzie: but you mean you want the values of particular keys…

12:29 {blake}: justin_smith: Oh, I only know a few of those. "In five years, every Soviet citizen will have helicopter!"

12:29 justin_smith: right

12:30 matzie: (actual context is a riemann event that goes to influxdb, triying to set :series to the value of :host and :service … but I’m climbing a whole lot of learning curves simultaneously)

12:30 and i don’t yet know enough clj to understand the riemann doc on this case

12:31 {blake}: (They're actually not much funnier in the original Russian...)

12:31 justin_smith: ,(apply (partial clojure.string/join \.) ((juxt :a :c) {:a "apple" :b "banana" :c "cherry"}))

12:31 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: string/join>

12:32 justin_smith: ,(clojure.string/join \. ((juxt :a :c) {:a "apple" :b "banana" :c "cherry"})

12:32 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

12:32 justin_smith: ,(clojure.string/join \. ((juxt :a :c) {:a "apple" :b "banana" :c "cherry"}))

12:32 clojurebot: "apple.cherry"

12:32 julianleviston: matzie: well, you set something in a map with the assoc function...

12:32 matzie: ##(doc assoc)

12:32 lazybot: ⇒ "([map key val] [map key val & kvs]); assoc[iate]. When applied to a map, returns a new map of the same (hashed/sorted) type, that contains the mapping of key(s) to val(s). When applied to a vector, returns a new vector that contains val at index. Note - index must be <= (count vector)."

12:33 matzie: ah… justin_smith ’s answer is making sense.

12:33 julianleviston: matzie: oh ok :)

12:33 justin_smith: (inc juxt)

12:33 lazybot: ⇒ 19

12:34 justin_smith: matzie: though select-keys would work better if the keys were eg. strings instead of keywords

12:35 matzie: so… I have a map, ‘event’, already which contains many keys, of which I want to take two (:host and :service), and create a period-separated string from those… I think I can work with this info, thanks all

12:35 justin_smith: np

12:39 gfredericks: could refs & stm & such be a library?

12:39 I guess they interact with agents pretty closely

12:40 justin_smith: gfredericks: I think refs + agents would want to be one lib

12:40 gfredericks: but atoms, apropriately, could stand on their own :)

12:44 gfredericks: also, you would probably end up with futures+agents using separate pools instead of sharing one

12:45 hiredman_: if the stm exposed hooks for detecting transaction commits (which I am pretty sure ztellman wants, I seem to recall discussing this in a loud bar) agents could just hook in

12:45 justin_smith: oh, that's interesting

12:46 gfredericks: ~this |was| discussed in a loud bar

12:46 clojurebot: In Ordnung

12:53 dnolen: wow the ability to break on uncaught exceptions in CursiveClojure is going to change my life

12:57 bbloom: dnolen: one of these days yet we'll have every obviously good tool in one damn language :-P

12:57 dnolen: bbloom: eh between real static analysis, real debugging support, real refactoring support I'm not going to dumb text editors for Clojure programming.

12:58 going back

12:59 bbloom: dnolen: understood. we've discussed this, but for onlookers: i use intellj for java most of the time and the rest of the time i do major text editing via vim, switching back and forth --- may consider doing similar for clojure soon

13:00 dnolen: bbloom: the Emacs simluation in IntelliJ is amazingly good, otherwise I would feel the pain more. I imagine getting the real VIM experience is a different matter.

13:00 bbloom: dnolen: yeah, evil is the only vim emulator that even comes close, but it just breaks muscle memory so badly

13:00 uncanny valley thing going on. i'd almost rather a significantly worse emulation

13:01 bigger problem is that there's never a good time to switch

13:01 ~2 weeks lost productivity is a hard fixed cost to pay

13:01 clojurebot: Alles klar

13:03 bbloom: dnolen: the ktc crew going to come out for some composable macros at PWL tonight?

13:03 TimMc: clojurebot: 2 weeks lost productivity?

13:03 clojurebot: 2 weeks lost productivity is a hard fixed cost to pay

13:03 bbloom: TimMc: nice.

13:03 dnolen: bbloom: I'm coming for sure

13:03 bbloom: cool

13:03 dnolen: bbloom: not sure about Kovas

13:04 bbloom: looking forward to meeting Sam, as we've had some fun twitter interactions in the past

13:05 gfredericks: the threadBound field on the Var class is interesting

13:06 I have to assume it's just a perf thing

13:06 justin_smith: gfredericks: isn't that about dynamic vars?

13:06 gfredericks: yeah

13:06 it starts out false

13:07 and the first time you use binding on a var it (for that var) gets set to true, and then it just stays true forever

13:07 afaict

13:07 bbloom: i wondered about that as well

13:07 it seems like you could check instanceof Unbound

13:07 saving a pointer & an atomic deref

13:07 gfredericks: check that on what?

13:08 the root being unbound doesn't say anything about whether the var has a thread-local binding

13:08 TMA: VIM emulation in IntelliJ is quite good -- at least compared to eclipse or netbeans counterparts; alas I have never got around to acquire more than basic knowledge of emacs

13:08 bbloom: gfredericks: er, yeah, you're right

13:08 gfredericks: sorry, was speaking from memory (poorly)

13:09 gfredericks: so presumably it only helps for dynamic vars that don't ever get bound

13:09 which I guess could happen enough in practice?

13:09 tcrayford____: gfredericks: sounds like a thing one could measure haha

13:10 gfredericks: tcrayford____: well it's more about how dynamic vars get used in different codebases

13:10 Bronsa: gfredericks: Var.java is kinda confusing. there's dead and duplicated code

13:10 gfredericks: e.g., libraries that have them for some kind of config that's rarely used

13:10 tcrayford____: so measure some open source ones haha

13:10 gfredericks: tcrayford____: well it's not just about the library itself but how people use them

13:11 tcrayford____: gfredericks: guess there's not really enough open source *apps* to measure that haha

13:12 gfredericks: tcrayford____: appending "haha" is your new verbal tick?

13:14 tcrayford____: haha

13:21 gfredericks: ,(keys (get-thread-bindings))

13:21 clojurebot: (#<Var: --unnamed--> #'clojure.core/*ns* #'clojure.core/*read-eval* #'clojure.core/*err* #<Var: --unnamed--> ...)

13:22 gfredericks: ^ surprised at how many unnameds there are

13:23 I just deref'd all the unnamed vars in my repl and got (nil 72 0 true nil nil 1 1 1 21982 19308 #<clojure.lang.DynamicClassLoader@f774f clojure.lang.DynamicClassLoader@f774f>)

13:23 tcrayford____: gfredericks: in a fresh reepl?

13:23 gfredericks: not too fresh

13:24 haha

13:24 tcrayford____: freshen up

13:25 sentient22: Can I ask a really noob question?

13:25 tcrayford____: sentient22: welcome. Yes!

13:25 sentient22: Okay so, new to clojure, been reading the documentation

13:25 gfredericks: lol a fresh repl stackoverflows for (get-thread-bindings) at java.util.Currency.getInstance

13:25 tcrayford____: (typically in irc: don't ask if you can ask a question, just ask it)

13:25 sentient22: Lists can't be indexed, according to the docs

13:25 gfredericks: tcrayford____: well you might at least have to establish the purpose of the channel

13:26 justin_smith: sentient22: you can use nth, but they are not associative

13:27 sentient22: Okay, so my question is then why does (assuming my list is '(1 2 3)) (.indexOf my-list 1) return 0?

13:27 justin_smith: sentient22: that's not the same sense of "indexing" that we mean regarding associative data structures

13:27 gfredericks: what docs say "can't be indexed"?

13:28 sentient22: http://clojure-doc.org/articles/tutorials/introduction.html

13:28 and justin_smith okay that makes a little more sense

13:28 Bronsa: ,(nth '(1 2 3) 0)

13:28 clojurebot: 1

13:28 justin_smith: sentient22: "access by index" is not the same as getting the item from an index

13:28 sentient22: nth walks a list until it gets to n

13:29 sentient22: while with a vector you can directly access item n

13:29 sentient22: Yeah okay I see what you're saying. Cool. Thanks!

13:29 Just got confused for a second because for some reason I thought .indexOf would fail

13:29 But it was just my own mind playing tricks on me lol

13:29 justin_smith: sentient22: yeah, it's a different usage of the word index

13:30 sentient22: yeah. Thanks all!

13:30 justin_smith: sentient22: clojure tries to avoid abstracting over things that lead to big inefficiencies, treating lists as lookup arrays is one example of that

13:31 (of a thing that is made less convenient because it's inefficient)

13:31 sentient22: Ahh yeah okay

13:34 gfredericks: ,clojure.lang.Var/rev

13:34 clojurebot: 989

14:29 mgaare: having a strange issue with tools.namespace. I do (refresh) on a fresh repl, it says it's reloading all the ns's, throws an exception loading a later ns that an earlier loaded ns was not found. If I go through and manually compile all the ns's, it eventually works fine

14:32 stuartsierra: mgaare: AOT

14:32 tbaldridge: ~aot

14:33 clojurebot: aot was so ahead of its time

14:33 tbaldridge: ~aot

14:33 clojurebot: aot was so ahead of its time

14:35 gfredericks: tbaldridge: sorry did I pollute actual useful things that the bot says?

14:35 tbaldridge: gfredericks: nah, I forget what the right incantation is to get the "AOT" image

14:35 ~AOT

14:35 clojurebot: AOT is kinda broken already

14:35 tbaldridge: ~AOT

14:35 clojurebot: AOT is kinda broken already

14:36 tbaldridge: it was the aliens guy

14:36 oh well

14:37 stuartsierra: How about this http://imgur.com/ojVQfVv

14:39 tbaldridge: I was thinking of this one: https://i.imgflip.com/h9gtq.jpg

14:39 but yeah, that works too

14:43 stuartsierra: I think we scared off mgaare.

14:43 TimMc: ~aot

14:43 clojurebot: http://i.qkme.me/3vb225.jpg

14:44 TimMc: It's case-sensitive, I guess.

14:48 hyPiRion: hrm

14:49 mgaare: stuartsierra: sorry, someone grabbed me to look at an issue where cljsbuild was working under bash and failing under zsh..... no idea. anyway, thanks, after a lein clean things are reloading again

14:49 hyPiRion: ,(map (comp first second) ['#(+ %) `#(+ %)])

14:49 clojurebot: (p1__25# p1__26__27__auto__)

14:50 TimMc: yup

14:51 I've occasionally wondered about that.

14:51 llasram: auto-gensymed gensyms?

14:52 hyPiRion: I wonder if it matters.

14:54 stuartsierra: clojurebot: tools.namespace

14:54 clojurebot: I don't understand.

14:55 TimMc: ~you

14:55 * TimMc squints

14:55 clojurebot: you have to double-pinky-swear before you :refer :all

14:55 stuartsierra: haha

14:57 gfredericks: ~you

14:58 clojurebot: you are a weirdo

14:58 bbloom: awesome.

14:59 llasram: ~you

14:59 clojurebot: you are the cloud

14:59 llasram: YES

14:59 gfredericks: ~it

14:59 clojurebot: it is time for clojure history anecdotes with technomancy

15:00 llasram: Awww

15:00 gfredericks: ~it

15:00 clojurebot: it is for clojure.pprint/cl-format :)

15:01 bbloom: ~why

15:01 clojurebot: bbloom: because you can't handle the truth!

15:01 bbloom: :-)

15:01 ~what

15:01 clojurebot: what is cells

15:01 * llasram just realized that clojurebot probably takes so long to respond to ~you because is doing some O(n) random selection over the facts

15:01 bbloom: ~what?

15:01 clojurebot: what is not a bug

15:01 gfredericks: llasram: I was thinking that

15:01 ~I

15:01 clojurebot: I don't have any opinions of my own

15:01 llasram: ~clojurebot

15:01 clojurebot: clojurebot is perhaps the definition of a legacy software system

15:01 bbloom: ~i

15:01 clojurebot: i is disapoint

15:01 bbloom: ~i

15:01 clojurebot: i is disapoint

15:01 bbloom: ~i

15:02 llasram: Now *that* is disapoint

15:03 hyPiRion: ~gfredericks

15:03 clojurebot: gfredericks is gfredricks

15:03 llasram: ha

15:04 hyPiRion: clojurebot, tautologist

15:04 TimMc: Is it possibly getting factoids over a network connection like it does with eval?

15:04 clojurebot: excusez-moi

15:04 gfredericks: actually it's a misspelling

15:05 I guess to make the factoids less spelling sensitive

15:05 ~gfredricks

15:05 clojurebot: gfredricks is a menace to bots everywhere

15:05 gfredericks: ~gfredericks

15:05 clojurebot: gfredericks is a DSL for seeding clojurebot with high-concept talk ideas

15:06 gfredericks: ~bbloom is an ornithologist

15:06 clojurebot: A nod, you know, is as good as a wink to a blind horse.

15:06 bbloom: gfredericks: fishing for a bird talk?

15:06 gfredericks: yep

15:06 I assume some sort of metaphor about birds living in trees

15:06 llasram: as long as he doesn't start birding for a fish talk

15:06 bbloom: gfredericks: you figure out how to get me to rant about birds and maybe i can do that for you

15:06 gfredericks: I'm sure you'll work it out so it makes sense

15:07 TimMc: mockingbirds

15:07 llasram: Because I don't know what that would mean

15:07 TimMc: I'll tell you when you're older?

15:08 llasram: heh

15:09 hiredman_: llasram: it is doing terrible core.logic things to infer new facts

15:09 TimMc: So with the right set of facts we could make it hang for absurdly long?

15:09 hiredman_: any set?

15:10 TimMc: You're suggesting that it already hangs for absurdly long?

15:11 hiredman_: I dunno

15:12 llasram: hiredman_: ah, interesting

15:12 hiredman_: a never used feature is clojurebot keeps a list of infered facts for some amount of time after being asked something, and if it is given a botsnack before a timeout it stores those facts in the db so they don't need inference again

15:13 llasram: oh!

15:13 That's cool

15:14 gfredericks: hiredman and his intimate secrets about clojurebot

15:14 llasram: clojurebot: ~it is time for clojure history anecdotes with hiredman

15:14 clojurebot: In Ordnung

15:14 llasram: Damn it

15:15 meant that to be clojurebot, but I am bad at editing text

15:15 hiredman_: clojurebot: origin story?

15:15 clojurebot: http://clojure-log.n01se.net/date/2008-11-21.html#13:04

15:15 llasram: Oh my

15:16 Way back from in the rhickey-on-IRC era

15:17 Pretty amusing that rhickey's handle gets highlighted in red there

15:23 tbaldridge: llasram: kind of like a red-letter Bible

15:23 TimMc: hiredman_: I've done ~botsmack after an inference but maybe not a ~botsnack.

15:24 rhickey: Thou shalt not mutate within my sight.

15:24 tbaldridge: rofl

15:25 TimMc: (let's see if that highlighting is still in effect)

15:28 moquist: I've read this line about 20 times and I still only understand it if the word order is wrong: "If a transaction specifies a unique identity for a temporary id, and that unique identity already exists in the database, then that temporary id will resolve to the existing entity in the system." (from http://docs.datomic.com/identity.html )

15:29 It seems to me that it wants to say: "If a transaction specifies a temporary id for a unique identity attribute, and that unique identity already exists..."

15:29 kirill: hi all, is there some kind of generic way to turn off various annoying logs from java libraries? I'm using a clojure library that uses netty, and I keep getting messages like "[main] DEBUG i.n.util.internal.PlatformDependent0"... which I'm not interested in

15:29 moquist: Am I misunderstanding, or on the right track?

15:31 llasram: kirill: Depends on the logging libraries in play. Usually you can tweak which classes log at what level with a small Java property file

15:31 amalloy: kirill: you basically have to figure out how java's logging works, and create an appropriate log4j.properties file (or whatever library is being used)

15:32 stuartsierra: moquist: "identity" in this case refers to the *value* of an attribute with db.unique/identity.

15:32 As in, your account number is an "identity" for you at the bank.

15:33 At least I think that's what it means. :)

15:48 TimMc: llasram: Check out the source for the IRC logs. For rhickey lines it has class="bdfl" :-P

15:51 gfredericks: ~bdfl

15:51 clojurebot: Excuse me?

15:57 seangrove: I don't suppose there's anything like om/shared in reagent?

16:01 bbloom: gfredericks: i could however probably give a whole talk about record players

16:01 gfredericks: bbloom: I don't think there's any good reason not to

16:01 bbloom: i don't know anything about records / record-players, other than that i'm sick of picking up a record and having a record player attached to it ;-)

16:02 (this is me bitching about OOP, if you can't tell)

16:02 gfredericks: ~this is bbloom bitching about OOP

16:02 clojurebot: You don't have to tell me twice.

16:02 gfredericks: ~this

16:02 * bbloom groans

16:02 clojurebot: this was discussed in a loud bar

16:04 gfredericks: bbloom: not a bad metaphor

16:04 bbloom: not strictly mine: it's from GEB

16:04 but it has stuck with me

16:05 gfredericks: oh man he couldn't'vebeentalkingabout OOP in context though

16:05 sobel: (inc GEB)

16:05 lazybot: ⇒ 1

16:05 bbloom: i particularly enjoyed the bit about whether or not aliens could interpret a record "correctly".... even if they got it to produce sounds, would it elicit the emotion that the composer was intending? who knows.

16:13 nicferrier: has anyone done any static analysis on clojure? for example security analysis?

16:16 dagda1: I'm trying to solve the project euler problem for selecting the nth prime number, my code works but it is not quick enough https://gist.github.com/dagda1/1f765e0fcade3193f1e0 can anyone suggest what is the bottle neck

16:17 by not quick enought, I mean it times out for the bigger numbers thrown at it on the test hacker site

16:17 I was thinking if I could ignore even numbers apart from 2 in the (iterate inc 2) bit

16:18 I'm surprised it times out TBH, I'm not really using loop/recur

16:20 jinagarano: noir.validation/rule doesn't set any errors for me. syntax is correct, arguments are passed properly, and if i evaluate them in the repl, the checks give proper return values. does anyone have an idea what the problem could be?

16:24 gfredericks: dagda1: you're filtering on (range 2 n) which takes a while for large n

16:25 dagda1: gfredericks is there an alternative that you know?

16:26 gfredericks: going up to (inc (Math/sqrt n)) is sufficient

16:27 dagda1: gfredericks are lazy sequences slow?

16:28 hyPiRion: I'd say the algorithm is more important than the underlying data structures here.

16:28 gfredericks: yep

16:29 dagda1: gfredericks: indeed

16:29 hyPiRion: But if you need low constant factors and don't want to find a clever algorithm to make primes, you could always use https://github.com/hyPiRion/primes

16:29 dagda1: hyPiRion: I know but it is all about learning clojure

16:29 gfredericks: and https://github.com/gfredericks/composites

16:30 hyPiRion: dagda1: ah. Well, then I'd focus on the algorithms :) I've done some project euler problems in Clojure, and the data structures doesn't really matter if you're doing them "the right way"

16:31 gfredericks: well you don't want to misuse the data structures at least

16:31 hyPiRion: Oh, yeah.

16:32 gfredericks: good ole (vec (concat (subvec v 0 i) [x] (subvec v i (count v)))) ;; lifehack

16:33 hyPiRion: gfredericks: psh, (-> (subvec v 0 i) (conj x) (into (subvec v i (count v))))

16:33 TimMc: Good thing we're using performant datastructures, amirite?

16:34 gfredericks: huh; does that work?

16:35 ,(def v (vec (range 10)))

16:35 ,(def i 3)

16:35 clojurebot: #'sandbox/v

16:35 #'sandbox/i

16:35 gfredericks: ,(def x "fort-ytwo")

16:35 clojurebot: #'sandbox/x

16:35 gfredericks: ,(-> (subvec v 0 i) (conj x) (into (subvec v i (count v))))

16:35 clojurebot: [0 1 2 "fort-ytwo" 3 ...]

16:35 gfredericks: hrm

16:35 I remember some difficulties with subvectors and transients, I guess it just means that into doesn't use them

16:36 hyPiRion: gfredericks: should be fine if they're implemented correctly

16:36 but yeah, when you speak about it, I remember something about that as well

16:36 raspasov: does anyone know what's the memory cost of (go (loop [] (do "something") (recur)))

16:37 justin_smith: raspasov: nearly nothing, it compiles to about what a while true loop would

16:37 dagda1: gfredericks: could you explain.... going up to (inc (Math/sqrt n)) is sufficient

16:38 gfredericks: dagda1: any divisor above sqrt(n) has a corresponding divisor below sqrt(n)

16:38 e.g., 100 is divisible by 20, but it's also divisible by (/ 100 20) == 5

16:39 justin_smith: another way to put it: it will have no pair of factors where both are greater than its square root

16:39 _alejandro: gfredericks: dagda1 because for any x,y > sqrt(n), x * y > n^2

16:39 doh x * y > n

16:40 raspasov: justin_smith: thanks, I have a use case where I'd have potentially a lot of those to ensure sequential operations to many locations, wondering if I should worry about GC-ing those loops when they are not in use

16:40 justin_smith: raspasov: I would be much more concerned about the CPU cost

16:41 raspasov: GC-ing the loop while ensuring that re-establishing the loop doesn't violate the sequential semantics seems tricky without going into lock land

16:42 tcrayford____: You care about GCing the loop - if you don't, you can cause unbounded thread growth on the JVM (iirc)

16:42 raspasov: justin_smith: well I assume that having a bunch of loops parked doesn't incur any cost? most of the loops will be parked most of time

16:42 justin_smith: raspasov: also, gc automatically reclaims resources, but you can't actually "gc" anything. You can make a loop stop (easiest from inside the loop) but the vm decides when to reuse the memory

16:42 raspasov: parked core.async loops?

16:43 moquist: Hm. stuartsierra seems to be gone now, but here's code I wrote to test my suggested change to the Datomic docs: https://github.com/moquist/datomic-uniqueness-ftw

16:43 justin_smith: raspasov: core.async makes a big difference here, because they won't actually hog a thread if parked

16:43 raspasov: justin_smith: by GC-in the loop I mean "ending" the loop by having it not (recur) or be parked any more

16:43 justin_smith: yes I'm aware of that

16:43 justin_smith: raspasov: OK, I think "halt" is more clear here

16:43 raspasov: that's why I'm using them :)

16:43 justin_smith: raspasov: OK, but you didn't mention core.async, that is like - the most important detail here

16:44 a parked go block isn't going to use many resources at all, no

16:44 raspasov: justin_smith: well (go) assumes the non-thread version

16:44 justin_smith: raspasov: which is why I asked if it was parking (you can't park (thread))

16:44 raspasov: there's the (thread (loop [])) version that actually blocks a real thread I think

16:44 justin_smith: right

16:45 that can only block, it doesn't really park

16:45 raspasov: yea but this is a potentially very long lived process, and over time there could be 100s of thousands of parked loops

16:45 I believe the documentation uses "park" for the "fake" threads and "block" for the real threads

16:46 justin_smith: frankly I'm not sure how that would scale, but I bet some profiling would help you predict

16:46 raspasov: but anyway I think we understand each other :)

16:46 tcrayford____: raspasov: depends on your machine too. I've seen modern machines do that many native threads ;)

16:46 tbaldridge: gos are attached to channels when parked, if the channel is GC'd the gos will be as well.

16:46 justin_smith: raspasov: yes, go glocks can park or block, threads can only block

16:46 raspasov: tbaldridge: oh that's good to know, thanks!

16:47 tbaldridge: raspasov: go blocks are really just fancy callbacks, so they behave the same way that (take! c (fn [v] ...)) would

16:47 amalloy: go blocks can block?

16:47 tbaldridge: sure, if you do something blocking in them ;-)

16:47 justin_smith: amalloy: if you fuck up you can do something blocking in a go block

16:47 amalloy: well, i guess that's fair

16:47 justin_smith: it's a bad idea though

16:47 tbaldridge: or if you do something stupid like, (chan 10 (map (fn [x] (Thread/sleep 10000) x)))

16:47 sobel: is that why <! is distinct from <!! ?

16:47 (parking)

16:47 tbaldridge: exactly

16:48 raspasov: yea I always send to an agent or future or something else non-blocking if I have some IO to do, et

16:48 sobel: hey, i'm learning

16:48 raspasov: etc

16:48 sobel: reasoning even

16:48 tbaldridge: raspasov: or instead of a future, just use (thread ...) that way you get backpressure

16:48 *instead of a agent

16:48 _alejandro: raspasov: https://tbaldridge.pivotshare.com/media/core.async-episode-7-gc'd-go-blocks/9394/feature was useful for me to understand how core.async and gc interact

16:48 sobel: small victories. hoping to deploy the first clojure in a client env. for my company next week, too. :)

16:48 raspasov: tbaldrige: yes, I do use that as well, thanks!

16:49 tbaldridge*

16:52 _alejandro: thanks I'll check that out!

16:54 cfleming: dnolen: pong

16:55 dnolen: cfleming: figured out, being able to drop into the debugger on any exception in IntelliJ is sick

16:55 cfleming: gonna save me hours

16:55 cfleming: dnolen: Yeah, that's a life-saver. I need to document the debugger now that it works properly.

16:56 dnolen: cfleming: it's seriously amazing

16:56 cfleming: dnolen: Expression evaluation now works too.

16:56 raspasov: dnolen: do you run your project directly from IntelliJ or connect remotely to a REPL in a terminal?

16:56 dnolen: raspasov: locally

16:56 cfleming: dnolen: I'm going to propose a talk for Clojure/West on the debugger I think.

16:56 dnolen: cfleming: my Clojure debugging workflow is finally almost as good as ClojureScript, lol

16:56 raspasov: dnolen: yea I was trying to make that work the other day but some leiningen plugin was causing me trouble

16:57 cfleming: dnolen: Haha

16:57 raspasov: otherwise can't wait to get all the IntelliJ/YourKit local goodness :)

16:57 amalloy: cfleming: i would install intellij just for a debugger

16:57 cfleming: dnolen: Since eval now works, you can now also put conditions on breakpoints too

16:58 amalloy: Now's your chance! Some bugfixes in the next drop too.

16:58 raspasov: cfleming: yes do that, I've been using Cursive for months and I think I only managed to start it once by accident :)

16:58 cfleming: Some Java-specific (but mostly relevant) info here: https://confluence.jetbrains.com/display/IntelliJIDEA/Debugger

16:59 sobel: what's the status of Cursive? do you have to own IntelliJ to use Cursive or what?

16:59 cfleming: sobel: No, it works with the free community edition.

16:59 raspasov: IntelliJ community edition is great & free

16:59 sobel: cool

17:00 amalloy: my main objection to intellij is that it doesn't start with an E like every other great editor/ide

17:00 dnolen: sobel: the intention however is the Cursive will cost money in the future, but at this point I'm all "take my money" already :)

17:00 raspasov: amalloy: that's a pretty big price to pay :)

17:00 amalloy: emacs, eclipse, and of course ed

17:01 cfleming: Yeah, since evim changed its name, I'm bugging JetBrains to do the same.

17:01 raspasov: what about Notepad, I heard all the legit hackers only use Notepad

17:02 cfleming: sobel: The idea is that there'll be a standalone version of Cursive, and a plugin to IntelliJ for those using Ultimate Edition. The same licence will work for both, so you'll be able to switch.

17:02 justin_smith: cfleming: ex ;)

17:02 hiredman_: back when I was doing euler problems in clojure I did them mostly in notepad++ with a clojure repl running in a cmd.exe window

17:02 worked great

17:02 raspasov: for clarification I'm talking about the most basic Notepad that comes with Windows since prob 95 lol

17:02 sobel: dnolen: that was my exp. with IntelliJ: take my money!

17:03 dnolen: sobel: well cfleming is continuing in that great tradition then

17:03 sobel: having LT and SublimeText both with working REPLs really cuts my urgency, though.

17:03 hiredman_: raspasov: sure, the biggest improvement of notepad++ over notepad in this case is notepad++ will hilight matching parans

17:04 sobel: but i have to think about more than myself, i'm hoping to start a whisper campaign for clojure to replace all our stupid groovy code here

17:04 and maybe some of the core java

17:04 raspasov: hiredman_: haha yea, I can't imagine not having color coding lol

17:04 amalloy: hiredman_: i'd have guessed the biggest improvement is it doesn't completely fail at handling unix line endings

17:04 hiredman_: the great thing about having a lot of practice copying and pasting code between an editor and a repl is it is a workflow that works *everywhere*

17:05 I can do things the same if the repl is in an ssh session in to dev or qa servers vs locally

17:05 expez: :db/id #db/id[:db.part/db] <- what does this literal notation mean in datomic schemas? Is this simply how you tell datomic to fabricate an id for you?

17:05 sobel: hiredman_: that's where i'm coming from, and it's a great advantage until i don't need it and then it becomes a costly capability to maintain

17:05 amalloy: i've tried turning on paren-highlighting in emacs, and couldn't really get the hang of it. it feels like a distraction, and not really needed when you have paredit commands like paredit-backward-up or whatever

17:08 sobel: indenting/coloring in ST3 seem to be ok

17:09 moquist: expez: Yes. See the docs for d/tempid, also.

17:16 justin_smith: tbaldridge: above, when you recommended using (thread) for things that might block, do you mean putting the whole loop in (thread) or just the blocking action?

17:16 tbaldridge: the whole loop

17:16 justin_smith: ahh, OK

17:17 tbaldridge: or at least move the the blocking bits to a different thread via a channel

17:17 justin_smith: tbaldridge: right, and they would be in their own loop in a (thread) block

17:24 sobel: has anyone (present) deployed with nginx-clojure? the nginx's cosocket support seems like it would be a pretty good boost.

17:27 justin_smith: sobel: my impression was that the boost nginx-clojure offers doesn't apply to the main bottlenecks you'd actually see in a clojure app. That said I haven't tested it to confirm.

17:31 sobel: justin_smith: i try to plan ahead to take advantage of the deployment environment for flexibility and performance, so i am looking to nginx for simple vertical scaling

17:32 need to borrow a prod environment to beat it up sometime

17:32 justin_smith: sobel: how would the nginx plugin make deployment / scaling easier?

17:32 sobel: you can get a digitalocean server for like $10 a month

17:34 dagda1: gfredericks: thanks

17:34 mgaare: sobel: have you seen this? https://github.com/ptaoussanis/clojure-web-server-benchmarks

17:34 sobel: justin_smith: the obvious/minimum needs are serving static content and proxying dynamic content reqs to your app. my experience is apache2 (to say nothing of nginx) beats java for that kind of service

17:35 justin_smith: sobel: sure, for security if nothing else I put nginx in front of my clojure app

17:35 mgaare: sobel: probably the most common way to do clojure web deployment is to have nginx as a reverse proxy in front of a clojure app

17:35 justin_smith: sobel: what I don't get is the rationale for putting the jvm inside the nginx process

17:35 mgaare: and the clojure web app runs using an embedded web server

17:35 justin_smith: exactly

17:36 sobel: interesting. i had not seen that graph since the may 2014 data.

17:38 i have been pretty used to deploying tomcat with mod_jk or just http proxying, but i was looking at OpenRESTy as an app platform when i saw nginx-clojure and started thinking clojure would be a brilliant member of that platform

17:39 so the interest is at least partly experimental. glad to see other servers reaching parity (and then some) with nginx-clojure, rather than leaving it in the dust :)

17:39 dah: yeah, http reverse proxy has to be the most simple to configure and operate

17:40 it's handy to be able to hit the application server directly locally, too

17:40 mgaare: sobel: also, have you seen immutant?

17:40 dah: instead of it being embedded or speaking some binary protocol

17:40 mgaare: (gotta give the shout-out there, those guys are great)

17:40 sobel: mgaare: no, but it's on my radar now

17:41 mgaare: sobel: what's particularly nice about the new version of immutant is that you can deploy an app that uses the immutant libraries either standalone or inside a wildfly (nee jboss) container

17:42 sobel: haven't heard that name (jboss) in a while

17:42 justin_smith: sobel: it's the container for the top performer on that benchmark :)

17:43 sobel: justin_smith: good enough for me!

17:47 jcrossley3: mgaare: thanks :)

17:48 sobel: find us in #immutant if you get stuck

17:48 sobel: thanks!

17:49 jcrossley3: sobel: justin_smith: technically, that benchmark was run with immutant *out* of container, no wildfly involved.

17:49 justin_smith: jcrossley3: oh, OK

17:50 jcrossley3: shows how much I know :)

17:50 sobel: is it faster with wildfly?

17:50 jcrossley3: sobel: i wouldn't expect much difference at all, tbh. undertow is doing all the work either in-or-out of wildfly

17:50 sobel: k

17:51 i really thought SQL would be the last data-drive language i'd ever need

17:52 tehgeekmeister: how do i coerce a url to a string representing just the contents of the url?

17:52 tcrayford____: tehgeekmeister: what url type do you have, and what do you mean by "contents"

17:52 tehgeekmeister: have a file url

17:52 amalloy: also by "coerce"

17:52 sobel: .toString?

17:53 tcrayford____: the path, the protocol? the host?

17:53 tehgeekmeister: want just the portion after the file: bit

17:53 tcrayford____: tehgeekmeister: what url class is it

17:53 (class url)

17:53 tehgeekmeister: on it

17:53 tcrayford____: (probably .getPath for a java.net.URL)

17:53 tehgeekmeister: yep, that's the kind it is

17:54 will try now

17:54 tcrayford____: (no idea if that actually works though, just scanned through the javadoc)

17:54 amalloy: ,(let [s "file:///home/akm/whatever.txt", u (java.net.URI. s)] (.getSchemeSpecificPart u))

17:54 clojurebot: "///home/akm/whatever.txt"

17:54 tehgeekmeister: it seems to have worked

17:56 amalloy: tehgeekmeister: just about anything will work fine for a file: url; the question is what you want it to do on other sorts of uris

17:56 eg, for http://google.com?q=wikipedia

17:56 tehgeekmeister: this is always going to be a file url in this case

17:56 i'm really just trying to get the path to a resource in my leiningen project

17:56 a shell script i want to bundle and execute

17:57 (by bundle i mean bundle with the app)

17:57 amalloy: why do you need its path?

17:57 tehgeekmeister: for shelling out to it

17:57 conch takes paths,

17:57 not files

17:57 amalloy: if you bundle it with the app, it won't be in a file at all, but in your jar

17:58 tehgeekmeister: crap

17:58 i seriously misunderstood something, then

17:58 i found this code on the net, and have been building off of it

17:58 tcrayford____: you could always copy it out of the jar and throw it in /tmp

17:58 #notagoodideathough

17:58 justin_smith: tehgeekmeister: you can slurp the file and provide that to /bin/sh via conch maybe?

17:58 tehgeekmeister: (-> (Thread/currentThread) .getContextClassLoader (.getResource path))

17:59 and using that to get files of things in the resource directory

17:59 justin_smith: tehgeekmeister: how did the files get out of the jar?

17:59 amalloy: tehgeekmeister: that's fine if you actually have files. but if you're distributing this program as a runnable jar

17:59 instead of as like a "please clone the git repo and run from that"

17:59 tehgeekmeister: i can distribute it however i want

18:00 could be made jar-friendly later, if need be

18:00 for now, i can just use it as a repo

18:00 good to know it is not yet jar friendly, though

18:03 bashed: Can anyone point me to a good intro on how clojure or any other immutability-centric language handles performance issues? Intuitively, it would seem that in-place transformation of a data structure would be more performant than making a copy of the data structure for each action.

18:04 justin_smith: bashed: full copies are not needed if you can't mutate :)

18:04 amalloy: bashed: it is, but we don't actually copy the whole data structure

18:04 justin_smith: bashed: basic idea, you have a tree which shares most of its structure

18:05 sobel: bashed: the nutshell explanation for me is that immutability takes a lot of complexity out of concurrency, which helps performance. also, as mentioned, the data structures support cheating our way around full copies

18:05 bashed: Oh, so is there a case when the immutability really affects perforamnce?

18:06 amalloy: bashed: i mean, every operation is slightly slower than the equivalent mutate-in-place operation

18:06 justin_smith: bashed: sure, it affects cache behavior because we have more heap fragmentation

18:06 sobel: sure. you won't have to lock a clojure data structure yourself.

18:06 amalloy: but it's not a lot slower, and you get a lot of benefits out of it, like keeping old versions, not needing to lock...

18:06 justin_smith: bashed: but most apps don't need to optimize to that level (and we have java arrays if you hit that point)

18:08 turbofail: oh boy. a badly formatted sha1sum file for a maven artifact

18:08 * turbofail shakes fist

18:09 hyPiRion: turbofail: like https://repo1.maven.org/maven2/org/apache/spark/spark-core_2.10/1.2.0/spark-core_2.10-1.2.0.pom.md5

18:09 (?)

18:10 turbofail: yep, that's the one

18:14 ah, after following the chain of bug reports i arrive at some stuff you're involved in

18:19 justin_smith: turbofail: the hyPiRion is calling from inside the thread

18:19 sobel: haha

18:21 hyPiRion: turbofail: I should've given you the tip about `:checksum :warn` as a temporary fix

18:21 turbofail: then who was lein?!?

18:22 tcrayford____: hyPiRion: any idea if there's a faster way to iterate through PersistentTreeMap than reduce-kv (e.g. without allocating a function)

18:23 loop/recur are (with first/rest calls), surprisingly slower

18:23 wait, not treemap, persistentarraymap

18:24 turbofail: hyPiRion: yeah. unfortunately my stuff is still broken even after succesfully fetching the dependency, but that's an unrelated issue

18:24 amalloy: it's not at all surprising that loop/recur is slower than reduce-kv

18:24 allocating a function to give to reduce-kv is going to be your fastest option

18:24 hyPiRion: turbofail: gurr. At least one step closer to a solution

18:25 turbofail: yeah. it looks like spark changed the signature of some of their constructors

18:49 wei: does there exist an rpc library (similar to shoreleave-remote) that runs asynchronously over sente?

18:56 dweave: I don’t really understand clojure’s (hickey’s) take on FRP. Basically my understanding is that “we don’t need it because clojure has point in time identities (datastructures)”. But isn’t FRP useful for more than just modeling time? isn’t it about composability?

18:57 these seem to be orhthoginal concepts, but the general attitude is that frp solves a problem clojure doesn’t have.. Or am i missing something

18:59 justin_smith: dweave: I think there are a few things in clojure that approach the general territory of FRP. core.async, prismatic/plumbing, ztellman/manifold

18:59 though none of those are exactly FRP of course

19:01 dweave: in fact, now that I think of it, the one thing that I think really could be FRP is the audio / control data flow in kunstmusik/pink which has explicit stepped time (because the audio signal processing algorithms it implements all need to be strict about time)

19:01 dweave: hmm

19:02 justin_smith: but that project is not very functional, as clojure code goes (because it needs low latency)

19:02 maybe I should say "not very pure"

19:02 dweave: I guess why is this not something that’s more widespread in clojure tho.. For instance clojurescript Om has no good corollary. I find it a great paradigm in gui programming

19:03 aperiodic: there's also a more-or-less port of ELM using core.async: https://github.com/jamesmacaulay/zelkova

19:03 justin_smith: dweave: well clearly cljs/om use core.async for the pipelining of events / calculations that frp would have

19:03 dweave: but it doesn't have the strict stepping of time that would make it frp

19:03 dweave: yeh

19:04 i think the difference with om is that ReactJS solves some of that problem

19:05 justin_smith: pink is pull based frp iirc

19:05 dweave: you know longer have to explicitly connect events to UI updates

19:05 justin_smith: (but I would not recommend trying to use pink for web dev at all... it's very specialized for audio synthesis)

19:06 dweave: is the strict time sync actually something you need? because otherwise core.async can surely do the rest

19:07 dweave: i think it is something i need, but let me give u an example and tell me if it qualifies as strict time sync

19:08 well my examples a little complicated. so i’ll simplify. Say I have a button and I only want some action to take place if I click it twice within a set number of seconds.

19:08 that’s a problem FRP handles elegantly

19:08 is that wat u mean by strict time

19:09 justin_smith: dweave: core.async does this nicely if you define debounce (which I swear should totally be built in by now)

19:09 dweave: the problem I’ve found with core.async is it places emphasis on using transducers

19:09 which u have to bake in when u create the channel

19:09 justin_smith: dweave: no, what I meant was that in frp there is a global model of time (often with a sampling rate and strict propagation semantics) and core.async is a bit looser about this stuff

19:09 dweave: that limits composabliity “down stream” no?

19:09 justin_smith: dweave: how would using a transducer limit composability

19:10 dweave: say i have a channel already

19:10 i can’t “add” a transducer to it

19:10 justin_smith: dweave: a transducer is compatible with an frp stream processor

19:10 dweave: what is frp stream processor in this context

19:11 justin_smith: dweave: some element that processes your data between a source and sink

19:11 in the abstract sense, anything with both inputs and outputs

19:11 dweave: i see

19:12 justin_smith: dweave: being able to recompute the graph at runtime can be a limitation in cljs (no eval / no compiler in the runtime) but not a limitation of core.async itself

19:12 but recomputing graphs should be a rare event anyway if you care about perf at all

19:12 dweave: if I have a channel i guess i’m wondering how to apply a map function to it

19:13 justin_smith: and in practice you can make a graph that is flexible enough to represent the various kinds of processing you need

19:13 dweave: say it’s being consumed by another component

19:13 justin_smith: dweave: the map function can be provided as an argument to the channel

19:13 dweave: but map is deprecated

19:13 in favor of transducers

19:13 justin_smith: no, we just use the transducing map now

19:13 it's still map

19:13 dweave: oh

19:13 what’s that look like?

19:14 (map ch fn)

19:14 ?

19:14 justin_smith: (chan buffering (map f))

19:14 dweave: and that produces a new channel?

19:14 justin_smith: right

19:15 you can send things to that channel in order to have them processed

19:15 dweave: but what if I already have a channel is what i’m saying

19:15 justin_smith: dweave: then feed that channel into the mapping one

19:15 dweave: just using pipe?

19:16 (pipe existing-chan (chan buffering (map f)))

19:16 justin_smith: there is also map (as opposed to the depricated map<)

19:16 dweave: and that does something like i just did ^

19:16 ?

19:16 justin_smith: https://clojure.github.io/core.async/#clojure.core.async/map

19:17 dweave: ah yes thank u

19:18 justin_smith: it's too bad core.async isn't as straightforward to demo on this channel as clojure.core is

19:18 it would be cool to have a "show and tell core.async" env for doing demos and establishing what works

19:18 dweave: yeah

19:19 could that be a lazybot plugin

19:19 justin_smith: yeah, the security would be tricky - there's good reason to restrict threaded / async stuff

19:19 but there's probably a way to do it...

19:19 dweave: true

19:25 kiwitobes: Is there any way to use Swing (or any other window library) if I'm connected to a remote REPL?

19:26 Trying to open windows complains that the environment is headless (which makes sense) but I can't tell if there's a way to run this part locally

19:26 justin_smith: kiwitobes: if the remote repl was started with the X server display set, the display is running, and it has permissions to access that display (on *nix)

19:26 kiwitobes: you would need to do X11 forwarding, and have an X server running

19:26 or if you use another windowing system - well good luck!

19:26 kiwitobes: justin_smith: Ah, ok, thanks!

19:27 Yes, I'm using X11

19:27 justin_smith: kiwitobes: you also need a java jre that has all the display stuff (not a headless jre)

19:27 kiwitobes: ssh has an option to do compressed ssh session forwarding

19:27 but there is some config needed, and X over a socket is notoriously hard to use

19:27 as in laggy, it's a fairly noisy protocol

19:28 kiwitobes: Right, I'm thinking I'll have to have a local repl somehow talking to the remote one

19:28 justin_smith: kiwitobes: that would give a much better user experience for sure - you could use some protocol to coordinate between the two processes

19:32 kiwitobes: I looked into using Gorilla REPL, but it doesn't connect to remote REPLs, it has to run its own

19:51 arrdem: what do people like for working with SQL?

19:52 justin_smith: more and more I think sql is the right dsl for doing sql in

19:52 arrdem: so you'd go with yesql

19:52 justin_smith: yeah

19:52 arrdem: hum...

19:52 justin_smith: haven't used it in anger yet though

19:53 just base line frustrations with various attempts to abstract over it

19:53 arrdem: fair. I used ibdknox's simpledb (which is an unbounded in memory map) in Grimoire and it's really just a memory leak that I need to replace with a real datastore.

19:53 so looking to see what my options are.

19:54 justin_smith: arrdem: so by "sql" you mean "persistent data store"

19:54 (though many of the good options are sql of course)

19:54 arrdem: by SQL I mean "SQL is something I need to learn anyway and the only set of datastores I have confidence in finding working drivers for"

19:54 justin_smith: :)

19:54 vas: Hi. I'm trying to use compojure and a simple HTML form to write to a database. any hints on how to make my submit button do an action that is caught by my router clj? (=

19:54 arrdem: with all due respect to cbp for his awesome work on bitemyapp/revise it is out of date.

19:55 otherwise I'd just use rethinkdb again :P

19:55 tbaldridge: for grimoire, I'd be tempted to use some sort of document db

19:55 like couchdb

19:56 justin_smith: vas: create a POST route, and point the form at it, and use wrap-params and friends (ring middleware) to turn the request data into a map of data

19:56 arrdem: yeah... since I'm finally caving to using a "real DB" anyway for analytics I may need to rethink the filesystem "datastore" I'm using for the actual documentation data.

19:56 justin_smith: vas: also, in practice, minimize your points of failure - test the route using CURL, then once you like those results, use the request form on a page etc.

19:57 arrdem: the datastore in question is just for storing analytics (for now..)

19:57 justin_smith: vas: nothing more maddening than "everything is broken and I don't know if I fixed either side yet" when you don't have the form or the backend working yet

19:58 vas: justin_smith: ah, that is a great idea. curl ftw. i just read about cemerick/friends today, checking it out now. also, madness is not always a bad thing *sips tea at tea party* thanks for the data|code.

20:03 arrdem: tbaldridge: have you used clutch or another couchdb driver?

20:03 tbaldridge: I did a long time ago, but the api is so simple, you can almost use slurp + data.json if you had to

20:04 arrdem: gotchga

20:09 cfleming: So my understanding is that destructuring cannot be used in Clojure deftype/defrecord/reify method implementations, but can in ClojureScript - is that right?

20:10 arrdem: yes IIRC

20:10 tbaldridge: really?

20:10 arrdem: tbaldridge: I've never seen it done in CLJ at least

20:10 tbaldridge: ,(reify clojure.lang.IDeref (deref [[x y]]))

20:10 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: sandbox$eval25$reify__27>

20:10 tbaldridge: interesting....

20:11 Bronsa: yeah deftypes & co in cljs expand into extend-type expressions

20:11 cfleming: Makes sense, since in ClojureScript I guess it desugars down into fns set to JS properties in the end

20:11 Bronsa: cfleming: correct

20:11 tbaldridge: someone should patch clojure...

20:12 cfleming: Bronsa: Ok - so extend-type allows destructuring? Is that true in Clojure too?

20:12 amalloy: tbaldridge: you can destructure just fine in deftype and friends

20:12 you just can't use &args

20:12 which people sometimes conflate

20:12 cfleming: amalloy: Are you sure about that?

20:12 Bronsa: amalloy: I don't think you are right

20:13 amalloy: i just did it in a reify

20:13 (defprotocol Foo (f [this x])) (f (reify Foo (f [this [a b]] (+ a b))) [1 2]) ; 3

20:13 Bronsa: oh well, TIL

20:14 amalloy: same in a deftype

20:14 Bronsa: (inc amalloy)

20:14 lazybot: ⇒ 221

20:15 Bronsa: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_deftype.clj#L63-L65 relevant code in core_deftype for those interested

20:17 cfleming: (inc amalloy)

20:17 lazybot: ⇒ 222

20:17 Bronsa: tbaldridge: looks like the exception of your example comes from trying to print the reify

20:17 cfleming: And that's independent of whether it's implementing an interface or a protocol, I guess

20:19 So I guess this also means that extend-type and extend-protocol also allow destructuring.

20:19 Bronsa: no doubt about that

20:20 cfleming: Ok, now I'm confused - the examples for extend-type also show it allowing rest params?

20:21 Actually, of course, since that ends up as an fn too

20:22 Bronsa: cfleming: http://sprunge.us/TcQT

20:22 weird, but valid usage

20:22 vas: in a very simple attempt to get a POST route working in my router clj i have something like ,(POST "/ptest" [val] (str "the val was : " val)) ... but I keep getting a 403 ferrbidden when using curl -X POST

20:23 cfleming: Huh

20:23 Bronsa: Like you say, TIL

20:23 Bronsa: I'm starting to think that the grammars I'm developing for Cursive will be pretty useful, this stuff is hard to figure out from doc + examples

20:25 Bronsa: cfleming: a weird thing about that example is, the accepted arities to f are still determined by the declared arities in the defprotocol, even though there's a variadic impl

20:25 e.g. you cannot invoke (f) or (f 1 2 3)

20:26 but I've never seen varargs used in extend-protocol

20:26 cfleming: I guess that makes sense, since the f you invoke is created by the protocol, which looks the implementing f up, right?

20:26 Bronsa: yeah

20:27 justin_smith: vas: maybe try turning off any auth et. until you have the basic functionality

20:29 vas: it can help to add sn outermodt middleware that dumps info before the rest of the code runs

20:29 *outermost

20:32 vas: justin_smith: it's pretty much as barebones as it can be. that is a good idea... it is bizarre because all the GET routines work fine..

20:32 justin_smith: easy to write your own printing middleware, but eg. ring.middleware.logger is an option as well

20:33 vas: justin_smith: thanks for mentioning curl, that is actually life-saving in this circumstance

20:33 amalloy: vas: what happens if you send a GET request for a route that your app doesn't handle at all, like curl http://localhost/dsaffas

20:33 justin_smith: perhaps something like ring-sntiforgery id on by default?

20:34 *antiforgery

20:34 vas: justin_smith: the GETs have a catchall, but the POST returns <h1>invalid anti forgery token</h1> ...

20:35 amalloy: sounds like justin_smith wins the prize

20:35 vas: :)

20:36 rakkar: excuse guys, but do you know where I can get a good clojure .pdf file tutorial? I can see a lot about it in different sites.

20:36 just free tuto

20:37 amalloy: i don't understand what you want, rakkar. a tutorial on using pdfs in clojure? a tutorial on clojure, delivered as a pdf...?

20:37 rakkar: to read offline

20:37 in my tablet

20:37 if I got in my needs

20:37 will check some good book before

20:37 I have already tried somethings on this language, very impresive.

20:38 vas: justin_smith: so, in short, i need to do sessions in order to be able to POST something? (pardon my nubility)

20:38 arrdem: O'reily will happily sell you a PDF copy of any of the Clojure books...

20:38 rakkar: a lot of books there

20:38 amalloy: *chuckle* nubility is an actual word, vas, which means something different from "newness"

20:39 vas: amalloy: rofl i just looked it up. haha

20:39 rakkar: many books, what could be the best?

20:39 arrdem: ~books

20:39 ,1

20:39 clojurebot: eval service is offline

20:39 * arrdem mutters darkly

20:39 rakkar: like to beginners, or to work with oracle databases

20:40 or concurrency

20:40 cfleming: While I'm at it, is it there any restriction on the placement of :as and rest params in parameter lists and destructuring?

20:40 By convention they're always last, but is that required?

20:41 ,(fn [a & b c] (+ a b c))

20:41 clojurebot: #<CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(NO_SOURCE_PATH:0:0)>

20:41 cfleming: ,(fn [a b & c] (+ a b c))

20:41 clojurebot: #<sandbox$eval49$fn__50 sandbox$eval49$fn__50@32529bfc>

20:41 cfleming: ,(fn [[a b & c]] (+ a b c))

20:41 clojurebot: #<sandbox$eval75$fn__77 sandbox$eval75$fn__77@6f35ec84>

20:41 cfleming: ,(fn [[a & b c]] (+ a b c))

20:41 clojurebot: #<CompilerException java.lang.Exception: Unsupported binding form, only :as can follow & parameter, compiling:(NO_SOURCE_FILE:0:0)>

20:42 cfleming: Wow, that's a helpful error messge

20:42 message

20:42 ,(fn [[a b & c :as d]] (+ a b c))

20:42 clojurebot: #<sandbox$eval129$fn__131 sandbox$eval129$fn__131@65d0c5d2>

20:42 cfleming: ,(fn [[a b :as c & d]] (+ a b c))

20:42 clojurebot: #<sandbox$eval157$fn__159 sandbox$eval157$fn__159@56cbdfca>

20:42 cfleming: ,(fn [[a :as b c & d]] (+ a b c))

20:42 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: c in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:43 cfleming: Interesting

20:44 ,(fn [[:or {b 10} a :as b & c]] (+ a b c))

20:44 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: c in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:44 Bronsa: cfleming: :as and :or go after fixed & varargs

20:45 cfleming: Bronsa: (fn [[a b :as c & d]] (+ a b c)) worked, or at least compiled - whether the fn does the right thing is another question

20:46 Bronsa: cfleming: & d is just ignored there

20:46 ,(fn [[a b :as c & d]] d)

20:46 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: d in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:46 cfleming: ,(fn [[a b :as c & d]] (+ a b c d))

20:46 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: d in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:46 cfleming: I see

20:46 Nice, thanks

20:46 (inc Bronsa)

20:46 lazybot: ⇒ 91

20:47 amalloy: whoa what, it's ignored, not an error?

20:47 cfleming: Looks like it

20:47 This is why we should be using grammars to parse our forms

20:48 Bronsa: cfleming: no why, c.c/destructure, c.c/for and c.c/doseq are so nice to read :P

20:48 cfleming: This, and many other reasons

20:48 amalloy: well. it's a bit tricky, because you either have to do what's currently done, and have the reader just accept lists and vectors and so on

20:48 or else you have to adjust the grammar every time you write a macro

20:48 justin_smith: vas: was walking to the clojerks meetup. it will suffice to provide the token ring generates when serving the page with the form, or turn off the middleware

20:49 cfleming: amalloy: I define grammars for each individual form

20:49 amalloy: cfleming: and user-supplied macros?

20:49 cfleming: amalloy: They'll be provided by an extension api

20:49 justin_smith: vas: actually the session may be used to track token validity...

20:49 cfleming: Words can't express how much better doing that made my life

20:49 amalloy: huh? it sounds like you're saying i have to write an intellij extension to write a clojure macro, but that can't be what you mean

20:50 cfleming: Not quite. You have to write a Cursive extension if you want support in Cursive for your macro.

20:50 amalloy: where support in cursive means...

20:51 cfleming: But "write an extension" makes it sound like more work than it is - it's pretty simple

20:51 Having your symbol resolution work, basically.

20:51 Otherwise there's no way for Cursive to see inside macros to see which symbols they define.

20:51 vas: justin_smith: i've always wanted to visit oregon... thanks for your help. i will investigate how to turn it off for now... although eventually CSRF protection will be +

20:53 cfleming: amalloy: But the extension mechanism is only required in Cursive since I need to support all macros. For a normal lib that needs to parse its own macros, it can be totally self-contained.

20:53 justin_smith: vas: the rradme looks quite straightforward https://github.com/ring-clojure/ring-anti-forgery

20:54 cfleming: amalloy: With macros it's even easier than what I do in Cursive, since you know what the form should look like, and you have &form to parse, so your first step can always be (let [parsed (p/parse &form my-grammar))

20:55 The parser combinators for a PEG parser are about a page of code, and took an afternoon to write.

20:55 amalloy: well, my perspective on this is that it sounds absurdly over-formal but i could believe i might be wrong

20:56 cfleming: Again, it sounds more formal than it feels when you're using it.

21:00 * turbofail is still debating attending clojure/west

21:01 arrdem: I will be.. should be fun =D

21:02 turbofail: yeah. it's just a significant amount of money is all

21:02 ideally i would have gone last year when it was in SF

21:03 then i could have at least avoided the hotel and plane ticket

21:07 cfleming: amalloy_: Here's an example: https://www.refheap.com/96978 is the grammar for deftype. I can then parse it like this: https://www.refheap.com/96980

21:09 turbofail: i still have nightmares about the c.c/for implementation

21:09 cfleming: amalloy_: (slightly edited to remove some Cursive-specific stuff, but that's the idea)

21:10 turbofail: https://www.refheap.com/96981 :-)

21:10 arrdem: (inc cfleming)

21:10 lazybot: ⇒ 10

21:10 turbofail: though i guess the nasty part of `for''s implementation isn't really the parsing of it, just the things it does to handle chunked seqs and things

21:11 cfleming: turbofail: Sure, although the parsing is also pretty hairy. Check out ns too for a bundle of laughs.

21:12 The other nice thing about this method is that with some small extensions you can get really nice error messages like "Expecting symbol but found vector when parsing let binding vector" rather than "Clojure compiler couldn't convert ISeq to char fuckyou"

21:13 arrdem: It's A Feature™

21:14 cfleming: And you don't get weird corners like rest params being ignored if they come after :as and :or clauses just because.

21:14 Anyway, I'll shut up now. tldr - this is fantastic, everyone should do it.

21:16 arrdem: I'll be looking out for CIDER support :P

21:17 * cfleming looks towards bbatsov

21:20 arrdem: one so motivated could probably package this up as polite-core-macros or something and just alter! all the clojure.core/* macros to add nice arg parser wrappers...

21:21 * cfleming searches for one

21:21 * arrdem takes a step back

21:22 cfleming: That's sort of similar to what dynalint does, I guess, although that's more dynamic checks more along the lines of :pre and :post I think

21:26 stevenleeg: quick question

21:26 how can I get access to pow and sqrt?

21:26 arrdem: half considered answer

21:27 stevenleeg: http://clojure.github.io/clojure-contrib/math-api.html is deprecated apparently?

21:27 arrdem: &(Math/sqrt 4)

21:27 lazybot: ⇒ 2.0

21:27 stevenleeg: arrdem: hurrr, got it

21:27 thanks

21:27 haha

21:27 arrdem: stevenleeg: it's interop to java.lang.Math. I don't like it and think we should have real math fns but we don't.

21:28 good numerics are hard.

21:28 bad numerics are easy.

21:28 stevenleeg: arrdem: what is http://clojure.github.io/algo.generic/clojure.algo.generic.math-functions-api.html

21:28 I saw that and it looks like real math fns in clj

21:29 but I couldn't do (use clojure.algo.generic.math-functions)

21:29 arrdem: stevenleeg: algo.generic is a solid math fn suite implimented as multimethods, which are fine for light/medium weight use but are too slow to be called "high performance".

21:29 $google arrdem meajure

21:29 lazybot: [arrdem/meajure · GitHub] https://github.com/arrdem/meajure

21:30 arrdem: ^ project of mine extending algo.generic to do math on numbers with units.

21:34 sdegutis: Has there been any work done to separate the ClojureScript compiler from the JVM?

21:38 gfredericks: sdegutis: I'm not sure what this means: https://twitter.com/swannodette/status/559013608232062977

21:40 cfleming: sdegutis:https://github.com/clojure/clojurescript/wiki/Bootstrapping-the-Compiler

21:40 sdegutis: Is help welcome?

22:33 julianleviston: ,"Just checking quotes - disregard"

22:33 clojurebot: "Just checking quotes - disregard"

22:33 julianleviston: yay

22:44 gfredericks: julianleviston: clojurebot does PMs

22:45 julianleviston: gfredericks: ah ok… I can't even remember how to do PMs… it's been about 15 years since I used one. lol

22:45 gfredericks: /msg ?

22:45 yep. sweet! haha go memory, go!

22:45 gfredericks: I always start with /query to minimize the chance of accidentally saying something publicly

22:46 I don't want anybody to know the things I say to clojurebot in private

22:46 julianleviston: gfredericks: lol… there's some poetry in there somewhere ;-)

Logging service provided by n01se.net