# #clojure log - Feb 03 2015

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

1:11 Mr0rris0: :D

1:17 vas: Hi, i'm using CIDER to play with compojure and enlive. Compojure is in my :dependencies but is not "on the classpath" within cider.. any ideas as to why? (works in external shell)

1:25 tomjack: did you kill and start a new CIDER JVM after adding to :dependencies?

1:25 if so, how are you starting CIDER? cider-jack-in? from a buffer visiting a file? which file?

1:26 (it should be a .clj file inside the project in question)

1:27 vas: tomjack: you are a genius

1:27 clojurebot: Huh?

1:28 vas: tomjack: i was not starting it from a .clj in the project... that was an awesomely simple fix haha. thanks

1:29 tomjack: C-h f cider-jack-in

1:32 (the cryptic doc there means you can do C-u C-c M-j (when it's bound) or C-u M-x cider-jack-in to get it to ask you what project you want)

1:38 vas: tomjack: those are very useful. thank you. how does one "bind" something like C-c M-j to cider-jack-in?

1:48 tomjack: it's bound in cider itself I think

1:48 you just have to be in _some_ .clj file already

1:48 (otherwise cider bindings aren't in effect)

1:49 maybe (global-set-key (kbd "C-c j") 'cider-jack-in)

1:49 (in ~/.emacs.d/init.el in case that is not clear)

1:50 justin_smith: also C-c <char> for any single symbol on the keyboard is reserved by emacs for user specific stuff

1:51 tomjack: ..unofficially :(

1:51 justin_smith: sure, but only shitty elisp modes steal those keys, so if you override their bindings, it's their own fault :)

1:51 tomjack: I thought org-mode did?

1:52 justin_smith: OK, shitty or grandfathered in non-shitty :)

1:53 tomjack: I just checked in an org mode buffer

1:53 tomjack: maybe it only takes minor-mode-reserved bindings, which I just learned about

1:53 justin_smith: looks like they use some C-c char, but not a-zA-Z

1:54 :)

1:55 I think I agree with Bastien, org-mode is not a major mode, it's a monster mode

1:55 justin_smith: haha

1:56 vas: does anybody know how to play with enlive snippets?

1:57 justin_smith: tomjack: "Don't define C-c letter as a key in Lisp programs. Sequences consisting of C-c and a letter (either upper or lower case) are reserved for users; they are the only sequences reserved for users, so do not block them." https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html

1:57 tomjack: so that gives us 52 decent C-c bindings that modes can't steal (major or minor)

1:58 tomjack: yes, I never really realized how valuable that is, until I just had flashbacks of trying to decide on a binding

2:02 ddellacosta: vas: what are you trying to do in particular w/Enlive?

2:08 vas: ddellacosta: so i've got deftemplate down, i'm trying to understand how i can grab a chunk of my html page and, defining it as a snippet, duplicate the chunk

2:09 ddellacosta: vas: I'm not sure about defining a snippet dynamically, assuming I'm understanding you right

2:09 vas: but have you checked out clone-for? https://github.com/cgrand/enlive/wiki/Table-and-Layout-Tutorial,-Part-4:-Duplicating-Elements-and-Nested-Transformations

2:09 vas: sounds like it may do what you need, if you are trying to repeat something

2:09 vas: tell me if I'm way off-base here

2:14 vas: ddellacosta: very helpful actually.

2:14 ddellacosta: vas: great!

2:25 julianleviston: Not to start a war of editors, but am I missing much using SublimeText and not something lovelier?

2:26 I’ve attempted to look at paredit for SublimeText a couple of times, but it just didn’t work out well for me. Am I better off using vim or emacs or something?

2:26 rhg135: Not at all

2:26 julianleviston: It’s often struck me that editing text is stupid.

2:26 And editing forms would be much more sensible… which is what paredit is for, right?

2:26 rhg135: It is for programming

2:27 tomjack: julianleviston: I was going to say "yes, paredit" before you mentioned it.. but I drank the kool-aid

2:29 I think every language I use that is not Clojure is regularly noticeably irksome for lack of good structural editing

2:30 julianleviston: I was watching timothy baldride’s tutorial before… and it looked like he knew what he was doing...

2:30 and he was using paredit.

2:30 tomjack: of course, I still use them..

2:30 julianleviston: tomjack: oh no doubt. I wouldn’t even consider talking about this unless it was a lisp

2:30 tomjack: course.

2:31 tomjack: so I guess my answer is, yes, you are missing something, but no, you are not necessarily better off :)

2:31 julianleviston: tomjack: which editor to use tho?

2:31 a nice one with a buffer and whatnot...

2:32 tomjack: dunno, "not necessarily" here indicates my ignorance with regard to you (which is much greater than my ignorance with regard to myself, which itself is quite large)

2:32 good luck :)

2:33 julianleviston: what do you use? :) vim?

2:36 justin_smith: I use emacs with vi key bindings

2:36 best of both worlds

2:38 julianleviston: ah ok.

2:38 what is tim using here? https://tbaldridge.pivotshare.com/media/core.async-episode-1-pipelines/9025/feature

2:39 justin_smith: no preview :(

2:39 julianleviston: efpm… huh?

2:39 I don’t understand...

2:39 justin_smith: I can't watch it without paying

2:40 julianleviston: yeah you can. the first one.

2:40 justin_smith: and I don't feel like paying money to see what editor he is using :)

2:40 I watched one of his before

2:41 julianleviston: you don’t heav to pay for the first

2:41 justin_smith: it's not my first

2:41 like I said

2:42 it sits there, not paying, with a donate button lit up

2:42 julianleviston: weird. not for me.

2:42 justin_smith: how many of his videos have you watched?

2:42 hellofunk: julianleviston: i think tbaldridge uses Cursive in some of his videos

3:08 julianleviston: justin_smith: just the free one.

3:08 justin_smith: core async pipelines.

3:08 hellofunk: thanks.

3:09 hellofunk: I find editors a necessary pain.

3:09 haha I sound so whiney :)

3:18 hellofunk: julianleviston: the editor situation for Clojure is a bit of an uphill climb, there is a learning curve regardless of the editor you choose. If I had to do it all over again, and had it been available when I started out, I'd have used Cursive, no doubt. But it's hard to break all the habits I've learned using emacs in my workflow.

3:25 julianleviston: hellofunk: I don’t mind learning things. For example, 6 months ago I decided to use Colemac in addition to Qwerty…. and that’s what I’m typing on now.

3:25 I’ll take a look at cursive, thanks.

3:26 Intellij?

3:26 Is it not slow and clunky bloatware?

3:26 I guess not.

3:29 I’m probably just wary because of eclipse.

3:32 ianhedoesit: ,(dotimes [n (count ["a1" "b2" "c3"])] (str "&ids=" (get ["a1" "b2" "c3"] n)))

3:32 clojurebot: nil

3:32 ianhedoesit: I think I know why that doesn't give me what I want, but I don't know how to do it correctly.

3:33 julianleviston: ianhedoesit: I think you just want join, don’t you?

3:34 ianhedoesit: what are you trying to end up with?

3:34 “&ids=[a1]&ids=[b1]&ids=[c1]” ?

3:34 ianhedoesit: yes.

3:34 julianleviston: ok one sec

3:35 hellofunk: julianleviston: definitely don't make the mistake of confusing IntelliJ and Eclipse. they are quite different. I can run Cursive fine on a nearly 4-year Macbook Pro, and I don't generally hear complaints about it being slow.

3:35 julianleviston: worth watching Colin Fleming's Clojure conj presentation about Cursive on ClojureTV youtube channel

3:36 julianleviston: I think this should do it,

3:36 (let [ids ["a1" "b2" "c3"]]

3:36 (join "&" (map #(str "&ids=[" % "]") ids)))

3:36 ianhedoesit: hellofunk: I just watched (most) of that today.

3:36 julianleviston: oops.

3:36 remove the & inside the first quote…

3:37 (let [ids ["a1" "b2" "c3"]] (clojure.string/join "&" (map #(str "ids=[" % "]") ids)))

3:37 ianhedoesit: that should've been more obvious to me. :) I should probably sleep. thanks

3:38 julianleviston: ianhedoesit: no wukkaz.

3:38 hellofunk: I just started watching jonyelipson’s… but ok.

3:38 epsilon

3:39 ianhedoesit: (inc julianleviston)

3:39 lazybot: ⇒ 3

3:53 ianhedoesit: (identity ianhedoesit)

3:53 lazybot: ianhedoesit has karma 1.

3:53 ianhedoesit: (karma ianhedoesit)

4:02 daniel: (identity daniel)

4:02 lazybot: daniel has karma 0.

4:03 ianhedoesit: :(

4:04 daniel: i know

4:05 hyPiRion: (inc daniel) ; fixed?

4:05 lazybot: ⇒ 1

4:07 julianleviston: cfleming: nice talk!

4:08 cfleming: interesting, because I’ve been ranting about structural editing for a long while… and I’ve been applying these same ideas in the project I’ve been devving for the last year or so… which is a structural editor for content… (ie websites).

4:08 daniel: hyPiRion: :D ty

4:09 (inc hyPiRion)

4:09 lazybot: ⇒ 65

4:09 michaelr: hey

4:11 julianleviston: hey

4:25 cfleming: julianleviston: Thanks, glad you liked it!

4:27 julianleviston: cfleming: it’s a really good further step into having languages and projects that are self-describing, learnable, and intelligently structured rather than “dumb text”.

4:28 tomjack: hmm, in gorilla repl, are we actually supposed to type code into the browser? ;[

4:28 julianleviston: cfleming: I really hate how I generally can’t apply the language to the source. “Homoiconicity what?”

4:28 cfleming: julianleviston: Right - I actually think text is a fine serialisation mechanism, having tried it I'm not a fan of graphical editors.

4:28 tomjack: ah

4:28 nevermind. whew.

4:28 cfleming: julianleviston: I think tools should understand it though

4:29 julianleviston: cfleming: yeah, definitely… cf previous work on transite.

4:29 transit*

4:29 tomjack: "Should you prefer more of an antique editing experience"

4:29 cfleming: tomjack: I didn

4:29 oops

4:29 tomjack: I didn't write that, but I did have a little chuckle when I read it

4:32 tomjack: ah, so we are supposed to paste from emacs into gorilla I guess

4:34 cfleming: tomjack: It seems like it would be nice to be able to treat gorilla as a remote REPL and connect to it from some other editor

4:34 tomjack: Although I haven't used it so I'm not sure if that makes sense

4:34 julianleviston: cfleming: what do you use as a REPL?

4:34 cfleming: or don’t you really do REPL dev?

4:35 cfleming: julianleviston: Cursive

4:35 julianleviston: oh it has a REPL in it? Sorry I missed that.

4:35 tomjack: the problem is all the other stuff

4:35 and your interface to a document shouldn't be a cider repl

4:36 cfleming: julianleviston: Yeah, I should have made that clearer in the talk - I'm not anti-REPL, I just don't think it should be used for providing basic editor functionality

4:36 julianleviston: The Cursive REPL is pretty full-featured these days

4:36 julianleviston: cfleming: <3

4:36 tomjack: copying into gorilla seems worth it, though

4:37 julianleviston: tomjack: howcomes? tell me about gorilla?

4:37 Glenjamin: there's various things you can get which will send text to another app

4:38 tomjack: julianleviston: well, latex, for one thing, that's very nice

4:38 plus.. everything else :)

4:38 julianleviston: tomjack: i’ve never heard of gorilla before now.

4:38 tomjack: I’ll go take a look.

4:38 tomjack: I mean, if I want to share code as pedagogy, that's what I'm gonna do

4:39 pretty nuts

4:40 cfleming: does that take a worksheet from github?

4:40 Any suggestions for one to try out?

4:43 julianleviston: Oh ok so it’s sort of like mathematica for code, similarly to that other project that was built on Om whose name eludes me right now...

4:43 mathematica for clojure*

4:44 tomjack: I'd say more "wolfram for code"?

4:44 julianleviston: So dumb question (cursive) but… how do I open my existing git project. lol...

4:44 tomjack: er, "wolfram for clojure"?

4:44 julianleviston: tomjack: same same, really… right...

4:46 (first one I found via depth-first search on the owner of the gorilla repo)

4:46 cfleming: julianleviston: Lein project?

4:46 julianleviston: cfleming: actually it’s a rails project that has a lein project inside it…

4:47 cfleming: julianleviston: ok, I guess you're not using IntelliJ Ultimate?

4:47 tomjack: pretty cool that clojure code can return latex too

4:47 julianleviston: cfleming: no… I just started.

4:47 cfleming: julianleviston: Ok, you won't get any Ruby support in that case.

4:47 julianleviston: cfleming: that’s ok. I’m fine with no ruby support :)

4:47 cfleming: just keen for the clojurescript support

4:49 tomjack: I guess: render/Renderable (render [self] {:type :latex :content "\\frac{1}{2}" :value 1/2})

4:49 cfleming: julianleviston: So I'm actually not sure what the best way to do that is. I think you'd be best creating the project from scratch, since if you import your lein project it won't know anything about the rest of it

4:49 julianleviston: So, File->New project, tell IntelliJ where it is

4:50 julianleviston: cfleming: I’ll give it a shot

4:50 using open

4:50 cfleming: julianleviston: You'll be able to use open to just open the Clojure part if that's all you need

4:50 julianleviston: Just use open, and point it to either the project.clj or the enclosing dir

4:53 julianleviston: CMD-SHIFT-N… guh.

4:55 Ah. I wish the find was softer (ie treated all punctuation as whitespace in search terms AND target files)

4:56 Argh why does option-shift-right arrow (word select kbd) include the whitespace after it?

4:57 how do I move between objects? it seems to be “move around between text” as the standard way of navigation.

4:57 (ie char-by-char)

4:57 Glenjamin: that was the issue i found when using cursive - intellij didn't quite seem to have the "usual shortcuts" i expected

4:58 julianleviston: Glenjamin: yeah well I’ll put up with that.

4:58 Glenjamin: yeah, i didn't have time to get used to it at that point :(

4:58 julianleviston: but selecting space after is a pain in the butt.

4:58 it all feels very java-y to me.

4:59 time to learn

4:59 SagiCZ: intellij is java ide after all

4:59 julianleviston: SagiCZ: yes, but clojure is built on java and it doesn’t feel like java at all, even though it is.

4:59 cfleming: julianleviston: Check https://cursiveclojure.com/userguide/keybindings.html for how to set up keybindings, or if you'd rather do it by hand go to settings->keymap

5:00 julianleviston: cfleming: sorry I shouldn’t have said anything. I’m aware there are keybindings.

5:00 cfleming: thanks! :)

5:00 Is there a good tutorial on keyboard navigation? because it’s not following anything I’m used to on MacOS

5:01 cfleming: julianleviston: Which keymap do you have selected?

5:01 SagiCZ: julianleviston: there is plenty of thing to configure in intellij.. for example if you should be able to move cursor on blank line by clicking or not

5:01 cfleming: julianleviston: Settings->Keymap

5:01 julianleviston: cfleming: whatever is standard. I’ll check.

5:01 cfleming: julianleviston: Make sure it's Mac OS X 10.5+

5:02 julianleviston: cfleming: erm… I don’t have settings. I have preferences…? but where are keymaps?

5:02 cfleming: julianleviston: Right, File->Preferences

5:02 julianleviston: Erm, no.

5:02 cfleming: julianleviston: Appearance & Behaviour -> Keymap

5:02 julianleviston: You're on a Mac?

5:03 julianleviston: cfleming: all good. Yeah, it’s under the app menu, prefences.

5:03 got it

5:03 cfleming: julianleviston: Sorry, IntelliJ IDEA -> Preferences

5:03 julianleviston: keymap was os x

5:03 switched to 10.5+

5:04 lovely

5:05 cfleming: julianleviston: Nice. That one follows Mac standards much better.

5:05 julianleviston: yeah and now I can use option up arrow to select levels of objects… huzzah :)

5:06 cannot wait until I’ve learned this. It’s the editor I’ve always wanted… for YEARS.

5:06 SagiCZ: julianleviston: have you been living under a rock?

5:07 julianleviston: SagiCZ: um no.

5:07 SagiCZ: but syntax editing editors and IDEs traditionally suck. Hard.

5:07 SagiCZ: intellij doesnt

5:07 julianleviston: SagiCZ: maybe I just have different requirements than most people.

5:08 SagiCZ: c’mon how many editors let you efficiently navigate around the actual objects of your program?

5:08 SagiCZ: as averse to the text.

5:08 SagiCZ: julianleviston: i dont understand what you mean by that

5:08 cfleming: julianleviston: Well, IntelliJ does for Java - the navigation is pretty amazing

5:09 julianleviston: SagiCZ: cfleming can you explain it to him?

5:09 SagiCZ: the semantic elements… as averse to the textual elements.

5:09 SagiCZ: well intellij can do that.. for years.. so whats the issue here?

5:10 julianleviston: SagiCZ: we’ll see, I guess :)

5:10 SagiCZ: maybe I’m assuming too much.

5:13 SagiCZ: also there is thousands of plugins..

5:13 julianleviston: cfleming: it doesn’t like om too much. Guess that’s because of the macros in it...

5:14 cfleming: julianleviston: Yeah, I'm actually working on om and om-tools support for the next release

5:14 julianleviston: cfleming: sweet.

5:14 cfleming: julianleviston: Out in a couple of days hopefully

5:20 julianleviston: cfleming: and therefore also clojurescript? Seems to be having some issue with (.. event -target -checked)

5:21 cfleming: julianleviston: ClojureScript is generally supported, although interop is difficult. There's an open issue for the .. form

5:21 julianleviston: cfleming: it’s a bit sad that macros force you to kind of… build extra bits for it.

5:21 cfleming: julianleviston: That one is just a bug/oversight. In general interop is hard though because in many cases symbol resolution is impossible

5:21 julianleviston: cfleming: yeah...

5:21 Glenjamin: you can use -> instead of .. there

5:27 julianleviston: cfleming: ok so I read the “getting around” page on doc… how do I navigate left or right at the current hierarchical level under the cursor (so if I’m at the beginning of a defn, I’d like left-this to nav to the end of the last one)

5:29 cfleming: ah ok I think I found it. I turned on other setting bindings cursive binding set and I can use paredit...

5:29 cfleming: julianleviston: Does Navigate->Structural Movement->Move Forward do what you want?

5:30 julianleviston: Ok cool

5:30 julianleviston: cfleming: one sec

5:30 cfleming: actually they’re for editing, not nav. I’ll check what you said.

5:30 cfleming: julianleviston: If you've applied the Cursive bindings it should have set one up for that

5:31 SagiCZ: .

5:31 julianleviston: cfleming: yes, structural movment -> Move Forward is it… ok I’ll check it out :) maybe the website could deal with this being on there, too :)

5:31 cfleming: sorry for so much noise. I’m just excited :)

5:32 cfleming: julianleviston: I'm pretty sure it's there - https://cursiveclojure.com/userguide/paredit.html, under Getting around

5:32 julianleviston: Hehe, no worries

5:32 SagiCZ: .

5:32 cfleming: julianleviston: Make sure you check out https://cursiveclojure.com/userguide/navigation.html too

5:34 ianhedoesit: if I have a common string such as a REST endpoint, ep.example.com, and I have multiple files which use that as a root but add onto it like /account/get-field and /settings/update, is there a better way to compose that per file other than (str core/endpoint "/settings/update?inputs=values")

5:37 I know it doesn't really save much time, I was just curious. for example, instead of just defining it in each file (i.e. (def endpoint "ep.example.com/account") in one file and (def endpoint "ep.example.com/settings") in another), including the one root endpoint from a file and changing it per file/ns

5:40 julianleviston: ianhedoesit: What would you like? You can always define a function which prepends some string to some args… (defn heythere [& args] (apply str "yeah yeah" args))

5:41 (heythere "woo") ; -> "yeah yeahwoo"

5:42 ianhedoesit: yeah, I figured. I'm not sure what I'd like. :) I was just not liking having multiple vars with the same name in different files with different meanings.

5:42 julianleviston: ianhedoesit: well if you don’t know what you’d like, then it doesn’t matter much what you write :-) <3

5:49 ianhedoesit: I'd like to not have to define the same variable in multiple files when it's slightly different, but I suppose just having one function like you said that I can easily compose stuff with would be fine.

5:51 julianleviston: ianhedoesit: I don’t understand why you have to define the same variable in multiple files… def it in one, then use require in the others.

5:52 cfleming: I can’t seem to get paredit turned on for some reason. Following https://cursiveclojure.com/userguide/keybindings.html it keeps not applying. Dunno if I should tell you this here or not!

5:53 cfleming: lots of conflicts apparently.

5:53 cfleming: julianleviston: I think this is just a case of confusing UI - if you go to your Keymaps panel, and check your actions there (search for slurp, for example) - does it have a binding applied?

5:53 ianhedoesit: julianleviston: I don't literally define the same thing multiple times in multiple files, I just have part of the same thing in multiple files (the root of the endpoint)

5:54 julianleviston: ianhedoesit: sorry I’m really not sure what you’re not able to do, then…?

5:54 ianhedoesit: but what you suggested is fine.

5:55 julianleviston: cfleming: no it doesn't.

5:55 cfleming: julianleviston: Have you copied the Mac OS X 10.5+ keymap to your own (mutable) one?

5:55 julianleviston: cfleming: yep

5:56 cfleming: then when I go into other settings -> clojure -> keybindings and choose Cursive, it has a lot of conflicts… when I apply, that “goes away”, but the bindings haven’t been applied.

5:56 cfleming: julianleviston: Hmm - when you go to the Keybindings panel and select, say, Cursive from the dropdown, what do you see? Are any actions selected?

5:57 julianleviston: I see. Could you try closing the settings panel and re-opening it? Someone else reported something similar today, and I'm not sure if this has changed in v14 or something.

5:57 julianleviston: cfleming: lots… but there are many conflicts

5:58 cfleming: sure. this will be my 5th time.

5:58 cfleming: julianleviston: It seems to work for most people though, not sure why it's problematic for some people.

5:58 julianleviston: Don't worry about the conflicts

5:58 julianleviston: The Cursive action will be used in Clojure contexts, and the default one otherwise

5:59 julianleviston: cfleming: oh… it’s working now. I have no idea what I did differently.

5:59 cfleming: god I feel like such a noob. apologies.

6:00 cfleming: julianleviston: Nah, don't, I hate this panel - it's the worst UI. Unfortunately I can't do much else since I can't customise the Keymap one.

6:00 julianleviston: I still need to make it clearer what's going on. To make it worse, what I think you were seeing there is that IntelliJ keeps a mutated copy of the settings around, but doesn't show that copy in other panels (e.g. Keymap) until you close the window.

6:01 julianleviston: Or something - there's definitely a problem in there somewhere, I can't work it out. Unfortunately this is the first thing everyone does when they try Cursive, so I have to fix it.

6:02 julianleviston: cfleming: haha :) hehe… no worries.

6:02 cfleming: thanks so much for your help. Embrace the fail, probably! :) (ie explicit instructions on how it stuffs up)

6:03 cfleming: julianleviston: Yeah, it'll have to be something like that unless I can fix it.

6:04 julianleviston: cfleming: God it’s still clunky as hell (not your fault… just what I should be able to do versus reality).

6:07 cfleming: For example, I’m two levels deep into a function… then I do “nav right” twice, and instead of going to the relative spot within the next section, it bumps me up to a higher level (level 0) and I’m now navving there. GUH. Fail.

6:07 cfleming: paredit is stupid.

6:07 cfleming: julianleviston: You'd like it to jump across at the same depth?

6:08 julianleviston: cfleming: yep.

6:09 The equivalence in prose would be… if I’m navving at word level, then I cross a sentence-bounds (ie full stop) all of a sudden I start jumping sentences and screaming running around while my house burns down ;-)

6:09 cfleming: julianleviston: What would you want here: (((foo|)) bar ((baz)))

6:09 julianleviston: sematic structure isn’t being respected.

6:10 cfleming: julianleviston: Jump to bar or baz?

6:10 julianleviston: cfleming: well, I’m navving symbols at that point, right? so… foo| -> bar| -> baz|

6:10 cfleming: julianleviston: But that doesn't respect your depth

6:11 julianleviston: cfleming: that’s true.

6:11 cfleming: but it does respect my semantic depth, I think… no?

6:11 Glenjamin: it's like when youre pressing "down" on a long line

6:11 and there's a short line

6:11 julianleviston: exactly.

6:12 think like a person, not a machine.

6:12 (that wasn’t aimed at anyone btw)

6:12 Glenjamin: that implies some level of mind-reading

6:12 julianleviston: Glenjamin: no.

6:12 cfleming: julianleviston: Ok, so it would have to remember the depth you're at and try to maintain it. Horribly stateful.

6:12 Glenjamin: Right

6:12 julianleviston: Glenjamin: it implies a good deal of syntactic analysis

6:13 Glenjamin: you need to know what i "meant" when i pressed "nav-right"

6:13 cfleming: julianleviston: Might be able to do it though, I'll think about it.

6:13 julianleviston: Glenjamin: what you mean is always bound to where you came from.

6:13 cfleming: it was actually what I thought you’d already done.

6:14 cfleming: julianleviston: But you came from somewhere else before that - it does require some mind reading to know from when you mean.

6:14 julianleviston: I don't think it's as simple as the line length case

6:14 Glenjamin: which actions continue the stateful movement, and which reset it?

6:14 julianleviston: cfleming: actually the opposite. It’s more simple than the line lenght case. Line lenght is hard.

6:14 length.

6:15 cfleming: Glenjamin: Exactly

6:16 julianleviston: cfleming: well, if I’m moving by character, then the next character. If I’m moving by symbol, then the next symbol, if I’m moving by sentence, then that, if by para, then that, if by function, then that, etc.

6:17 It would only require three levels of functions, I think… one is “move to the next at this syntactic level”, and the other is “move to the next and jump syntactic level up”, and the third is “move right, syntactic down”

6:17 so it’d need current state… (what syntactic level you’re at)… and six “keys”

6:18 cfleming: julianleviston: I don't think that's what most people want when using paredit, but maybe they're just used to something crappy.

6:18 julianleviston: cfleming: you’re right.

6:18 cfleming: I'm still not sure what you mean by syntactic level

6:18 julianleviston: cfleming: apologies for confusing this with paredit.

6:18 cfleming: Do you mean depth in the tree?

6:18 julianleviston: cfleming: not quite really.

6:18 cfleming: Or do you mean char/symbol/form

6:19 julianleviston: cfleming: I’m not completely sure but possibly depth in the tree...

6:20 cfleming: For example… I want to work on a particular function. I open a file containing it, then quickly move at function level between them until I find it, then I go into that function… now I go in go in go in, then work on a particular section of the function… perhaps within a let block… I nav around inside that let block, doing my work… refactoring forms, shifting things, etc. (and so on).

6:21 cfleming: this excited me so much because it’s possible to build meta patterns of editing on top of it. For example, you’ve done extract chunk to let block binding var, I noticed.

6:22 cfleming: julianleviston: If you're talking depth in the tree, paredit already provides move forward in, move forward out, and so on

6:22 julianleviston: cfleming: it does. But the left and right don’t work properly.

6:22 cfleming: julianleviston: Right, but you need a lot more semantic knowledge to do that right than just tree depth

6:23 julianleviston: "that" being extract let bindings

6:23 julianleviston: cfleming: Do you?

6:23 cfleming: ah.

6:23 cfleming: julianleviston: Sorry, unsynchronised writes to a single data store

6:23 julianleviston: cfleming: lol no worries :)

6:25 cfleming: I guess what I’m after is for the things we actually do to be made easier than the things we don’t do much. For example, when I’ve selected a function to work on, I very rarely need to change the arguments immediately, yet I *always* have to nav through the argument list to get to the body. W… T…. F…

6:25 cfleming: it’s not probably worth worrying about.

6:27 cfleming: julianleviston: That's definitely a worthy goal.

6:27 julianleviston: It has to be unambiguous how it works, though.

6:27 julianleviston: Anyway, I'll think about it.

6:32 julianleviston: cfleming: I think it’s probably mostly there. It’s a bit tricky, though… in that ()| () -> () |() which makes it feel like two presses between each thing, so that actually each thing is not just one thing, so it doesn’t give you the feeling of navigating between single items… it gives you the feeling of navigating between things and the spaces between them. “Beginning of form 1 -> beginning of form 2 ->

6:32 beginning of form 3” is uniform, but “beginning of form 1 -> end of form 1 -> beginning of form 2” feels… wrong, somehow.

6:32 R0B_ROD: $seen godd2 6:32 lazybot: godd2 was last seen quittingPing timeout: 246 seconds 1 day and 14 hours ago. 6:33 julianleviston: cfleming: anyways. :) let me know if you want me to muddy the water further. 6:34 cfleming: and I love your work so far! 6:44 cfleming: julianleviston: Thanks! And thanks for the feedback too, it's interesting. I think I'll try implementing the move-at-same-depth thing and see how it works. 7:43 CookedGr1phon: Hey all, I have a genclassed namespace, which gets created with an onCreate lifecycle method 7:43 I would like to use something from another namespace throughout the file so currently havea require :refer 7:43 however, I would very much like to require the namespace as part of the onCreate 7:44 so that I can do some actions immediately before loading the namespace 7:44 but still keep the convenience of the referred naming in this file 7:58 pyrtsa: Is no one else worried that clojure.core/dedupe is going to miss a reasonable number of use cases because it doesn't take a "by key" function argument? 7:59 I.e. I would've defined it as (dedupe f xs) -- remove consecutive duplicates of (map f xs); (dedupe f) -- transducer version. 8:00 It would be dead simple to just say (dedupe identity xs) when the current behaviour is needed. 8:01 julianleviston: pyrtsa: can’t why can’t you just comp it with map? 8:01 pyrtsa: sorry if that’s a stupid q. 8:01 hyPiRion: why not just call it dedupe-by ? 8:01 pyrtsa: hyPiRion: Sure, could do that as well, but don't you think it's better to just do it in clojure.core? 8:01 hyPiRion: so you can do stuff like (dedupe-by :index = xs) 8:02 Maybe. 8:03 pyrtsa: I'd still go with a signature like (dedupe[-by] f xs) 8:03 Glenjamin: i wonder how many functions like that can be defined efficiently only in terms of clojure.core 8:03 pyrtsa: I honestly don't think dedupe without a key is good library design. 8:03 Glenjamin: that would simplify massively me "one-function dependency manager" 8:04 s/me/my/ 8:04 certainly the -by variant is more widely applicable 8:04 julianleviston: pyrtsa: it’s not a library, tho… add it to contrib? 8:05 pyrtsa: julianleviston: My point is, 1.7 is still alpha. This thing could be changed for the better. 8:05 Glenjamin: is dedupe new in 1.7? 8:05 pyrtsa: Yes. 8:05 hyPiRion: Your use case would be simply (dedupe :index xs). 8:06 hyPiRion: pyrtsa: Sure, but what if I want to check on something else? 8:06 hellofunk: a simple compojure route like (GET "/some/dir/file.html" ...) returns an error 401 when accessing site.com/some/dir/file.html#whatever and I can't figure out why... is the hash something that requires explicit mention in the compojure route also? 8:06 hyPiRion: say (dedupe-by :key identity xs) 8:06 err 8:06 (dedupe-by :key identical? xs) 8:06 julianleviston: hellofunk: does it work without the location? (ie the hash) 8:07 Glenjamin: the hash shouldn't be sent to the server at all 8:07 pyrtsa: hyPiRion: Ah, *that*. 8:07 hellofunk: julianleviston: good catch, it has nothing to do with the hash, same error. 8:07 Glenjamin: looks like dedupe got added as part of rich's "transducers wip" - no separate discussion on jira afaict 8:08 it could probably be overloaded to support index-fn and comparison-fn 8:08 pyrtsa: hyPiRion: Actually, It could be (dedupe-by keyfn comp coll) 8:09 Like the longer signature of sort-by. 8:09 hyPiRion: yeah 8:10 pyrtsa: Cool. That'd work. But because of the partial application nature of transducers, I'd not 8:10 ...have (dedupe-by keyfn coll) defined at all. 8:11 hyPiRion: right. Hrm. 8:11 pyrtsa: hyPiRion: Though... sort-by asks for a Comparator. 8:11 hyPiRion: an optional comparator, mind you 8:11 julianleviston: I still don’t understand why you can’t compose them together… as in.. dedupe transducer composed with map… no? 8:11 I’m missing something aren’t I? 8:12 pyrtsa: julianleviston: You often want to keep the original and compare by some aspect of it. 8:12 julianleviston: yeah… but still 8:13 even so… i still don’t get it 8:13 pyrtsa: julianleviston: Say I'm walking a Datomic history index, only keeping the latest added/retracted boolean of the datom. If I (map :added datoms), all I've got is a sequence of booleans. 8:13 Sorry, actually the booleans is what I miss. 8:14 hyPiRion: pyrtsa: perhaps ask puredanger about this. Sounds reasonable to ask about it 8:14 pyrtsa: So a datom being a map of keys [:e :a :v :tx :added], I'd dedupe by (juxt :e :a :v). If instead, I mapped (map (juxt :e :a :v) datoms), I'd lose the :tx and :added. 8:15 hyPiRion: Cool. 8:15 Glenjamin: doesnt dedupe only do consecutive? 8:16 pyrtsa: Glenjamin: Yeah. And any sorted sequence is terrific for that! 8:16 ...Like Datomic indices. 8:16 Glenjamin: oh right, sorted by eav 8:16 pyrtsa: Yep! 8:16 ...and :tx, descending. 8:18 hyPiRion: Thinking of the most generic use case, actually (dedupe pred coll) where pred takes 2 arguments, would work. Then the ordinary use case would be (dedupe = coll). 8:20 hyPiRion: pyrtsa: Would be a bit ugly to get the result you wanted though 8:21 pyrtsa: Agreed. 8:23 hyPiRion: ,(defn asidef [f nxt] (fn [& xs] (apply nxt (map f xs)))) 8:23 clojurebot: #'sandbox/asidef 8:23 hyPiRion: ,((->> = (asidef :key) (asidef :key)) {:key {:key 1}} {:key {:key 1}}) 8:23 clojurebot: true 8:33 sveri: Hi, is anyone here using environ? I am having trouble to get profiles.clj to work. It does work some sort of, but somehow does not recognize I am in dev mode anymore. There also seem to be problems with cljx regarding environ. Anyone experienced this or using a different approach? 8:35 jballanc: sveri: we've switched over to Nomad 8:35 not quite as convenient as environ, but seems to be a bit more robust 8:36 clgv: sveri: if you can't trace it in the lib maybe that lib is too complex. 8:37 sveri: jballanc: this is the third time I don't get it running, I guess I give nomad a try too 9:01 clgv: With profiles.clj I should be able to replace all repositories by my own private proxy repository, correct? 9:02 jballanc: in theory 9:02 engblom: While I am more productive in Clojure than in Haskell, Clojure seem to be much more difficult to teach to other than Haskell. It is easier to pick out a subset to teach when it comes to Haskell. 9:02 clgv: jballanc: did you experience differently in practice? 9:03 engblom: Has anyone been teaching Clojure here? 9:04 tbaldridge: I have a friend who has picked up Clojure after only about a year in Python/Java (no programming experience at all before that). 9:05 He's pretty much taken Clojure for the Brave and True and ran with it, no major issues yet 9:05 clrnd: engblom, I have taught haskell and it can be quite difficult sometimes 9:05 the_frey: that's a great way to get up to practical usefulness 9:05 CFTBAT that is 9:06 tbaldridge: the_frey: yeah, and the early videos by Rich provide a nice basis to the whole thing. 9:07 So I'm about to spout something that could be considered slightly offensive and/or controversial: 9:07 TEttinger: gasp 9:07 tbaldridge: engblom: my theory is that Haskell might be easier to start teaching to people since there are so many small details that can be covered before actually getting to the useful stuff. 9:08 You have to have discussions about types, IO monads and the like before even getting to a Hello World!. In clojure you just plop a println anywhere, and can use slurp on a whim. 9:09 TEttinger: tbaldridge: so there's more that you can use with minimal necessary knowledge, so that's a broad base to cover 9:09 tbaldridge: So while it seems like they are learning a good foundation of what is needed to program Haskell, I'd question how useful this basic Haskell knowledge is. 9:09 clgv: engblom: you can start teaching Clojure similarly as you would teach Common Lisp. Start from functions definition over Control flow constructs to sequence ops (map, reduce ...) 9:09 Glenjamin: so you reckon people struggle because they get to the "i can do stuff, what should i build?" step sooner? 9:09 tbaldridge: Glenjamin: exactly. 9:10 TEttinger: I agree, definitely 9:10 Glenjamin: the idea has a certain smug appeal :) 9:10 clrnd: and SICP, it get's you to nothing to "write your own lazy eval champ!" in a few weeks 9:10 tbaldridge: and they quickly hit really hard problems (concurrency, web interop, talking to a DB, etc), and those take time to figure out. 9:10 clrnd: from* 9:12 CookedGr1phon: Can anyone think of a neat way to do a scoped require in clojure? What I want is when the block of code gets hit, it requires a namespace, loads if required, and then refers some functions but only within the scope of that one statement 9:13 tbaldridge: (require .... :as ~(gensym "ns_name")) 9:13 Glenjamin: CookedGr1phon: why? 9:13 tbaldridge: ^^ don't do that ;-) 9:13 CookedGr1phon: I'm trying to narrow down and coordinate when namespaces get loaded in order to get my startup as slick as possible, and namespaces are too granular 9:14 waiting for everything to load (simply running through the namespace dependency tree) takes ~6 seconds, but I can get something on the screen and reacting in under 200ms if I only load what I need at the very start, and then load the rest in the background 9:15 I can obviously make smaller namespaces, but then my code is horrible to follow 9:15 so yeah, trying to find a way to get finer control over this 9:16 borkdude_: does anyone have an example of Riemann instrumentation of a compojure app 9:18 clgv: CookedGr1phon: so you app has to be able to do meaningful stuff while the other parts are still loading? 9:18 CookedGr1phon: clgv: yeah on other threads 9:18 clgv: CookedGr1phon: require from multiple threads? have fun with that ;) 9:19 CookedGr1phon: heh, ideally I won't be requiring from multiple threads 9:19 the code loading all happens in one thread, just in a strict order 9:19 and then when the code is loaded, I let it go off and start doing useful work 9:29 julianleviston: jog my memory… find first in coll satisfying pred? not some, but … ? 9:30 just first filter? 9:30 Glenjamin: yeah 9:30 stuartsierra: or (some (fn [x] (when (pred x) x)) coll) 9:31 julianleviston: oh nevermind, http://stackoverflow.com/questions/10192602/return-first-item-in-a-map-list-sequence-that-satisfies-a-function-returning-tru says (some #(if (= % 1) %) '(3 4 1)) which works well... 9:31 stuartsierra: exactly! cool thanks.. Hey hi by the way. I loved your book! 9:31 oh no I got confused… I mean I loved component. 9:32 stuartsierra: julianleviston: thanks :) 9:32 julianleviston: stuartsierra: plus I really liked your last talk on it. 9:32 (inc stuartsierra) 9:38 clgv: lazybot seems to be on vacation 9:39 Glenjamin: (dec lazybot) 9:45 clgv: (lazybot) ; where is the irc metabot restarting lazybot? ;) 9:45 (send-off raynes restart lazybot) 9:47 bonsai_hk: quick show of hands: who is NOT into web programming 9:48 clgv: bonsai_hk: mostly algorithm dev 9:48 julianleviston: bonsai_hk: do you mean not only? 9:48 bonsai_hk: or not at all? 9:48 bonsai_hk: julianleviston: let's say your current focus for some definition of focus 9:49 clgv: like algorithmic trading? 9:49 tbaldridge: probably about 90% of my work is backend DB stuff, eventually it has a web API, but don't touch that much 9:49 clgv: bonsai_hk: no 9:49 bonsai_hk: scroll down to "which domains ..." 9:51 bonsai_hk: clgv: I've seen the survey thanks but no IRC handles there to chat to :-) 9:52 tbaldridge: well is it the request - db lookup - response kind of backend? it would be web ish 10:27 luxbock: ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret) 10:28 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading> 10:28 luxbock: hmm 10:29 is there a better way to do this? I'd like to get a vector/list of the expressions in the traversal order 10:29 justin_smith: &(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) 10:29 ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) 10:29 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.walk, compiling:(NO_SOURCE_PATH:0:0)> 10:29 justin_smith: ,(require 'clojure.walk) 10:29 clojurebot: nil 10:29 justin_smith: ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) 10:29 clojurebot: [(let [x 123] (+ x 456)) let [x 123] x 123 ...] 10:29 clgv: luxbock: you are using transients wrongly anyway 10:30 luxbock: yeah? 10:30 clgv: you'd need to put the vector in an atom 10:30 hyPiRion: (inc clgv) 10:30 luxbock: ah right 10:30 justin_smith: luxbock: you need to use the return value of conj! 10:30 luxbock: first time using them 10:30 clgv: yes. for hashmaps this would certainly fail for larger input (> 16 elements?) 10:30 justin_smith: luxbock: or, even worse, *sometimes* your code doesn't work if you fail to use the return value 10:30 hyPiRion: clgv: 8 10:30 luxbock: I was wondering if there was a way to do this without the transient 10:30 or atoms 10:31 clgv: hyPiRion: ah 8 key+val pairs? 10:31 justin_smith: luxbock: sure, write your own walker, and carry two accumulators 10:31 hyPiRion: yus 10:31 ,(let [t (transient {})] (dotimes [i 10] (assoc! t i i)) (count t)) 10:31 clojurebot: 8 10:31 clgv: luxbock: not with clojure.walk 10:32 luxbock: alright, I think this looks a bit ugly but it's so much easier than writing my own walker that I'll just use an atom 10:32 clgv: luxbock: but you can write your own preorder traversal with apropriate value passing 10:32 it'll be just a recursive function after all 10:33 luxbock: right 10:38 darrenh: is there an idiomatic way to coerce something that may be a list of strings or a single string into a list? eg. (foo "bob") --> ["bob"], (foo ["bob" "fred"]) --> ["bob" "fred"] 10:38 llasram: darrenh: no, and in my experience wanting to do that is an anti-pattern 10:39 darrenh: This is to handle what ring does with multi-valued params 10:39 llasram: Ah 10:39 darrenh: I'd rather ring always returned a list 10:39 justin_smith: darrenh: one option would be a multimethod with implementations for string and list 10:39 llasram: Ok, yeah. So in this case you know ring will always yield a string or a vector, so you can just check that 10:40 justin_smith: multimethod may be overingeneered if you only get two types though 10:40 llasram: (checking generically for "any sort of sequential collection" is bizarrely more difficult) 10:40 justin_smith: ,(sequential? "hello") 10:40 clojurebot: false 10:41 darrenh: ah yes, I was thinking (flatten (merge [] "x")) 10:41 justin_smith: ,(map sequential? ["hello" () []]) 10:41 clojurebot: (false true true) 10:41 justin_smith: ,(merge [] "x") 10:41 clojurebot: ["x"] 10:41 llasram: ,(sequential? (java.util.ArrayList.)) 10:41 clojurebot: false 10:41 darrenh: ,(flatten (merge [] ["a" "b"])) 10:41 clojurebot: ("a" "b") 10:41 justin_smith: llasram: good point 10:42 darrenh: I have actually never seen merge used with [], why not into? 10:42 darrenh: ,(merge [] [:a :b]) 10:42 clojurebot: [[:a :b]] 10:42 TimMc: wait what 10:42 darrenh: ,(flatten (into [] "x")) 10:42 clojurebot: (\x) 10:42 darrenh: yeah, that didnt work :) 10:43 justin_smith: flatten is terrible 10:43 hyPiRion: sure, merge just does that strange conj thingy 10:43 TimMc: ~flatten 10:43 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with. 10:43 hyPiRion: ,(conj {:a :b} {:c :d :e :f}) 10:43 clojurebot: {:c :d, :e :f, :a :b} 10:43 Glenjamin: proposal to remove flatten from core 10:43 justin_smith: hyPiRion: oh, of course, merge is just calling conj 10:43 ,(flatten {:a 0 :b 1}) 10:43 clojurebot: () 10:43 justin_smith: ,(flatten "hello") 10:43 clojurebot: () 10:45 clgv: darrenh: Most of the time you want (apply concat coll) instead of (flatten coll) 10:46 darrenh: It doesn't take too long until an implementation using flatten, will suprise you with unexpected output 10:46 justin_smith: clgv: well, his given usecase is that he might get {:key "val"} or {:key ["val1" "val2"]} from the ring api 10:46 hyPiRion: just wrap it in a list if you really need it 10:46 justin_smith: but a simple if is better than a flatten there (checking for vector?) 10:46 hyPiRion: well, the problem is that the API sometimes gives him a coll of strings, sometimes a string 10:47 darrenh: clearly the correct solution is to fix the ring api to be consistent at the expense of convenience ;) 10:47 justin_smith: darrenh: sometimes a coll sometimes a string is not convenience 10:47 not when you need to write code that uses the result 10:48 clgv: ah in that case.... darrenh: I usually have a utility function similar to (defn ->sequential [x] (if (sequential? x) x [x])) 10:48 darrenh: most query strings do not have multi-valued params, so returning a string most of the time is convenient.. most of the time 10:49 clgv: thanks 10:51 a lot of web frameworks have this 'surprising array when you expected a strign' issue 10:51 clgv: darrenh: often used in macro implementations that support lists and single values 10:51 darrenh: ha! try json rendering in "GNU R" - it maximises those kind of surprises... 10:52 justin_smith: darrenh: which leads to a conundrum if you want "principle of least surprise" - is the most surprising thing to offer a string sometimes, an array others, or to not provide that surpise like the others do? 10:53 darrenh: I'd go for consistency - it would confuse a new developer briefly, then they would learn the valuable lesson that query params can repeat, saving themselves much future pain 10:54 justin_smith: you mean consistency with everyone else, not consistency within the API 10:54 darrenh: consistency within the api: all query values are lists 10:54 justin_smith: ahh 10:54 :) 10:54 Glenjamin: a different access pattern for string vs seq is the only option that's unambiguous and still simple imo 10:55 kodumulo: On http://martintrojer.github.io/clojure/2013/07/07/coreasync-and-blocking-io/ it says that thread parking breaks the 1thread = 1 job "knot". When you park a thread does that mean that thread can do other work without spawning a new thread? 10:55 justin_smith: kodumulo: parking means your task no longer holds the thread 10:56 and the thread can go do other things 10:56 when your data is ready, some other thread will pick up the process where it left off 10:56 kodumulo: Ah so its not like the job *lives* in the thread. The job is independent and *uses* the thread when needed 10:57 justin_smith: kodumulo: right, or you could say the threads pick up jobs as they are ready to do work, and drops them as they park 10:57 julianleviston: kudumulo - core async threadparking uses a threadpool 10:59 kodumulo: Thats a brilliant concept. It kinda reminds me of a ruby fiber 10:59 justin_smith: kodumulo: the general concept is called "green threads" 10:59 kodumulo: ah 11:00 justin_smith: but in clojure it's a little different, because there are also multiple real threads 11:00 kodumulo: I thought green threads were just threads that didn't get their own cpu, like in ruby 11:00 julianleviston: justin_smith: unless you’re in cljs. ;) 11:00 ToxicFrog: justin_smith: "greenthreads" are specifically things that look like threads to code running in the interpreter but are all hosted in the same OS thread, unrelated to thread pools 11:00 Glenjamin: i also see it called 1:N threading 11:00 justin_smith: ToxicFrog: ahh, sorry 11:00 julianleviston: kodumulo: you probably don’t want to think about ruby threads. It’s a friggin nightmare. 11:01 kodumulo: julianleviston: one of the reasons I use clojure now in the first place ;) 11:01 Glenjamin: Fibers are the same/a similar system to this 11:01 kodumulo: and dependencies, rubygems is a nightmare as well 11:01 julianleviston: kodumulo: likewise ;-) the GIL … guh! 11:01 justin_smith: ToxicFrog: regardless, the same implementation issues that come up with green threads also come up with core.async style threads - you need your own threading logic in the vm 11:01 julianleviston: kodumulo: yeah, a whole bunch of things… 11:02 kodumulo: OOP is really just not very good for DRY. 11:03 justin_smith: ToxicFrog: is there a general term for this kind of mix of multiple real threads, with green-thread style pseudo-threading? 11:04 julianleviston: justin_smith: timesharing? 11:04 Glenjamin: ah, M:N model, that's what i was thinking of 11:04 justin_smith: aha! 11:05 Glenjamin: yeah, just found this as you said that http://en.wikipedia.org/wiki/Thread_%28computing%29#M:N_.28Hybrid_threading.29 11:08 muller: is mapcat map followed by cat? 11:08 Glenjamin: concat, yes 11:08 justin_smith:$source mapcat

11:08 TimMc: There is no cat.

11:08 muller: yeah concat

11:08 Glenjamin: there is now!

11:08 slipset: while on the topic of core.async

11:08 llasram: (doc cat)

11:09 clojurebot: "([rf]); A transducer which concatenates the contents of each input, which must be a collection, into the reduction."

11:09 justin_smith: TimMc: I thought there was a cat transducer

11:09 TimMc: Oy, transducers.

11:09 slipset: the fact that the go-macro is implemented as a state-machine

11:09 justin_smith: (source mapcat)

11:09 Glenjamin: that docstring should really say "EAGER" on it massive letters

11:09 slipset: is that inherent to CSP, or does the idea stem from som other place?

11:10 TimMc: 𝑬𝑨𝑮𝑬𝑹

11:10 justin_smith: slipset: I think CSP was first articulated in terms of state machines, it was a CS thing after all

11:10 muller: ,(mapcat reverse [[3 2 1 0] [6 5 4] [9 8 7]])

11:10 slipset: justin_smith:hmm, I started reading the CSP book by Hoare, but sort of fell off before the state machine was mentioned.

11:10 clojurebot: (0 1 2 3 4 ...)

11:10 muller: ,(concat (map reverse [[3 2 1 0] [6 5 4] [9 8 7]]))

11:10 clojurebot: ((0 1 2 3) (4 5 6) (7 8 9))

11:11 justin_smith: slipset: double checking that now

11:11 muller: not the same?

11:11 justin_smith: muller: apply concat

11:11 muller: what

11:11 slipset: I guess CSP mentions processes as state-machines, which makes sense.

11:11 justin_smith: ,(apply concat (map reverse [3 2 1 0] [6 5 4] 9 8 7]]))

11:11 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

11:11 justin_smith: ,(apply concat (map reverse [3 2 1 0] [6 5 4] [9 8 7]]))

11:11 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

11:12 justin_smith: ,(apply concat (map reverse [[3 2 1 0] [6 5 4] [9 8 7]]))

11:12 clojurebot: (0 1 2 3 4 ...)

11:12 muller: why do we need apply i don't get it

11:12 julianleviston: when the input is a collection instead of direct arguments

11:12 justin_smith: muller: map can only return one collection

11:12 Glenjamin: (doc concat)

11:12 clojurebot: "([] [x] [x y] [x y & zs]); Returns a lazy seq representing the concatenation of the elements in the supplied colls."

11:12 slipset: but the whole thing, which is nicely explained here http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/

11:12 justin_smith: muller: concat needs multiple args

11:12 TimMc: muller: I hand you [1 2 3 4 5]. Add them.

11:13 (reduce is cheating :-P)

11:13 slipset: shows how the, I guess green thread like thingy in the go-macro is implemented as a state-machine

11:13 muller: ,(apply + [1 2 3 4 5])

11:13 clojurebot: 15

11:13 muller: ok :P

11:13 Glenjamin: ,((constantly 15) [1 2 3 4 5])

11:13 clojurebot: 15

11:14 muller: I misunderstood what concat does

11:14 justin_smith: Glenjamin: :P

11:14 Glenjamin: needs more than one testcase

11:15 justin_smith: slipset: I just double checked, by page 12 it is definitely talking about state machines http://www.usingcsp.com/cspbook.pdf

11:15 clgv: test.check ;)

11:16 slipset: justin_smith: yes, but that's sortof the vending machines state-machine

11:16 and that makes sense

11:17 but as I (akwardly) tried to formulate, my question is around how the go-macro is implemented

11:17 and the usage of a state-machine to "flatten" the callback hell.

11:17 justin_smith: slipset: I think I missed your followup while skimming the csp doc

11:18 kodumulo: in cider can you reload project dependencies from repl or do do you need to quit and start new session?

11:18 do you*

11:18 justin_smith: kodumulo: you can redefine functions or reload namespaces, but to change a dep version you need to restart the vm

11:18 kodumulo: justin_smith: thanks

11:19 everytime i cider-jack-in i feel like neo

11:24 muller: is there a difference between (1 2 3) and [1 2 3]?

11:24 clgv: muller: list vs vector

11:24 muller: ok

11:25 ToxicFrog: muller: [1 2 3] is a vector literal. (1 2 3) tries to call 1 with arguments 2 and 3 and evalutes to the result. '(1 2 3) is a list.

11:25 slipset: justin_smith:seems like c# await is implemented as a state-machine as well

11:25 justin_smith: slipset: yeah, a lot of things have state machines at the bottom, they are a very well understood abstraction

11:25 ToxicFrog: ,(map type [[1 2 3] '(1 2 3)])

11:25 clojurebot: (clojure.lang.PersistentVector clojure.lang.PersistentList)

11:26 ToxicFrog: ,(type (1 2 3))

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

11:26 muller: yeah I meant '(1 2 3)

11:26 TimMc: justin_smith: "I don't even see the parens anymore; all I see now is juxt, dosync, let."

11:26 julianleviston: muller: yeah, vectors and lists are different.

11:26 justin_smith: muller: most things that work with '(1 2 3) work with [1 2 3] also - usually what matters in clojure are the interfaces more than the concrete types

11:26 TimMc: heh

11:27 zerokarmaleft: whoever said that is going to betray everyone for a steak

11:27 TimMc: Err... I guess I meant that for kodumulo.

11:27 justin_smith: TimMc: I was about to say that

11:27 julianleviston: muller: vectors are fast to add to the end of, and to look up. Lists aren’t particularly.

11:28 kodumulo: TimMc: lol

11:28 justin_smith: TimMc: that's definitely true though, the parens disappear

11:28 muller: list is a singly linked list, and vector stores elements in sequence in the memory, like an array in C?

11:28 kodumulo: I (->) all the things so they do actually disappear ;)

11:28 Glenjamin: someone once pointed out i had 14 parens on the end of a line

11:28 julianleviston: muller: can I recommend you read clojure in small pieces?

11:28 Glenjamin: i hadn't noticed

11:29 justin_smith: muller: vector is more like a tree of arrays - it's complicated

11:29 muller: hyPiRion has a good series of blog posts about vector implementation if you really want to know the whole deal

11:29 muller: okay

11:29 julianleviston: muller: or, watch rich hickey’s talks on the persistent data structures.

11:29 Glenjamin: it's safe to say it acts much like an array, but is persistent

11:29 justin_smith: muller: http://hypirion.com/musings/understanding-persistent-vector-pt-1

11:29 julianleviston: muller: http://daly.axiom-developer.org/clojure.pdf

11:30 muller: thanks

11:30 borkdude: I'm trying a query in the Riemann dashboard but I keep getting a parse error. My query is simply: '(service = "metri")'

11:31 julianleviston: muller: https://www.youtube.com/watch?v=ketJlzX-254

11:31 Glenjamin: borkdude: i think there's a riemann irc channel

11:31 borkdude: I get invalid term \"metri\"

11:31 Glenjamin thanks

11:32 muhuk: How come this isn't infinite recursion? https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L1478

11:32 julianleviston: muller: coz it’s a call to the runtime.

11:33 hyPiRion: muller: the most important part to know for a person new to Clojure is that a vector acts like an immutable arraylist, yet is superfast for the operations you usually do on arrays/arraylists

11:33 julianleviston: muhuk: sorry… coz it’s a call to the runtime.

11:33 muhuk: justin_smith: isn't (keys map) (the 2nd) evaluated first?

11:34 julianleviston: muhuk: the java interop character calls the keys method on the runtime.

11:34 muhuk: that’s my understanding, anyway.

11:34 Glenjamin: i always find (. obj (method arg)) really weird

11:35 muhuk: julianleviston: what I see is it's calling the result of (keys map) on RT

11:35 Glenjamin: especially when (. obj method arg) does the same thing

11:35 julianleviston: muhuk: nah...

11:35 muhuk: I see

11:35 hyPiRion: muhuk: Think of it as (clojure.lang.RT/keys map)

11:35 julianleviston: muhuk: (. clojure.lang.RT (keys map)) means “send the keys message to RT with the arg map”

11:35 ToxicFrog: ...wow, that's a really unclear way of writing it.

11:35 muhuk: got it, thanks

11:36 julianleviston: ToxicFrog: and yet, it’s much easier than native java when you get used to it.

11:36 Glenjamin: ,[(. "a" (equals "a") (. "a" equals "a")]

11:36 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

11:36 julianleviston: the . interop operator behaves more similarly to the threading macros really.

11:36 Glenjamin: oh, missed a paren

11:36 ,[(. "a" (equals "a")) (. "a" equals "a")]

11:36 clojurebot: [true true]

11:37 Glenjamin: i find it very odd that those two do the same thing

11:37 TimMc: It only becomes important when you have a nullary method.

11:37 and I guess a field with the same name :-P

11:37 Glenjamin: oh, the former is always a fn, but the latter can be a field?

11:37 ToxicFrog: julianleviston: no, I mean, it's much more unclear than either (. RT keys map) or (RT/keys map)

11:38 And AFAIK has the same semantiocs

11:38 julianleviston: ToxicFrog: k.

11:38 hyPiRion: let's try it out

11:38 ,(clojure.lang.RT/keys {:a 1 :b 2})

11:38 clojurebot: (:b :a)

11:39 TimMc: Glenjamin: As I understand it, yes. As long as there are no args.

11:39 justin_smith: ,(Math/PI) ; more interop "fun"

11:39 clojurebot: 3.141592653589793

11:39 TimMc: (.foo obj) could be a field access or method call.

11:39 ToxicFrog: hyPiRion: there we go then.

11:39 TimMc: justin_smith: :-(

11:39 Glenjamin: ,(. (first {:a 1}) key)

11:39 clojurebot: :a

11:39 Glenjamin: erm, that's not what i meant to do

11:39 but it worked :s

11:40 to the local repl!

11:40 ToxicFrog: (. obj method (a b c ...)) I could see, maybe, but (. obj (method a b c ...)) just rubs me the wrong way.

11:40 hyPiRion: justin_smith: whut

11:40 ,Math/PI

11:40 clojurebot: 3.141592653589793

11:40 hyPiRion: ok, that's a tad weird

11:41 Glenjamin: ,[(. (first {:a 1}) getKey) (. (first {:a 1}) (getKey))]

11:41 clojurebot: [:a :a]

11:41 clgv: ,(read-string "(Math/PI)")

11:41 clojurebot: (Math/PI)

11:41 clgv: ,(macroexpand-1 (read-string "(Math/PI)"))

11:41 clojurebot: (. Math PI)

11:42 clgv: ,(macroexpand-1 (read-string "Math/PI"))

11:42 clojurebot: Math/PI

11:46 clgv: Bronsa: alright.

11:48 justin_smith: hyPiRion: I think it is backward compatibility or something?

11:51 stuartsierra: yes, there were several variant syntaxes for the . special form before the .method and Foo/static syntax were introduced.

11:52 And (.field object) still works on Clojure JVM despite the addition of (.-field object)

11:56 clgv: I always thought (.-field object) is CLJS only...

12:10 justin_smith: clgv: well, java classes are much less likely to have fields you use directly (as opposed to an accessor method)

12:12 clgv: justin_smith: what is that referring to?

12:13 hyPiRion: TimMc: how's that Swearjure transpiler going, btw?

12:13 julianleviston: clgv: interop

12:14 clgv: julianleviston: that is surprising

12:16 TimMc: hyPiRion: On hold since forever. Function-calling is actually tricky -- you have to know whether it's a call like (:foo {}) or a call to a swearjure-transpiled fn.

12:17 Glenjamin: convert to AST in between?

12:17 TimMc: and sometimes the latter is derived from an expression like (if x fn1 fn2).

12:18 Glenjamin: I may just say that you can never call a swearjure-transpiled fn, but have to use a form like (fncall f a0 a1 a2)

12:18 Glenjamin: that seems simple enough

12:19 TimMc: THat was the only technical stumbling block I ran into. The main problem is that I have better things to do. :-P

12:19 clgv: TimMc: damn that's a pity. so swearjure is never going to see broad application in industry ...

12:19 Glenjamin: in other news, i got turned down for a remote UK clojure job today in favour of someone younger and cheaper >.<

12:19 TimMc: clgv: Pull requests welcome!

12:19 clgv: TimMc: :P

12:19 zerokarmaleft: TimMc: what would a swearjure conference be called?

12:20 clgv: zerokarmaleft: pub brawl?

12:20 TimMc: zerokarmaleft: Something unprintable, I'm sure.

12:20 justin_smith: our local clojure meetup is clojerks, so I imagine swearjerks would work nicely for swearjure

12:20 TimMc: #<conj>

12:21 justin_smith: oh wait, what's swearjure for conj?

12:21 hyPiRion: TimMc: asking because http://hypirion.com/musings/swearjure-is-turing-complete

12:21 justin_smith: it's just [~@xs ~x]

12:21 zerokarmaleft: hah, perfect

12:22 justin_smith: so, it's "the swearjure [~@xs ~x]" of course

12:22 the unpronouncability is a feature

12:22 hyPiRion: heh

12:22 The conj function is something like

12:23 TimMc: hyPiRion: Oh fuck, replacing the binding form! Brilliant!

12:23 justin_smith: "the swearjure syntax-quote vec-literal unquote deref xs unquote x endvec"

12:23 hyPiRion: justin_smith: #([[~@% ~([~@%&](+))]](+)) I think

12:24 justin_smith: oh wow

12:24 julianleviston: Glenjamin: how old are you? If I’m allowed to ask

12:24 Glenjamin: 27 :)

12:24 justin_smith: I won't try to spell out the pronunciation of that

12:24 julianleviston: Glenjamin: waaaaaa? that’s just weird.

12:24 hyPiRion: TimMc: yeah, it's awesome. You can actually make sensible programs with Swearjure now :D

12:24 Glenjamin: well, the other guy was probably a fresh grad without 5 years of building software experience, hence cheaper

12:25 julianleviston: Glenjamin: oh well, I guess they’ll pay. LOL.

12:25 Glenjamin: Even 5 years is not very much.

12:26 Glenjamin: depends where & what you worked on :)

12:26 julianleviston: Glenjamin: I’m not convinced of that.

12:26 Glenjamin: well, not every 5 years of experience is the same

12:26 julianleviston: Glenjamin: but yes, the only thing you can really say about age is that it provides opportunity...

12:27 Glenjamin: no guarantees the person is going to have used it wisely or not.

12:27 Glenjamin: it's possible to have less overall experience after 20 than it is after 5, but obvisouly the theoretical maximum after 20 years is higher

12:27 TimMc: hyPiRion: So we can do the ski calculus now?

12:27 hyPiRion: TimMc: yes

12:27 julianleviston: Glenjamin: of course, this disregards all the things that actually matter, too. ;-)

12:27 TimMc: oop, just go to that part of the blog post

12:27 Glenjamin: anyway, the guy was probably demonstrably cheaper, and that was due to lack of experience - either in software or negotiation

12:27 TimMc: *got

12:28 julianleviston: Glenjamin: yeah, like I say, though, they’ll pay ;-)

12:28 * hyPiRion &

12:29 julianleviston: Glenjamin: I wonder how old he is? Less than 5 years in a lisp is like… do they actually understand stuff? lol. Like… I think it took the last junior I taught about 4 years to start understangin map and don’t even talk about reduce.

12:30 clgv: hyPiRion: isnt the usage of x,y,z cheating? ;)

12:30 julianleviston: Glenjamin: I mean understanding when to use it and whatnot. <shrug> ah well...

12:35 TimMc: clgv: It's equivalent to $,+,- 12:35 Well, no... ++, --, +- 12:36 clgv: TimMc: ok ;) 12:38 TimMc: hyPiRion: since floats in our cpus are finite you should be able to emulate them as well, right? 12:39 ah well, only if / would return doubles instead of ratios... damn 12:57 mikerod: Why would I be getting issues related to lein-cljsbuild when I do not have it configured as part of my leiningen project? 12:57 "WARNING: no :cljsbuild entry found in project definition." these sorts of issues 12:57 and then subsequently, I get failures for the more recent version of cljs now requiring Java 7 I guess 12:57 muller: julianleviston what.. map is easy.. reduce, granted, is a bit harder to grasp for newbies 12:57 mikerod: I don't need cljs for my particular workflow right now. It just started failing within the last day or so when I haven't added a dependency of any sort. 12:58 "You're using [lein-cljsbuild "1.0.4"], which is known to work well with ClojureScript 0.0-2197 - *." I do not even see a lein-cljsbuild in my lein deps :tree or lein deps :plugin-tree 12:58 So I'm wondering if something is implicitly going on with leiningen now. 13:15 vas: hello, is somnium the preferred way to connect to mongodb with clojure ^.^ ? 13:16 {blake}: vas: I use monger. 13:16 agarman: I use the java driver directly 13:16 vas: {blake}: thanks thanks. 13:17 {blake}: vas: No problem. 13:18 agarman: been awhile since I was in there, but also using monger 13:20 {blake}: If I were doing it again now, I might use JDBC directly! Not that there's anything wrong with Monger, just not sure what I got from using it. 13:21 agarman: monger mostly converts mongo data structures <-> clojure data structures 13:22 and doesn't make a new DSL to hide mongos... 13:22 {blake}: Well, I notice using JDBC directly (for mssql) it returns thing as a map. 'bout all I need. 13:22 Yeah, I'm...iffy...on the DSL thing. 13:23 I used to be pro-DSL until I started using Ruby hardcore. =P 13:26 vas: agarman: so you prefer to use the driver directly currently? how would I go about that? 13:31 agarman: @vas monger was fine...it turns Mongo's command language into a DSL written in Clojure functions and converts stuff into and out of Mongo for you. 13:32 @vas I'd probably start with the Java driver today. I'm not big for including a lot of little, simple libraries in my projects. 13:34 @vas though Monger only adds transitively adds two deps, which isn't so bad 13:35 vas: agarman: yeah, simplicity is :key. maybe i will start with monger then until i get the hang of things. thank you for your words 13:57 does anyone use any templating for CSS, such as jade or haml? 14:04 {blake}: vas: Under Ruby, I have. In Clojure, I've just used Hiccup. 14:04 Althought that's not CSS, so never mind. =P 14:05 vas: {blake}: selectors and stuff, yeah. i don't mind playing css-ninja with the actual files, but i do kinda miss the elegance of jade, for example. 14:06 {blake}: This might be instructive: http://blog.getprismatic.com/bringing-functional-to-the-frontend-clojure-clojurescript-for-the-web/ 14:13 vas: {blake}: you're the best. that link appears to be just what i needs. 14:13 {blake}: vas: Terrific! 14:25 vas: general question: i am returning a list '({:tag :div, :attrs {:id thangID}}) ... i want to evaluate thangID before returning the list, but using the ~ operator just returns (clojure.core/unquote thangID) instead of evaluating... any suggestions? 14:27 muller: why do I get a list in here? 14:27 {blake}: vas: Wouldn't that be... (thangID)? 14:27 muller: ,(map reverse [[1 2 3] [4 5 6]] 14:27 {blake}: What do you mean by "evaluate"? 14:27 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading> 14:27 muller: no 14:27 ,(mapcat reverse [[1 2 3] [4 5 6]]) 14:27 clojurebot: (3 2 1 6 5 ...) 14:27 muller: why a list and not a vector? 14:28 ,(map reverse [[1 2 3] [4 5 6]]) 14:28 clojurebot: ((3 2 1) (6 5 4)) 14:28 {blake}: muller: It's my understanding that, generally, functions use the structure that works best for their operations. 14:28 So changing from one type to another is pretty usual. 14:29 muller: but isn't that what this code is doing? it changes the type from vector of vectors to list of lists 14:29 oh sorry, I've read that as unusual 14:29 reverse seems to be the culprit 14:30 ,(reverse [1 2 3]) 14:30 clojurebot: (3 2 1) 14:30 {blake}: muller: Map is building a list by concatenating items, I think. Which is easiest done in a list. 14:30 ,(map inc [1 2 3]) 14:30 clojurebot: (2 3 4) 14:30 muller: oh map always returns a list 14:30 {blake}: ,(mapv reverse [[1 2 3][4 5 6]]) 14:30 hyPiRion: map is lazy, which is why you get back a seq 14:30 clojurebot: [(3 2 1) (6 5 4)] 14:30 ianhedoesit: ,(rseq [[1 2 3] [4 5 6]]) 14:30 clojurebot: ([4 5 6] [1 2 3]) 14:30 hyPiRion: Also, if you know your input is always going to be a vector, use rseq 14:31 ianhedoesit: hey, I just did that! :) 14:31 hyPiRion: ianhedoesit: yeah, you beat me to it :) 14:32 muller: that's doesn't do the same thing 14:32 aperiodi1: vas: your immediate problem is that ~ only works inside of , not '. but why not just do (list {:tag :div, ...}) if you really want a list 14:33 muller: it is reversing outter vector, i am reversing inner vectors 14:33 ianhedoesit: ,(into [] (mapcat reverse [[1 2 3] [4 5 6]])) 14:33 clojurebot: [3 2 1 6 5 ...] 14:36 muller: ,(into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) 14:36 clojurebot: [[3 2 1] [6 5 4]] 14:36 muller: anything better? 14:36 is there a map/reverse equivalent that keeps the original data structure 14:37 vas: aperiodic: thanks. (list) is much easier to play with. 14:37 jackhill: muller: I don't know, but I'm curious about why you want to keep the original structure. 14:39 {blake}: muller: Are there many things at all in Clojure that preserve data structures, I wonder. 14:39 I mean, to preserve it, you sort of have to know what it is, don't you? 14:40 muller: jackhill I am just learning now. but in real code I would want to keep it a vector, because, pressumably, I picked vector over a list or sequence it for a reaswon, rather than randomly 14:41 jackhill: muller: ah. I wonder if I need to start doing that. 14:41 vas: aperiodic: excellent. got to the bottom of my issue with your insightful catalyst. gracia 14:42 muller: {blake} yes 14:42 aperiodic: vas: glad it helped! quoting is tricky and generally unnecessary outside of writing macros, which is very rarely called for 14:43 {blake}: muller: Well, having to know about the structure places a lot of limitations on how general you can make your code. If it's important to you, you could make code that did so, at least for your specific cases. 14:43 muller: so say I wanted to implement a map equivalent that kept the original data structure. how would I go about it? would I have to hardcode the types in the function, or can i somehow have each function per type 14:43 s/each/one 14:43 {blake}: muller: 14:43 ianhedoesit: muller: I think you should really think about why you think you need to do that. 14:44 {blake}: muller: I'm a relative noob myself, and I used to worry about the same thing. Having actually coded in Clojure for a while, it hasn't really been an issue. 14:45 If I need a specific type, I'll use an "into {}" or "into []" or whatever on the return value of whatever's changing my type. 14:45 muller: ianhedoesit because I picked certain data structure (be it a vector, list or something else) because of the properties it has. and I want to keep it that type 14:45 ianhedoesit: I understand the difference between a list and a vector in terms of performance, but Clojure will typically decide what's best for you anyway, as far as I understand it. 14:46 {blake}: When you get down to it, it's a sort of premature optimization. 14:46 muller: ianhedoesit but it doesn't do that, it always returns sequence. even when it is not the best type 14:46 ianhedoesit: how do you know 14:47 I mean how do you know that is not ideal? 14:47 muller: i was told that in here a couple of minutes ago 14:47 blake I don' think it is premature optimizatio to pick (and stick to) appropriate data structure 14:47 {blake}: muller: I think map returns sequence precisely because it's the best option. 14:48 muller: why is it the best option? 14:48 ianhedoesit: for one it's a lazy seq, so that's obviously better than realizing any data structure every time. 14:49 {blake}: muller: That is a big question. But you're going in to this with assumptions you've carried over, presumably from other languages. 14:49 And again, I did the same thing. I finally just gave up those notions and found the issue more-or-less vanished. 14:50 muller: if i am processing the list once what advanage do i get from laziness? 14:51 ian I am not. I just want to write clear code. (into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) could be clearer 14:52 so my question still remains, what would be clojure's way of writing a map like that, that doesn't return sequence but whatever datastructure caller passed 14:52 raspasov: muller: what are you trying to do? 14:52 make this nicer? (into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) 14:53 muller: raspasov I want a map equivalent that doesn't return a sequence but whatever type it was passed 14:53 how would I write it? 14:53 tbaldridge: transducers can do that 14:53 muller: ok googling 14:54 tbaldridge: (one sec while I construct an example) 14:54 {blake}: tbaldridge: Ooh, cool. 14:55 bucketh3ad: to relevant parties, why not: (vec (map (comp vec reverse) [[1 2 3] [4 5 6]])) ? 14:55 raspasov: muller: when you say whatever type - is that limited to maps, vectors, sets, LazySeqs, etc usual suspects in Clojure? 14:56 ianhedoesit: ,(mapv (comp vec reverse) [[1 2 3] [4 5 6]]) 14:56 clojurebot: [[3 2 1] [6 5 4]] 14:56 bucketh3ad: Mmm. even purdier. 14:56 ianhedoesit: :) 14:56 muller: raspasov that would be enough. but im curious if we could make it extensible too, so that you could extend it for other data structures 14:57 tbaldridge: yeah, what ianhedoesit said, that's pretty clean 14:57 raspasov: do look into transducers like tbaldridge says, it can make the transformation in one step I believe, without generating intermediary lazy seqs 14:57 justin_smith: bucketh3ad: one better: (mapv (comp vec rseq) [[1 2 3] [4 5 6]]) 14:57 rseq is faster if you know the arg is a vec 14:58 tbaldridge: you can also make into generic via empty: ,(let [coll [1 2 3]] (into (empty coll) (map inc coll))) 14:58 {blake}: muller: Sure. Though obviously your new routines have to have someway to construct the final output of previously unknown types. 14:58 muller: that is much cleaner yeah 14:58 ianhedoesit: I recommended rseq earlier and I already forgot. 14:58 justin_smith: haha 14:59 muller: {blake} why? they have a function that transforms the elements. and you write a new function per type that represents a data structure 14:59 {blake}: ianhedoesit: I didn't! I'd never heard of rseq before you mentioned it. So, thanks! 15:00 muller: Right, that's what I mean: You need a new function per type. Look, you either transform it yourself after, or you have your routine make that transformation for you, right? 15:00 muller: yeah 15:01 {blake}: muller: If you want to preserve structures all-the-way-down, you'd pretty much have to rewrite Clojure's basic elements to do so. 15:01 At least I think so. Y'all can correct me if I'm wrong. 15:02 muller: I don't know what you mean by Clojure's basic elements 15:02 tbaldridge: that's pretty much what transducers allow you to do, write algorithms without worrying about input or output types 15:02 justin_smith: (inc tbaldridge) 15:02 * justin_smith kicks lazybot. 15:02 raspasov: here is the transducer version (defn transform-into-self [xf coll] (into (empty coll) xf coll)) 15:02 and use it (transform-into-self (map inc) [1 2 3]) 15:02 tbaldridge: ,(into [] (map inc) [1 2 3]) ;; no seqs were created by this code 15:02 clojurebot: [2 3 4] 15:03 muller: I would like to write this myself for practice and learning. can I write a map that dispatches on the type of the second argument (type that we are mapping over) 15:03 vas: thanks everyone for being kind and awesome. have a good breakfast/lunch/dinner when you do! (= 15:04 justin_smith: muller: you could. It will be easier if you use transducers. I think people use the name fmap for this function sometimes? 15:04 raspasov: muller: just a note, most likely you need 1.7 alphas to have transducers 15:04 out of the box 15:04 muller: do I have to hardcore the types in one function definition, or can I separate definitions, one per type 15:04 hardcode :) 15:04 justin_smith: oh yeah, 1.7 is not out of alpha yet, and you need 1.7 for transducing 15:04 {blake}: tbaldridge: Wait, what? How is that possible? 15:05 tbaldridge: Doesn't (map inc) make a sequence? What sorcery is this?! 15:05 justin_smith: muller: third option is create the right type using one function, regardless of the type of the input 15:05 arrdem: {blake}: transducer magic 15:05 justin_smith: muller: without hardcoding types 15:06 {blake}: arrdem: My God, it's like a thermos! It keeps the hot hot, and the cool cool! But how does it know?! 15:06 justin_smith: the asterix on "regardless of the type of the input" being the type would need to work with the protocols underlying empty / into 15:06 tbaldridge: {blake}: no, (map inc) creates a transducer, so it looks something like this (once it all executes), (.reduce [1 2 3] (comp conj (map inc)) []) 15:07 {blake}: tbaldridge: Ahhhhh. That's kind of awesome. So this is in 1.7, though, right? Us <=1.6 types are still making seqs and whatnot. 15:08 tbaldridge: yes sadly, but 1.7 is pretty stable ;-) 15:09 {blake}: tbaldridge: Well, thank you for that example. I'd sort of grasped that transducers worked that way, but that's a simple and clear demonstration of their power. 15:10 muller: so I would use defmulti and defmethod for this? to write a function that dispatches on the type of some argument 15:10 raspasov: {blake}: the even cooler part is that you can "attach" transducer transforms to channels :) 15:10 tbaldridge: muller: since you're only using a single dispatch, protocols are probably what you want 15:11 {blake}: raspasov: I...can't even. 15:11 muller: tbaldridge ok cool 15:11 tbaldridge: {blake}: right, tansducers decomplect (*ducks*) the three things in a normal lazy seq transform: a) iterating the source, b) the transformation, c) the output type. Each one of those can be tweeked with transducers 15:12 raspasov: if you (def x (chan 1 (map inc))) 15:12 , (>!! x 1) 15:12 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: >!! in this context, compiling:(NO_SOURCE_PATH:0:0)> 15:12 raspasov: you get (<!! x) 15:12 {blake}: tbaldridge: And we get that for free? Backwardly compatible, no performance hit... 15:13 raspasov: Dude. 15:13 raspasov: but then you have to make sure everything that gets through the channel is a number, otherwise there will be exception (you can supple an optional exception handler) 15:13 supply* 15:13 tbaldridge: the performance is actually better (due to less memory allocation), but at the cost of having to rewrite your code a bit. Notice how we're doing (map inc) not (map inc coll) 15:14 TimMc: It only costs one arity. :-P 15:14 michaelr: hi 15:14 noonian: but the old version of map is still there so you can do it incrementally 15:14 old arity I should say 15:14 {blake}: raspasov: I would imagine. But still cool. 15:15 ianhedoesit: raspasov: why do you need to map inc and not just inc? 15:15 tbaldridge: TimMc: the first arity is free :-P 15:15 justin_smith: haha 15:15 ianhedoesit: (I don't know anything about channels or anything) 15:16 muller: noonian how do you pick between old and new version of map? 15:16 raspasov: ianhedoesit: everyone asks that :) it's like you're "mapping" over what passes through the channel, and because inc (I guess) does not have transducer arity? tbaldridge is that right? 15:16 michaelr: my application will be in clojurescript with the server side API handled by compojure delegating to liberator, now i've used secretary for routing in clojurescript before. i wonder whether there is any upside to using bidi instead and whether there is any real use case to push it between compojure and liberator as well? 15:16 justin_smith: ianhedoesit: inc works on numbers, he wants inc to be applied to every number that comes from some source of data 15:16 noonian: muller: if you're using 1.7 you will have the new version, otherwise you have the old version 15:16 ,(map inc) 15:16 clojurebot: #<core$map$fn__4507 clojure.core$map$fn__4507@7b908768> 15:16 muller: hmm 15:16 noonian: guess clojurebot is using 1.7 lol 15:17 tbaldridge: ianhedoesit: right, what channels need are transducer functions which deal with streams of values. So you can also do stuff like this with channels 15:17 muller: if i got it right (map inc) calls a different function than (map inc x)? 15:17 tbaldridge: (def a (chan (comp (partition-all 2) (map inc)))) 15:17 ianhedoesit: that's what I figured, I just thought maybe channels could just take any function 15:17 tbaldridge: That'll increment numbers, and then partition them, 15:17 ianhedoesit: I don't know how data is passed around with channels or anything about them 15:17 {blake}: muller: Sorta. Multiple arities are described in the same function declaration. 15:17 raspasov: muller: yes, different arity of the same fn 15:17 ianhedoesit: ,(map inc 1) 15:17 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> 15:17 muller: ok it executes different code 15:18 cool 15:18 noonian: muller: (map inc) returns a 'transducer' which you can then apply to a collection using the new transduce or sequence functions (sequence isn't actually new). (map inc [1 2 3]) actually applies the function and returns a new collection immediatly 15:18 ianhedoesit: ,((map inc) 1) 15:18 clojurebot: #<core$map$fn__4507$fn__4508 clojure.core$map$fn__4507$fn__4508@7ebb051c> 15:18 ianhedoesit: oh okay 15:18 justin_smith: ianhedoesit: by taking a transducer to apply to the channel, instead of a function to map across the channel, there is the added flexibility that the transducer could be a reduction (ie. summing all numbers to come in on the channel) 15:19 ianhedoesit: ,(((map inc) 1) 1) 15:19 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> 15:19 tbaldridge: ,(((map inc) conj) [] 1) 15:19 clojurebot: [2] 15:19 ianhedoesit: justin_smith: okay, neat. 15:19 tbaldridge: ianhedoesit: thats what you want ^^ 15:19 muller: noonian (map inc [1 2 3]) returns a sequence, like now, yes? 15:19 ianhedoesit: tbaldridge: lol thanks, yeah 15:19 muller: like before rather 15:19 noonian: muller: yes, the semantics for the other arities of map are the same as always 15:20 ,(map inc [1 2 3]) 15:20 clojurebot: (2 3 4) 15:20 noonian: ,(sequence (map inc) [1 2 3]) 15:20 clojurebot: (2 3 4) 15:20 noonian: (sequence (comp (map inc) (map (partial * 10)) [1 2 3]) 15:20 ,(sequence (comp (map inc) (map (partial * 10)) [1 2 3]) 15:20 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading> 15:20 noonian: ,(sequence (comp (map inc) (map (partial * 10))) [1 2 3]) 15:20 clojurebot: (20 30 40) 15:21 ianhedoesit: "magic" 15:21 muller: just wondering if I understand sequences. if we assign the result of (map inc collection) to a variable nothing is computer? until we start pulling values the from resulting seqeuence 15:22 computed 15:22 ianhedoesit: nothing is computer 15:22 justin_smith: muller: yes, map is lazy 15:22 {blake}: impossible is nothing 15:22 justin_smith: muller: not all sequences are lazy, but lazy-seq (which map creates) is 15:23 ianhedoesit: is there any timeline or ETA for a "stable" Clojure 1.7? 15:23 muller: can I skip some values in a lazy-seq 15:23 (and skip computing those values) 15:23 justin_smith: muller: no, they must be realized in order 15:24 muller: ,(def x (map print [1 2 3])) 15:24 clojurebot: #'sandbox/x 15:24 muller: ,x 15:24 clojurebot: (123nil nil nil) 15:24 justin_smith: ,x 15:24 clojurebot: (nil nil nil) 15:25 TimMc: justin_smith: Map is *sort of* lazy. 15:26 muller: why sort of 15:26 l3dx: after connecting cider to a repl (or using jack-in) the repl buffer doesn't show up. any suggestions? 15:26 TimMc: ,(def ch (map println (range))) 15:26 clojurebot: #'sandbox/ch 15:26 TimMc: ,(def ch (first (map println (range)))) 15:26 clojurebot: 0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n#'sandbox/ch 15:26 muller: why does it compute all values? 15:27 TimMc: Chunked sequences. 15:27 "Lazy" means "it probably won't do any computation, and it definitely won't do all of it, but it might do something in the middle." 15:28 (range) emits a sequence that is realized in chunks of 32 at a time; map respects that and computes each of those chunks as a unit. 15:28 muller: oh 15:28 TimMc: If you're doing side-effecty stuff in there, you might get surprised. 15:28 muller: does (range) retur n lazy-seq or something else 15:29 TimMc: &(class (range)) 15:29 ,(class (range)) 15:29 clojurebot: clojure.lang.LazySeq 15:30 {blake}: ,(type (range)) 15:30 clojurebot: clojure.lang.LazySeq 15:30 {blake}: huh 15:30 TimMc: ,(class (seq (range))) 15:30 clojurebot: clojure.lang.ChunkedCons 15:32 justin_smith: TimMc: but the specific answer for "will map do anything if I don't use the result" is the same - or is there some datatype that messes with that too? 15:32 muller: intermediate sequence won't be created in here right? (map f (map g (range)))) 15:33 justin_smith: muller: it will, and that is part of why we have transducers now 15:33 muller: because (comp (map g) (map f)) doesn't create the extra seq that your version does 15:35 TimMc: justin_smith: Mmmm... I could make one, I think. 15:36 amalloy: muller: it will be created, but not realized all at once 15:36 justin_smith: TimMc: I'd be interested to see that (and even more interested to see a sane reason that one would be needed :)) 15:37 TimMc: justin_smith: I don't think I can make something that will involve calling f in (map f c), but if realizing c involves side-effects, then I can make those happen. 15:38 Mmm, no, not even that I think. 15:44 csd_: Have any of you experienced a bug in Cider where it seems to temporarily loose the ability to create an nrepl session? 15:44 amalloy: TimMc: yeah, i think that's impossible. map just returns (lazy-seq ...) before it does any work, so nothing will happen until you seq the result 15:44 csd_: lose* 15:47 it would appear that the solution is to do cider-jack-in a second time, while the buffer for the first attempt is still open 15:47 amalloy: ,(read-string "#;") 15:47 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading> 15:48 justin_smith: csd_: weird 15:48 amalloy: i was surprised this returned EOF rather than "no dispatch macro for ;" 15:49 Bronsa: amalloy: tagged literals can have spaces between # and the tag 15:49 ,(read-string "#;\nfoo[]") 15:49 clojurebot: #<RuntimeException java.lang.RuntimeException: No reader function for tag foo> 15:50 justin_smith: ,(read-string "#;\n_invalid []") 15:50 clojurebot: #<RuntimeException java.lang.RuntimeException: No reader function for tag _invalid> 15:50 justin_smith: err 15:50 ,(read-string "#;\n_ invalid []") 15:50 clojurebot: #<RuntimeException java.lang.RuntimeException: No reader function for tag _> 15:50 justin_smith: oh, #_ is different I guess 15:50 amalloy: Bronsa: it's just, i would have expected the ; to be an invalid part of a dispatch macro, not a comment in the middle of one 15:50 justin_smith: it just looks like a tagged reader 15:51 Bronsa: amalloy: it's not going to intepret it as a dispatch macro anymore. it's in tagged-reader mode :P 15:51 amalloy: there's no invalid dispatch character error anymore 15:52 amalloy: Bronsa: the error message is still there, in a not-unreachable code path 15:52 Bronsa: right 15:52 no wait, not-unreachable? 15:53 amalloy: well, it's not unreachable as far as the compiler is concerned - there are if/else branches that lead there. i can't tell for sure whether they are "actually" unreachable 15:54 Bronsa: amalloy: I'm pretty sure there's no way to get that exception anymore 15:55 amalloy: hmmm 15:55 challenge accepted 15:55 gfredericks: leiningen user-profile protip: seldom-used plugins can be "hidden" from the leiningen startup & classpath by shoving them in a dedicated profile and adding an alias for that plugin's command that expands to with-profile 15:57 amalloy: Bronsa: https://www.refheap.com/41aa882e49e562b2d00f0ed84 15:58 now that you know it's possible, care to guess how, or shall i spoil it? 15:58 zacts: hi which doc explains examples of how to create subdirectories to my project structure within a clojure app? 15:58 app -> subdirectory within my lein repo 15:58 Bronsa: amalloy: does it involve using a custom tagged reader? 15:58 amalloy: yes 15:58 Bronsa: that's cheating :P 15:59 amalloy: hey, you said it was unreachable 15:59 Bronsa: fair enough 15:59 zacts: hum.. Java.io.File. ? 15:59 amalloy: anyway, the custom reader is just (constantly nil) 15:59 zacts: is this the proper way to do this? 15:59 amalloy: if you invoke that reader you get the old no-dispatch-macro error 15:59 Bronsa: amalloy: ah yeah, there is actually a ticket in jira for that 16:00 crash_ep: Do any of Clojure's iterating procedures result in a stack overflow if actually allowed to iterate over an infinite sequence? E.g., doseq? 16:00 tbaldridge: crash_ep: no 16:01 crash_ep: tbaldridge thanks 16:02 {blake}: zacts: What are you trying to accomplish? 16:02 amalloy: tbaldridge: you can produce sequences that will cause stackoverflows when you iterate over them, which may be what crash_ep is worried about 16:03 tbaldridge: hey, I didn't say it was unreachable ;-) 16:04 crash_ep: amalloy what are you talking about? 16:05 zacts: {blake}: just save config files, but I figured it out 16:05 {blake}: zacts: Congrats. =) 16:05 amalloy: i mean, if you produce a sequence like uh...(nth (iterate #(map inc %) (range 5)) 10000) 16:05 zacts: thanx {blake} 16:06 amalloy: that's a perfectly fine result in theory (and if you change 10000 to 100 it works fine), but in practice trying to consume it causes a stack overflow 16:06 but this is related to the sequences you produce, not how you iterate over them 16:10 crash_ep: amalloy: why is that? Doesn't iterate create a lazy sequence? 16:13 is the same sort of problem as what i'm describing here 16:13 fortruce: is there a way to force a rational to be represented as a decimal in the repl? 16:14 justin_smith: fortruce: (double (/ 2 3)) 16:14 ,(double (/ 2 3)) 16:14 fortruce: justin_smith: thanks 16:14 clojurebot: 0.6666666666666667 16:15 ianhedoesit: ,(float (/ 2 3)) 16:15 clojurebot: 0.6666667 16:15 justin_smith: fortruce: that's actually doing a type conversion, but it's probably the simplest thing 16:16 fortruce: justin_smith: yea, i just need it for a quick calculator 16:16 ianhedoesit: ,(/ 2.0 3) 16:16 clojurebot: 0.6666666666666666 16:16 crash_ep: amalloy thanks for the link 16:16 fortruce: ianhedoesit: thats cool :) 16:16 justin_smith: yeah, you could always potentially pollute the calculation too 16:17 ianhedoesit: ,(/ 2. 3) 16:17 clojurebot: 0.6666666666666666 16:17 TimMc: ,(nth (iterate #(map inc %) (range 5)) 10000) 16:17 clojurebot: #<StackOverflowError java.lang.StackOverflowError> 16:17 TimMc: Take that, bot! 16:19 justin_smith: TimMc: for some reason I thought lazy-seqs would handle that better 16:19 crash_ep: TimMc you animal 16:22 tbaldridge: hyPiRion: read your blog post earlier today, +1 16:23 hyPiRion: tbaldridge: the performance one or the swearjure one? :p 16:23 tbaldridge: hyPiRion: both, but I was thinking about swearjure 16:23 hyPiRion: haha, thanks 16:24 tbaldridge: hyPiRion: the performance one was good as well, it mentioned many concerns I've had about vectors, but never took the time to investigate 16:32 hyPiRion: Yeah – fortunately I don't think very many people hit perf issues related to the vector impl 16:33 Except for ztellman, who seems to have perf issues with about everything :p 16:34 gfredericks: the one constant factor in all of ztellman's perf issues is ztellman 16:40 {blake}: ,(map (fn[i](inc i)) [1 2 3]) 16:40 clojurebot: (2 3 4) 16:41 {blake}: (let [afn (fn[i] inc i) (map afn [1 2 3])) 16:41 ,(let [afn (fn[i] inc i) (map afn [1 2 3])) 16:41 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )> 16:42 {blake}: ,(let [afn (fn[i] inc i)] (map afn [1 2 3])) 16:42 clojurebot: (1 2 3) 16:42 {blake}: ,(let [afn (fn[i] (inc i))] (map afn [1 2 3])) 16:42 clojurebot: (2 3 4) 16:42 TimMc: gfredericks: O(ztellman) 16:44 amalloy: what in the world is http://octopushub.org/clojure/2015/01/26/hellofunk-did-you-notice-stackoverflowcom-questions-28131135-howtoimplementzipwithfoldlinaneagerlanguage.html about, does anyone know? it seems to be a bizarre collection of things said to me about clojure 16:45 gfredericks: amalloy: this is the future of content 16:45 jump on the bandwagon or you'll be left by the train with no elephants in your pockets 16:46 amalloy: gfredericks: you're making the problem worse now. i can just see tomorrow's headline: "amalloy: this is the future of content" 16:46 gfredericks: you mean making the problem better 16:46 hyPiRion: haha 16:53 TimMc: Hmm, I can't see any obvious way to perform an injection attack on that site. 16:54 It probably won't even pick on you again any time soon, so you'd have to predict the next search... 16:56 Hah, the last "related question" is from me. 16:56 aaelony: I know I'm behind the times and this is a silly question, but I'm following a simple Transducers example using filter (http://ianrumford.github.io/blog/2014/08/08/Some-trivial-examples-of-using-Clojure-Transducers/), and the repl is telling me that I have the "Wrong number of args (1) passed to: core/filter". I imagine I need to require a particular version of Clojure and possible use/require something but haven't googled for it correctly yet 16:56 . What might I need to get this to work? 16:57 tbaldridge: aaelony: switch to the latest clojure alpha 16:57 amalloy: TimMc: i think they record everything anyone says, and synthesize pages based on all the subjects somewhere 16:57 tbaldridge: , *clojure-version* 16:57 TimMc: The pages aren't dynamic, I think... 16:57 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"} 16:58 amalloy: well actually, that's interesting. "site:octopushub.org justin_smith" returns a bunch of results, but "site:octopushub.org timmc" gets none at all 16:59 aaelony: tbaldridge: Thanks, Tim. My google-fu is terrible though and I'm not finding the right artifact etc for the project.clj 17:00 any 1.7 alpha should work, but alpha5 is the latest 17:00 aaelony: tbaldridge: perfect. thank you. 17:00 TimMc: *shrug* 17:00 aaelony: :) 17:02 TimMc: amalloy: You could try emailing david.mazvovsky@gmail.com to ask what up. 17:03 justin_smith: amalloy: wat? Is this some new version of blogspam? 17:04 amalloy: i don't know, man. it's weird 17:04 TimMc: whence that address? 17:04 justin_smith: someone scraping bytes off the wire? 17:04 TimMc: amalloy: whois 17:05 justin_smith: The content scraper is... IN the room! 17:05 justin_smith: haha 17:05 maybe it's the side job of that spanish speaking bot 17:05 amalloy: justin_smith: i'm inclined to think they're scraping one of the log sites or something 17:05 tbaldridge: perhaps it's someone's job 17:05 justin_smith: ahh, yeah, that makes more sense 17:05 amalloy: because someone with an irc bot would be less confused about who wrote what 17:06 TimMc: They have IRC logs from several channels. 17:06 amalloy: like, all the messages "mentioned by justin_smith" are actually messages *to* justin_smith, like "justin_smith: thanks" 17:07 TimMc: I wonder if I could file a DMCA request against them. 17:07 ...no, they're in Israel, aren't they. 17:07 justin_smith: TimMc™ 17:07 haha 17:08 amalloy: TimMc: well, you could ask google to hide their links. that's how the DMCA works against non-US stuff, right? 17:08 justin_smith: I mean your nick already has the ™ 17:08 TimMc: yup 17:09 Mmm... their website is hosted in EC2, in the US. 17:09 I wonder how that works. 17:10 tbaldridge: TimMc: well we are talking about DCMA, isn't the domain of that basically "we'll sue anyone who doesn't abide by our laws, YAH! 'murica!" 17:10 weavejester: Has anyone come across an "unsupported binding form" error in the latest Clojurescript versions? 17:11 Or has anyone actually successfully used the latest Clojurescript without it excepting? 17:11 I assume it must work for someone :) 17:11 michaelr: weavejester: are you on 55 or 60? 17:11 weavejester: michaelr: 60 17:12 michaelr: 60 works for me 17:12 weavejester: Hm... 17:12 It would be nice if I had some way of figuring out where this error is coming from 17:13 michaelr: maybe one of the middleware 17:13 try maybe lein-ancient to upgrade deps 17:13 weavejester: michaelr: Are you using cljsbuild 1.0.4? 17:14 michaelr: This is a pretty simple project. It just relies on Clojure, Clojurescript and tools.macro. 17:15 Oh wait, I think I've figured it out. 17:16 The project was still pulling in Clojure 1.5.1 17:16 Hm... okay, it's still failing. 17:16 michaelr: 1.0.4 17:17 lein clean (?!) 17:18 weavejester: Yeah, I think it picked up something weird 17:20 Ahah, that's done it. Looks like the problem is that 2760 only works with Clojure 1.6.0 or greater 17:20 michaelr: Thanks for your help 17:32 {blake}: I'm mapping over a routine that returns a map, so I get a sequence of maps as a result. Because I want just a single map, I'm then doing an apply merge. 17:32 (apply merge (map function stuff)) 17:32 I feel like I'm doing too much here. 17:32 justin_smith: {blake}: wait, how do you get a sequence of maps out of a map? 17:32 your function turns a k/v pair into a map? 17:33 amalloy: justin_smith: {blake} means "i'm mapping (a function that returns a map) over some sequence" 17:33 {blake}: Well, my function takes parameters for an SQL query and returns a map of the values. 17:33 amalloy, justin_smith: Yes, sorry if that wasn't clear. 17:33 justin_smith: aha 17:34 amalloy: {blake}: (apply merge (map ...)) seems fine 17:34 justin_smith: {blake}: you may want to use reduce / into, but merge over map seems decent enough 17:34 {blake}: amalloy: OK. I was thinking I could reduce it into a {}, too, but not sure it's better. 17:35 justin_smith: Hah. OK. Thanks, guys. 17:35 justin_smith: {blake}: no need for {} even (reduce (fn [acc m] (into acc (f m))) mps) 17:35 or wait, that would skip the f on the first of mps, so use {} as your explicit initial val 17:36 but it comes out pretty much the same 17:36 {blake}: Let me try reduce, while I have the time. 17:37 amalloy: i don't really love that reduce. it's just manually inlining the map call, doing transducers by hand 17:37 tbaldridge: {blake}: in short, upgrade to 1.7 17:38 amalloy: (into acc (map f) mps) is the same thing i think, with transducers? 17:38 tbaldridge: yep, pretty much 17:38 {blake}: justin_smith: It doesn't help readability, to my eyes. But I tried. =P 17:45 TimMc: clojurebot: {blake} |means| "i'm mapping (a function that returns a map) over some sequence" 17:45 clojurebot: In Ordnung 17:46 {blake}: Was ist das? 17:50 TimMc: Just teaching clojurebot some crap. 17:52 ianhedoesit: clojurebot: what does {blake} mean 17:52 clojurebot: Excuse me? 17:52 ianhedoesit: ;-; 17:52 {blake}: heh 17:52 This could be useful. 17:57 TimMc: clojurebot: {blake}? 17:57 clojurebot: {blake} means "i'm mapping (a function that returns a map) over some sequence" 17:58 {blake}: clojurebot words? 17:58 clojurebot: words? 17:58 clojurebot: These words are razors to my wounded heart 17:59 ianhedoesit: clojurebot: TimMc? 17:59 clojurebot: TimMc is a jerk 17:59 {blake}: heh 17:59 ianhedoesit: whoa there 18:00 {blake}: When I use a word, it means just what I choose it to meanneither more nor less. 18:00 TimMc: ~TimMc 18:00 clojurebot: TimMc is a jerk 18:00 TimMc: heh, maybe that's all it knows about me 18:01 ianhedoesit: ~ianhedoesit 18:01 clojurebot: Excuse me? 18:01 ianhedoesit: clojurebot: ianhedoesit |means| "what a great guy - from clojurebot with love." 18:01 clojurebot: Ik begrijp 18:02 ianhedoesit: ~ianhedoesit 18:02 clojurebot: ianhedoesit means "what a great guy - from clojurebot with love." 18:03 ianhedoesit: TimMc: clojurebot is just a clojure wrapper for PircBot by jibble.org right? 18:11 TimMc: Dunno, check source. 18:12 ianhedoesit: I used "means" because of a comment amalloy made that made it sound like he was defining "{blake}", but you can use anything. 18:12 atratus: can anyone explain how make-array results in nesting? https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L3680 18:13 does that line mean its relying on Java to do the work and not clojure? 18:14 TimMc: yeah 18:14 ...I don't understand why it's so hard to find the javadocs online 18:16 Well, I guess the answer is "Oracle doesn't understand internets". 18:16 atratus: It's a call to java.lang.reflect.Array/newInstance 18:18 atratus: TimMc: ok thankyou, yeah that stuff is awful 18:18 sardinha_biba: meaning of falsey and truthy please? I am new to programming and not a native english speaker, so I'm having some difficulty understand it and online translations didn't help. 18:19 TimMc: sardinha_biba: true and false are actual booleans; many languages use broader notions of true-like values and false-like values. 18:20 So in Clojure, nil and false are treated as false-like (falsey) and everything else are true-like (truthy) 18:21 Forms like (if x ...) coerce x into an actual boolean value (true or false). 18:22 sardinha_biba: TimMc: Thank you. makes more sense now. Thought that falsey was somewhat different than false 18:45 {blake}: If I have a multi-user app that connects to mongoDB, can anyone think of a reason why I shouldn't just use the same connection for all calls into it? As opposed to trying for a connection per user/session/whatever? 18:55 amalloy: {blake}: don't make a connection per user 18:55 unless you're letting users build their own queries or something and you need them to have different permission levels i guess 18:56 {blake}: amalloy: Nah, nothing that sophisticated. It's really just a substitute file system, if we're being honest. 18:57 I think I just need a way to check if the connection is still good. 19:27 ianhedoesit: what are you using for establishing the connections? 19:27 tcrayford____: {blake}: I'd establish the connection at once, then pass it through everything. Typically your client should handle connection errors/reconnection/etc 19:28 (though I have *no* idea how good mongo's jvm drivers are, I try really hard to never use or think about mongo) 19:28 {blake}: one common pattern (if you're using ring) is to assoc it onto the request in a middleware 19:29 {blake}: tcrayford____: So you'd have it so that every session had its own connection? 19:29 tcrayford____: {blake}: no, one connection, but shared 19:29 just it *looks* like every session has it's own connection 19:30 means that testing gets easier - you don't have a global connection anywhere, it just comes in with the request 19:30 {blake}: tcrayford____: OK, so what's the benefit of passing around...oh, I see. =P 19:30 tcrayford____: :) 19:31 also like, means that you don't have jvm bootup dependent on connections happening, which *can* mess you up in production etc 19:31 Glenjamin: tcrayford____: ah good, it's not just me doing that (assoc resources into req) 19:31 tcrayford____: Glenjamin: pretty sure that's a standard pattern at this point 19:31 Glenjamin: why do you always have so many underscores? 19:31 tcrayford____: trying to win an award 19:31 Glenjamin: i've seen a few examples that have their routes close over "components" 19:32 {blake}: Well, my guy wrote some code that just blithely opens a connection for every request. Which is cool. Until you have a few zillion connections. 19:32 killfill: newbie question: (def a (atom {:hi "there" :list [1 2 3 4]})) <-- how could i delete one element of that :list? 19:32 justin_smith: killfill: does that vector have to remain a vector? 19:33 killfill: justin_smith: i think so. yes. 19:33 tcrayford____: {blake}: I once had code in production that uh, spawned a thread for every incoming request, and left it there (because of a bug) 19:33 stuff goes south north of like 200k threads on linux apparently 19:33 {blake}: tcrayford____: That takes a man's OS to handle...a manly man's OS. 19:33 tcrayford____: (on that hardware anyway) 19:34 {blake}: tcrayford____, Glenjamin: I'm curious about the passing around resources, though: What I get back from connect-db looks like "#<DBApiLayer mydbname>". 19:34 tcrayford____: {blake}: also note that pattern (new connection per request) will *really* mess you up in postgres and some other databases - they spawn a new process per client connection 19:35 justin_smith: ,(swap! (atom {:hi "there" :list [1 2 3 4]}) update-in [:list] ((fn [n] (fn [v] (vec (concat (take n v) (drop (inc n) v))))) 2)) ; killfill 19:35 clojurebot: {:list [1 2 4], :hi "there"} 19:35 justin_smith: killfill: it's a little awkward with the drop-nth as an anonymous function, but that's easy to fix in a real namespace 19:35 {blake}: tcrayford____: Well, I think it's caused us some issues on Mongo, as well. =P 19:35 killfill: wops 19:35 justin_smith: killfill: also, labeling a vector as :list is kind of weird 19:36 killfill: i could probably have figure that out in 1 year.. :P 19:36 tcrayford____: {blake}: /me resists making disparaging remarks about mongo 19:36 justin_smith: killfill: it's more straightforward if it isn't a one-liner 19:37 killfill: justin_smith: if having a list instead of a vector, would it make it simplier? or we would just take thouse 'vec' out 19:37 justin_smith: killfill: general idea is that swap! mutates the state of an atom, and returns the new state, update-in takes a sequence of keys and runs a function on the value found at the end 19:37 killfill: having a list would just take out the vec call 19:38 {blake}: tcrayford____: Swing away. I've got no emotional attachments. 19:38 killfill: justin_smith: thanks! 19:38 {blake}: But I'm still not seeing how I'd pass that connection through an HTTP request. 19:38 justin_smith: killfill: simpler example of update-in: 19:38 ,(swap! (atom {:a {:b 0}}) update-in [:a :b] inc) 19:38 clojurebot: {:a {:b 1}} 19:39 dbronico: I'm using Clojure for a simple script, and when I run it from the REPL, all is well. When I run it with lein-exec, it prints my debug messages but terminates before the call to 'map' is done. Can anyone help me sort this out? 19:39 justin_smith: killfill: what I do in the first example is only different in a couple of small details 19:39 {blake}: dbronico: Paste it to refheap! 19:39 justin_smith: dbronico: map is lazy 19:39 dbronico: map does nothing, unless you consume the value 19:39 dbronico: in the repl, the printing step consumes the value 19:40 dbronico: Aha, so a doall should fix it up, I'm thinking? 19:40 justin_smith: dbronico: use dorun, unless you need to use the return value somewhere 19:40 {blake}: dbronico: Well, it'll reveal the error in the REPL, anyway. 19:40 justin_smith: {blake}: ? 19:41 which is saying the same thing as justin_smith but with more words 19:41 justin_smith: {blake}: the repl hides the error because printing forces the lazy seq to be realized 19:41 bonsai_hk: dbronico: if you're "doing things" using map, i.e. a glorified for-loop, then rather use doseq instead 19:41 {blake}: justin_smith: Right...so if he does a -- okay, right, got it backwards. 19:41 justin_smith: heh 19:41 dbronico: justin_smith: OK, that seemed to be the ticket. 19:42 justin_smith: dbronico: very common mistake, I made it more times than I care to admit 19:42 ~map 19:42 clojurebot: map is *LAZY* 19:42 justin_smith: haha 19:42 dbronico: {blake}, amalloy: Thanks for the attempt. You guys are like sharks in here! =] 19:42 bonsai_hk: I will definitely check that out. 19:43 justin_smith: dbronico: it's a cutthroat battle for imaginary internet points 19:43$karma amalloy

19:43 :P but lazybot is slacking

19:43 amalloy: is lazybot dead again? i restarted him last night i think

19:43 {blake}: It's #Clojure, where the games are made up and the points don't matter.

19:43 tcrayford____: {blake}: sent you a pm, unsure if you saw it

19:44 justin_smith: amalloy: is lazybot dying or just in a weird disconnect / netsplit state or something?

19:44 amalloy: disconnected

19:44 but doesn't recover

19:44 &1

19:45 lazybot: ⇒ 1

19:45 justin_smith: amalloy: so theoretically the fix would be detecting disconnection (which eg. my client seems to do fine) and handling that event

19:45 amalloy: i think it tries to do that but is broken somehow

19:45 justin_smith: by my client I mean my regular irc client, not some irc lib I am sitting on

19:45 amalloy: right

19:46 justin_smith: amalloy: I am not at all surprised that the API update broke that hook / trigger (if that's even how it works)

19:46 amalloy: justin_smith: it was broken before you touched it, in exactly the same way afaict

19:46 * justin_smith puts the rosary beads back and gets off his knees.

19:50 amalloy: the gradual reputation gain i get from old SO answers is a fun reminder of the weird questions people ask sometimes: http://stackoverflow.com/q/8531793/625403 is someone asking how to create a future that doesn't actually start right away

19:52 justin_smith: a slight distinction, completing in the future vs. starting in the future

19:53 see also, people expecting agents to abstract fixed actions over parameters that come in from the client, rather than a stored state modified by an action provided by the client

19:55 amalloy: justin_smith: of course, in one sense it actually is a fixed action: the function #(apply % current-state %&)

19:56 not that this is a terribly useful sense

19:56 justin_smith: well, the naive expectation is that they would somehow be able to define that action of course

19:57 amalloy: right. i want a log-to-file agent, and i want to send it lines to log

19:57 justin_smith: maybe we can make a ticket on JIRA requesting that agent and go switch names from now on

19:57 then people would be less confused

19:58 (not really)

19:58 amalloy: justin_smith: that'll be the first change made after https://github.com/clojure/clojure/pull/6

19:59 justin_smith: haha

20:05 so, in this CMU text, I see the following "Reactive agents simply retrieve pre-set behaviors similar to reflexes without maintaining any internal state." http://www.cs.cmu.edu/afs/cs/usr/pstone/public/papers/97MAS-survey/node14.html ; while in the docs for agent I see "Clojure's Agents are reactive, not autonomous - there is no imperative message loop and no blocking receive." http://clojure.org/agents

20:05 this is two different meanings for "reactive agent" right?

20:05 amalloy: probably. reactive is practically just an adjective meaning "friggin awesome"

20:06 justin_smith: heh

20:06 "functional friggin awesome programming"

20:06 it works!

20:06 amalloy: also, there is a kinda funny github bug involving issue references that i just noticed

20:06 justin_smith: amalloy: yeah, that issue ref was weird

20:06 on issue 6

20:06 amalloy: justin_smith: it's not just issue 6!

20:06 justin_smith: err.. pull 6

20:06 oh?

20:07 amalloy: *all* the low-numbered issues in the clojure repo are "mentioned" by that other one

20:07 up to #29

20:07 because that other one includes a paste of some console output

20:07 which contains lines looking like: "native: #25 pc 00008cf0"

20:08 justin_smith: ah, and I bet some crazy regex grabs those

20:08 hiredman_: it turns out github is just a pile of heuristics that fail at the edges like everything else

20:08 amalloy: but...unicorns?

20:09 hiredman_: unicorns, scrum, and agile best practices, etc

20:17 xemdetia: I once saw a project manager increase efficiency by twelve unicorns once

20:34 tehgeekmeister: how do you set pprint to be less eager about adding newlines between keys (with no dedent) and complex values?

20:34 is there any way?

20:44 justin_smith: tehgeekmeister: http://clojuredocs.org/clojure.pprint there are some variables that help control how pprint behaves

20:44 tehgeekmeister: @justin_smith yeah, i looked at those

20:44 set the print-miser-width to like 10k and it still didn't do what i was after

20:45 justin_smith: tehgeekmeister: how about *print-right-margin*

20:48 tehgeekmeister: @justin_smith trying it now

20:49 nope, set it to 10k-ish too

20:51 maybe I'm doing it wrong, i did: (def ^:dynamic *print-right-margin* 1000000)

20:51 (10k-ish apparently means a million.)

20:51 @justin_smith see above

20:51 justin_smith: tehgeekmeister: that's not how it works

20:52 tehgeekmeister: https://www.refheap.com/96881

20:52 tehgeekmeister: checking now, thanks for the help

20:52 justin_smith: notice I got pprint to put 100 numbers one one line

20:53 *on one

20:53 tehgeekmeister: the docs indicate that there is a variable called *print-right-margin* in clojure.pprint which controls that behavior

20:54 tehgeekmeister: yeah, so this isn't exactly what we're after fixing, but at least i've learned how to customize the options

20:54 i'll dig through the docs a bit more and try things now

20:54 now that i know how to do it right

20:54 justin_smith: tehgeekmeister: in general you aren't going to see code that looks for magic var names in your namespace, that's just not how we do things

20:54 tehgeekmeister: yeah, it seemed oddd

20:55 justin_smith: if some var controls a functions global behavior, it'll be defined in the same project (if not the same namespace)

21:06 from now on, when I use agents in my clojure code, I will be naming them "smith"

21:24 andyf: tehgeekmeister: If pprint isn?t bending to your will, you may want to take a look at aprint to see if it does what you want: https://github.com/razum2um/aprint

21:28 dbronico: If I am doing work in parallel that has prints, is there a way to guarantee no overlapping prints? I was hoping atoms with watches would work, but it's not the case.

21:28 julianleviston: dbronico: I would think a logger would have this covered.

21:28 justin_smith: dbronico: one option is (locking *out* (println ...)) - just make sure that nothing inside the println call tries to do the same of course

21:28 or yeah, the better option is a proper logger

21:29 dbronico: A proper logger... Can you give a little more detail or a reference to where I can find out more?

21:29 julianleviston: dbronico: maybe you could redef println for your work.

21:30 justin_smith: dbronico: check out clojure.tools.logging

21:30 julianleviston: just first google I found...

21:30 justin_smith: or what julianleviston said

21:30 julianleviston: haha :)

21:30 sorenmacbeth: is there a not terrible way to resolve an aliases var to it's fully qualified self?

21:31 justin_smith: sorenmacbeth: you can get the mappings of an ns programmatically, and look it up in there - depending on what you are actually doing

21:31 julianleviston: dbronico: core async channels could be good… :-)

21:31 justin_smith: ,(.getMappings *ns*)

21:31 clojurebot: {primitives-classnames #'clojure.core/primitives-classnames, +' #'clojure.core/+', Enum java.lang.Enum, decimal? #'clojure.core/decimal?, restart-agent #'clojure.core/restart-agent, ...}

21:33 dbronico: justin_smith, julianleviston: Thanks a lot. I'll check out the logging. Didn't realize it was an easily-Googlable term. =P

21:33 justin_smith: or ##(ns-refers *ns*) which is slightly higher level

21:33 lazybot: ⇒ {primitives-classnames #'clojure.core/primitives-classnames, +' #'clojure.core/+', decimal? #'clojure.core/decimal?, restart-agent #'clojure.core/restart-agent, sort-by #'clojure.core/sort-by, macroexpand #'clojure.core/macroexpand, ensure #'clojure.core/ensure, chun... https://www.refheap.com/96882

21:33 dbronico: julianleviston: Thanks for the suggestion. I hear a lot about core.async. I'll check that out, too.

21:33 julianleviston: dbronico: it’s fricking awesome.

21:34 dbronico: a really good way to make sure your one thing does only one thing at once (fanning in).

21:35 sorenmacbeth: justin_smith: cheers

21:35 justin_smith: ,(ns-aliases *ns*) ; this may also be helpful

21:35 clojurebot: {}

21:36 justin_smith: and in general ##(clojure.repl/apropos #"^ns")

21:36 lazybot: ⇒ (ns-unmap ns-publics ns-unalias ns-aliases ns-resolve ns-refers ns ns-name ns-map ns-interns ns-imports nss)

21:38 dbronico: julianleviston: So I'd set up a channel, a sorta 'channel-reader' that's infinite loop (in theory) that just listens on the channel and prints whatever it gets, then just have my print messages get put on the channel.

21:38 justin_smith: dbronico: google isn't always reliable (ie. we phased out clojure.contrib much faster than google stopped giving results about clojure.contrib)

21:39 dbronico: yeah, that's the idea. I would write a function that takes varargs and puts them on the chan to be printed (so that your code doesn't have to look like core.async code, it can just be your-ns/println)

21:39 julianleviston: dbronico: yeah, you could have one go block with a channel set up around your main functionality that just blocks then prints, and your main functionality then passes that channel to the rest of the code, and then all your calls to println become a call to put! the channel instead.

21:40 justin_smith: wait… clojure.contrib is phased out?

21:40 TEttinger: julianleviston: yeah since 1.2

21:40 justin_smith: julianleviston: http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

21:40 amalloy: julianleviston: the old old old thing of a single clojure-contrib jar is out

21:40 clojure contrib as a collection of independent libraries still exists

21:40 julianleviston: oh phew.

21:41 justin_smith: oh yeah, good point :)

21:41 but we don't have the clojure.contrib.whatever naming any more either

21:41 even if they are contrib projects

21:41 dnolen: iOS ClojureScript REPL is blowing my mind, all thanks to mfikes

21:41 julianleviston: bmabey: .… of rspec/cucumber fame?

21:42 dnolen: haha… wow…. that’s so fricking cool

21:43 dbronico: justin_smith, julianleviston: OK, I'm checking out core.async. Thanks again.

21:46 julianleviston: dnolen: so what are the ramifications of this that give you so much excitement?

21:46 dnolen: julianleviston: well later React Native

21:46 julianleviston: (that I’m not doubt missing)

21:46 dnolen: julianleviston: but really this just means you can script any iOS application given you've added adequate bridging

21:47 julianleviston: React Native just ships with a bunch of free bridging

21:47 julianleviston: but this just means you can build real iOS apps (no WebView) with ClojureScript with the expect REPL driven workflow

21:47 julianleviston: dnolen: hey what do you think of Relay, btw? I spent the last like 6 months wrangling my own with Om/CLJS and… I’m tired. :-)

21:48 dnolen: ah… yeah, react native… huzzah… does it transpile to the objc/swift runtime? For some reason I thought it was running a javascript vm inside it. lol.

21:49 (no idea if transpile is the right word to use there)

21:49 dnolen: julianleviston: Apple shipped real JavaScript bindings into Objective-C run time w/ iOS 7

21:49 julianleviston: this is old news

21:49 julianleviston: dnolen: oh. I think I missied that. What does real JS bindings mean, tho?

21:49 dnolen: julianleviston: but yes embedded JS that talks to native components

21:50 julianleviston: like a real native embedded language bridge

21:50 julianleviston: ooh

21:50 dnolen: julianleviston: the same way V8 talks to C++

21:50 julianleviston: dnolen: or Nu or CocoaRuby

21:51 dnolen: yep

21:51 julianleviston: wow

21:52 OMFG so we might get true native performance running clj in the browser in iOS… and on Om apps… oh this is nuts.

21:54 dnolen: julianleviston: well you're limited by JSC, no JIT yet, but this doesn't matter for many apps

21:54 julianleviston: FB is already building real apps w/ stuff

21:54 and the perf is good

21:55 rkneufeld: If anyone out there is using or has considered using Simulation Testing, I'd love to get your input: http://www.rkn.io/2015/02/03/state-of-sim-testing-2015/

21:56 tehgeekmeister: @justin_smith we found fipp, it does the style of printing we're after

21:56 julianleviston: dnolen: that’s really cool

21:56 tehgeekmeister: but thanks for the pointers, they'll definitely help us get up to speed

21:56 justin_smith: tehgeekmeister: oh, nice

21:57 bbloom: tehgeekmeister: let me know if fipp works out for you

21:57 tehgeekmeister: bbloom: it does so far, in like <5 minutes of use

21:57 will get back to you though, for sure

21:57 mfikes: dnolen: The perf of React Native is actually much better than what the FB Groups app would lead you to believe. (There is a lot of FB infrastructure that is unrelated to React Native in its init sequence.)

21:58 justin_smith: bbloom: oh, now that I see you are around, I'm thinking you may be one of the people who could give me a good answer to this question I just posted on the ml https://groups.google.com/forum/#!topic/clojure/Le_McSEy1_c

21:58 dnolen: mfikes: good to hear

22:01 mfikes: dnolen: I was concerned because the ClojureScript / native hybrid app I built starts up much (much) more quickly than FB Groups, and Vjeux esentially explained that plain-vanilla React Native apps start up instantaneously :)

22:02 julianleviston: Also, this will all lead to Android, and (for someone like me) perhaps the ability to build decent web apps :)

22:02 julianleviston: haha :)

22:04 n0n3such: quick question: i have spent the last 2 years learning scala and building a big project in scala and now want to learn another language while i develop my scala skills further. I am considering haskell and clojure.

22:04 mfikes: julianleviston: It is an amazing thought: You can learn Clojure(Script) for front and backend (1 language), and React for several front ends.

22:04 julianleviston: mfikes: it really is…

22:04 n0n3such: How will learning clojure help me improve as a software developer ?

22:04 mfikes: julianleviston: And all of it is very functional

22:04 julianleviston: n0n3such: learn them both. They’re both excellent.

22:05 n0n3such: julianleviston: which is a better investment of my limited time and brainpower ?

22:05 julianleviston: n0n3such: clojure is a lot easier to approach, so start with that… but learn a little haskell every day.

22:05 mfikes: n0n3such: Yes, you need to at least read through the Haskell O'Reilly book. It will _force_ you to look at things a certain way.

22:06 n0n3such: mfikes: Real World Haskell ?

22:06 sharms: how do I make 'lein ring server' auto-reload?

22:06 mfikes: n0n3such: Yep. I liked that one. Brian O'Sullivan IIRC

22:07 julianleviston: sharms: I think the help tells you doesn’t it?

22:07 codestorm444: I looked into many FP languages, and chose Elixir

22:07 n0n3such: codestorm444: why ?

22:07 julianleviston: codestorm444: why choose one?

22:07 sharms: julianleviston: no, running 'lein help ringer server' gives no help

22:08 codestorm444: Elixir runs on the Erlang VM which has some awesome features. It incorporates some of the better features from clojure, but has a friendly Ruby-like syntax

22:08 julianleviston: gotta start somewhere

22:09 clojure was my #1 until I learned about Elixir, haskell would have been #3 choice

22:09 n0n3such: why clojure #2 ?

22:09 julianleviston: codestorm444: I guess, as always, it comes down to… what are you trying to do? :)

22:10 sharms: If the LEIN_NO_DEV environment variable is not set, the server will monitor your source directory for file modifications, and any altered files will automatically be reloaded. https://github.com/weavejester/lein-ring

22:11 sharms: julianleviston - thanks, I am not sure for whatever reason that is working, however if I add :auto-reload? true to my project.clj it works now

22:11 codestorm444: why #2? well, clojure pros: large base of JVM libraries... concurrency features... macros

22:11 julianleviston: sharms: oh yeah, sorry… it’s been a while since I’ve used it.

22:12 codestorm444: erm… what about the persistent data structures? OMG

22:12 codestorm444: and the immutability…

22:13 codestorm444: yeah, elixir has those too

22:13 i guess most FP languages do

22:13 julianleviston: codestorm444: erm… no?

22:13 codestorm444: not that I know of.

22:14 codestorm444: Elixir does

22:14 Scala hedges with val and var

22:14 julianleviston: codestorm444: it has persistent data structures?

22:14 codestorm444: yes

22:14 julianleviston: codestorm444: can you point me to where this is true?

22:15 codestorm444: using the same trie structures as Clojure?

22:16 TEttinger: there are probably other data structures that are persistent that are better for certain tasks

22:16 as in, not 32-trie based

22:18 julianleviston: TEttinger: sure. As always, it depends what you’re trying to do ;-)

22:18 codestorm444: julianleviston: I don't have a hnady link for you, but that's how elixir works. You add something to a list, you get a different list, the original is untouched

22:18 julianleviston: TEttinger: these ones have some nice properties, tho… to put it mildly ;-)

22:19 amalloy: codestorm444: that's not necessarily the same thing as persistent

22:19 TEttinger: ah, it's immutable not necessarily persistent

22:19 amalloy: you can implement that property using copy-on-write arraylists or something, which supports a functional style but is immensely slow

22:19 julianleviston: codestorm444: can I suggest before you go down any of these paths, watch some rich hickey talks about persistent data structures...

22:20 amalloy: i don't know how elixir's data structures actually are, just pointing out that your example doesn't necessarily answer the question

22:20 julianleviston: codestorm444: that was why I asked you four times… I should have asked you to define persistent data structure instead, it seems.

22:21 codestorm444: the end rub is… these are incredibly fast for most of the types of things most coders do most of the time, and support concurrency really well.

22:22 amalloy: http://comments.gmane.org/gmane.comp.lang.elixir.general/442 suggests that the answer is complicated

22:25 julianleviston: amalloy: hm… it seems pretty cut and dry to me… it relies on what the erlang vm does… which isn’t aware of this stuff. What about vectors? sorted collections? the whole idea of the sequence abstraction? For the guts of most coding practice, I’m yet to see a language that encourages a programmer to pay as much attention to the upsides of the structures they pick (and why) as it does to the downsides.

22:35 I love that where other languages say “Don’t look into this box”, “Don’t worry about how that works”, or “I’ll handle that for you”, clojure says “It’s hard, but you can absolutely do it, let me show you how, and what the costs/benefits are of choosing each thing are”.

22:37 tehgeekmeister: so if i want to pipe a java buffered stream to stdout in clojure, how do i do that idiomatically?

22:38 rather than reading the whole thing in, and then printing it out

22:38 i mean i know i can read a small chunk, write it, etc, but i figure there has to be a better way

22:39 Lewix: hi gentlemen

22:39 julianleviston: tehgeekmeister: https://www.safaribooksonline.com/library/view/clojure-cookbook/9781449366384/ch04.html

22:39 Lewix: (+ (cons (nth [1 2 3] 0) [1 2 3]) )

22:39 I expected this to work

22:40 what's the logic behind it not working?

22:40 ToxicFrog: Nethack bot written in Clojure achieves the first fully automated ascension: https://www.reddit.com/r/nethack/comments/2tluxv/yaap_fullauto_bot_ascension_bothack

22:40 justin_smith: oh wow, awesome

22:41 julianleviston: Lewix: you’re trying to add a cons cell

22:41 Lewix: what does that mean?

22:41 maybe you want (apply + (cons (nth [1 2 3] 0) [1 2 3]) )

22:42 sdegutis: What's a good GUI toolkit for writing a budget app?

22:42 Lewix: julianleviston: cons produces a list

22:42 julianleviston: sdegutis: MYOB

22:42 sdegutis: too sarcastic? :-)

22:43 sdegutis: oh

22:43 Lewix: julianleviston: which makes me wonder why apply is needed - it's not a vector

22:43 julianleviston: Lewix: + takes numbers.

22:43 Lewix: you passed it a cons cell

22:43 Lewix: nothing to do with vectors.

22:44 ,(doc +)

22:44 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'"

22:44 Lewix: julianleviston: i see so the first evaluator cares about the others evaluators

22:44 strange

22:44 julianleviston: Lewix: what’s an evaluator?

22:44 Lewix: julianleviston: anyways, i expected (cons (nth [1 2 3] 0)) to return a list and be treated as such

22:45 julianleviston: Lewix: apply takes a function (ƒ) and a collection of some kind, and calls it as though you’ve poured the contents of the collection into arguments of calling that function (ƒ).

22:45 Lewix: julianleviston: However, from what you're saying + cares that it was called with cons

22:45 bbloom: (doc cons)

22:45 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

22:45 Lewix: julianleviston: i don't have apply here

22:45 julianleviston: ,(+ ‘(1 2))

22:46 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ‘ in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:46 julianleviston: ,(+ [1 2])

22:46 clojurebot: #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentVector to java.lang.Number>

22:46 Lewix: whihc makes sense

22:46 (+ (1 2 3))

22:46 ,(+ (1 2 3))

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

22:46 julianleviston: ,(+ '(1 2))

22:46 clojurebot: #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentList to java.lang.Number>

22:46 Lewix: ,(+ 1 2 3)

22:46 clojurebot: 6

22:47 Lewix: ,(+ (1 2 3))

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

22:47 Lewix: really

22:47 here is my issue

22:47 julianleviston: ,(cons 1 nil)

22:47 clojurebot: (1)

22:47 tehgeekmeister: @julianleviston seems like that just shows how to do bytes at a time, not just plugging two streams together

22:47 julianleviston: ,(+ (cons 1 nil))

22:47 clojurebot: #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentList to java.lang.Number>

22:47 julianleviston: see?

22:48 tehgeekmeister: what does that mean? Sorry… not really sure what plugging two streams looks like. Prolly not the best guy to answer your Q, really...

22:48 tehgeekmeister: ah okay

22:48 nbd

22:48 julianleviston: tehgeekmeister: ask it in java… someone can explain it idiomatically in clojure.

22:48 tehgeekmeister: i basically mean, if i have a stream that produces data

22:48 and one that can consume data

22:48 i just want to redirect all content from the producer to the consumer

22:48 julianleviston: tehgeekmeister: yeah… why can’t you just plug them together?

22:49 tehgeekmeister: in java you'd do this imperatively, i think

22:49 julianleviston: tehgeekmeister: isn’t that just a matter of plugging the one into the other? (out (in))

22:49 dbronico: julianleviston: Thanks for recommending core.async. For what I needed it for (non-overlapping, parallel printing), the setup was really easy and it seems to be working with 7 threads.

22:49 julianleviston: tehgeekmeister: Using a streamreader and streamwriter tho

22:49 amalloy: tehgeekmeister: clojure.java.io/copy ?

22:49 tehgeekmeister: i would like it to be that simple, i just don't know

22:49 @amalloy checking

22:49 julianleviston: dbronico: yeah it’s great, isn’t it! :)

22:49 tehgeekmeister: it is that simple.

22:49 amalloy: don't touch readers and writers if you want to use bytes. those are for characters

22:50 tehgeekmeister: i just want straight redirection.

22:50 julianleviston: tehgeekmeister: what amalloy said!

22:51 Lewix: grok or no grok?

22:52 Lewix: julianleviston: my problem was simply that I assumed list and a serie of number was the same thing

22:52 (+ 1 2 3 4)

22:52 clojurebot: *suffusion of yellow*

22:52 julianleviston: Lewix: ah!

22:52 tehgeekmeister: amalloy: that's synchronous, I imagine, so I couldn't copy two streams in parallel? oh wait, there's gotta be a thing for that. i can figure this out.

22:52 amalloy: tehgeekmeister: future

22:52 Lewix: (+ (1 2 3 4))

22:52 amalloy: use threads

22:52 Lewix: not the same thing

22:52 julianleviston: add( list( 1, 2) ) // -> what is this? add doesn’t understand a list.

22:52 apply(add, list( 1, 2) ) // -> I will do as you wish

22:53 Lewix: julianleviston: thats right

22:53 julianleviston: Lewix: sometimes I found shifting things to C syntax helped in the past.

22:54 bbloom: think of ( and ) like you might [ and ] when initializing an array or something

22:54 parens in C are for precedence, but in a lisp they construct a data structure like [ and ] can do

22:55 julianleviston: bbloom: which if you look at the AST C produces, is a data structure...

22:55 bbloom: julianleviston: that AST is an implementation detail of a particular compiler

22:55 julianleviston: bbloom: so really, it’s the same thing. Precedence, or data structure… LISP just lets you know what is going on under the hood.

22:55 bbloom: julianleviston: in clojure it's an abstraction provided to the object program

22:56 julianleviston: i disagree with the notion of "under the hood"

22:56 julianleviston: bbloom: Ok.

22:56 bbloom: i disagree with the notion of disagreement.

22:57 bbloom: also, parens are not only for precedence in C. The parens I was talking about are for function call notation.

22:58 bbloom: which can be viewed as a data structure indicating to the compiler to call a function… which is what a list is used for in LISP

22:58 bbloom: granted C is in no way homoiconic, but the parallel is there IMHO.

22:59 * bbloom walks away from a pointless debate

23:00 julianleviston: bbloom: what’s your point? :-)

23:01 Lewix: bbloom: good point

23:01 julianleviston: bbloom: I like that clojure adds vectors so that linear data collections can have a separate reader syntax to program form syntax, though. That alone makes understanding clojure code so much easier than, say, scheme, or CLISP.

23:01 dnolen: julianleviston: I think you missed the simple point that C source isn't data structure the way Lisp and the benefits derived therein. In you have to go all the way to the AST. In Lisp you don't. Thank god. But the real AST is there in those rare cases that you need.

23:01 Lewix: the documention of closure sucks

23:01 ,(doc cons)

23:01 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

23:02 Lewix: really? you dont tell me how to use it

23:02 bbloom: Lewix: every single function would have to tell you how to use it

23:02 Lewix: the clojure docs are not for beginners

23:02 julianleviston: Lewix: sure it does… the [] is the arument list - it takes two… x and a seq…

23:02 bbloom: at least the functions are

23:02 Lewix: I dont know i can do this

23:02 dnolen: Lewix: http://clojuredocs.org

23:02 Lewix: ,(cons "doc didnt help" (1 2 3))

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

23:02 Lewix: ,(cons "doc didnt help" [1 2 3])

23:02 clojurebot: ("doc didnt help" 1 2 3)

23:03 bbloom: Lewix: you're trying to do multiple things at once & you don't understand the primitives

23:03 type (1 2 3) in to your REPL by itself

23:03 note that a leading comma uses a repl here

23:03 Lewix: ,(cons "doc didnt help" (1 2 3))

23:03 clojurebot: ("doc didnt help" 1 2 3)

23:03 julianleviston: Lewix: sadly we’re not QUITE at the self-describing pedagogical language we’d all love… but CLJ is a huge step there compared to other modern languages.

23:03 bbloom: ,(1 2 3)

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

23:03 Lewix: I still think the doc sucks

23:03 julianleviston: Lewix: no way, man.

23:04 Lewix: it’s there for people who know how to read it.

23:04 Lewix: julianleviston: it doesnt tell me what it return

23:04 theres many form of sequences from what I read

23:04 julianleviston: Lewix: (source cons) does tho

23:04 bbloom: (doc cons)

23:04 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

23:04 bbloom: "returns" is literally the first word of the doc string

23:04 Lewix: i don't know if it's a list or a lazsequence for example

23:04 julianleviston: Lewix: ah… it’s a SEQ.

23:04 gfredericks: that's usually not important

23:05 julianleviston: Lewix: that’s a thing.

23:05 Lewix: ,(list? (cons "doc didnt help" (1 2 3)))

23:05 clojurebot: false

23:05 bbloom: ~list?

23:05 clojurebot: excusez-moi

23:05 bbloom: ~list

23:05 clojurebot: excusez-moi

23:05 bbloom: dammit clojure-bot

23:05 julianleviston: (seq? (cons ‘yay nil))

23:05 * Lewix votes for improving the doc

23:05 julianleviston: Lewix: erm… how would you impove it?

23:06 any less terse and you’d annoy people who don’t want to wade thru crap to get to the info.

23:06 Lewix: read this: http://clojure.org/sequences

23:06 Lewix: julianleviston: just be more specific. There's no excuses - some others languages have good doc

23:06 julianleviston: Lewix: I don’t follow… that *IS* very specific.

23:06 bbloom: Lewix: you're wishing for the wrong solution to your problem

23:06 julianleviston: it returns a seq. That’s what it does.

23:06 bbloom: Lewix: typical clojure users quite like clojure's docstrings

23:06 Lewix: I'm no wishing for anything

23:06 bbloom: Lewix: you need a book

23:06 ~book

23:06 clojurebot: book is programming clojure

23:07 Lewix: julianleviston: a list is considered a seq

23:07 julianleviston: bbloom: agreed!

23:07 Lewix: um… what?

23:07 go read that link I just sent you.

23:07 bbloom: julianleviston: that's not helpful

23:07 julianleviston: bbloom: no but the link may be. :)

23:07 bbloom: ~colls

23:07 clojurebot: colls is seqs and colls

23:07 bbloom: ~seqs

23:07 clojurebot: seqs is http://www.brainonfire.net/files/seqs-and-colls/main.html

23:07 julianleviston: bbloom: I’m just explaining that he needs to learn more.

23:07 bbloom: ^^ that link is more helpful

23:07 but still, it's not helpful at all

23:08 gfredericks: julianleviston: a list is a seq though

23:08 Lewix: so wait

23:08 bbloom: Lewix: try http://www.braveclojure.com/

23:08 julianleviston: bbloom: Sure it is :) You just hate me :)

23:08 Lewix: you guys are telling me that list are not seq ?

23:08 julianleviston: bbloom: oh god not that!

23:08 Lewix: (seq? (1 2 3 4))

23:08 ,(seq? (1 2 3 4))

23:08 clojurebot: true

23:08 julianleviston: ,(type (1 2 3 4))

23:08 clojurebot: clojure.lang.Cons

23:08 amalloy: lists are seqs for sure

23:09 tomjack: bbloom: hey! after years of willful ignorance, oleg/filinski/delimc/effects/etc have come back around and bit me on the ass. just curious, is getting ext_test.clj in eclj to work a TODO, or is it supposed to work?

23:09 Lewix: amalloy: exactly which bring me back to my point.

23:09 the doc could be more specific

23:09 gfredericks: amalloy: I have though heard it argued that lists being seqs is an impl detail

23:09 amalloy: hm

23:09 gfredericks: Lewix: more specific how?

23:09 saying it returns a list?

23:09 Lewix: gfredericks: saying that it returns a seq is confusing

23:09 bbloom: tomjack: nothign in eclj is supposed to work :-P

23:10 Lewix: ,(seq? (1 2 3 4))

23:10 clojurebot: true

23:10 bbloom: tomjack: it's totally me exploring stuff. not sure what state i left it in

23:10 Lewix: ,(list? (cons "doc didnt help" (1 2 3)))

23:10 clojurebot: false

23:10 tomjack: ah, ok

23:10 well, thanks for it, quite inspiring

23:10 julianleviston: Lewix: I think if you find the docs confusing, then it’s probably because you need to increase your knowledge of clojure. They’re not there to teach you clojure. They’re there to explain how things work once you know.

23:10 bbloom: tomjack: cool. glad you like it

23:10 gfredericks: Lewix: not sure what the confusion is, what else would it say?

23:10 Lewix: julianleviston: you just told me that list are not a seq, in my defense

23:10 julianleviston: Lewix: it isn’t.

23:11 Lewix: they’re not identical.

23:11 amalloy: julianleviston: it one million percent is. if you're going to condescend to Lewix at least be right

23:11 julianleviston: Lewix: the relationship is inclusive.

23:11 Lewix: from what i gather list and lazyseq are both seq

23:11 julianleviston: amalloy: I wasn’t aware I was being condescending. Apologies!

23:11 amalloy: me recommending someone else learn more doesn’t preclude me from not being ignorant!

23:12 bbloom: julianleviston: "learn more" is just a dick way to say anything

23:12 gfredericks: (inc bbloom)

23:12 julianleviston: bbloom: is it? I thought it was concise.

23:12 gfredericks: sometimes concision is dickish

23:12 julianleviston: bbloom: sorry for being a dick!

23:12 gfredericks: despite intentions

23:12 julianleviston: haha :) ok.

23:13 apologies for my dick.

23:13 ish.

23:13 ness.

23:13 gfredericks: especially on the internet where people can't see your face

23:13 julianleviston: Lewix: dude… apologies… I am on your side.

23:13 Lewix: I am here to help, and I’m interesed in all of our betterment.

23:13 amalloy: gfredericks: upcoming project: replace every website with a picture of my face

23:14 jonh: , (type (cons "doc didnt help" `(1 2 3)))

23:14 clojurebot: clojure.lang.Cons

23:14 Lewix: julianleviston: no worries

23:15 jonh: Lewix: so my guess is that is why list? does not return true

23:15 julianleviston: Lewix: also, I need to learn as much, if not more, than you…

23:15 Lewix: julianleviston: I doubt. I started three days ago. You'll probably know more

23:15 You*

23:16 julianleviston: this might help…

23:16 ,(list)

23:16 clojurebot: ()

23:16 julianleviston: ,(list? (list))

23:16 clojurebot: true

23:16 julianleviston: ,(seq? (list))

23:16 clojurebot: true

23:17 julianleviston: ,(list? (seq))

23:17 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/seq--4091>

23:17 julianleviston: ,(list? (seq (list)))

23:17 jonh: pwnd

23:17 clojurebot: false

23:17 julianleviston: does that help?

23:17 gfredericks: amalloy: I'm writing a movie script based on the premise that you somehow succeed at doing so despite the various reasons it's impossible

23:17 amalloy: experts are baffled

23:18 amalloy: gfredericks: sequel to The Core?

23:18 gfredericks: yeah bruce willis and a small team are going to hack into the internet to take those amalloy photos down

23:18 using guns

23:19 a side plot would involve the efforts by web designers to adapt their UIs to the new constraint of having amalloy's photo in the middle of the page

23:20 julianleviston: ,(type (seq [1 2]))

23:20 clojurebot: clojure.lang.PersistentVector\$ChunkedSeq

23:20 gfredericks: ,(deftype ChocolateChunkedSeq [])

23:20 clojurebot: sandbox.ChocolateChunkedSeq

23:20 julianleviston: ,(list? (seq [1 2]))

23:20 clojurebot: false

23:21 julianleviston: ,(type (seq (list 1 2)))

23:21 clojurebot: clojure.lang.PersistentList

23:21 julianleviston: obviously that’s a list, whereas a seq’d vector isn’t, right?

23:21 but both are seq’s… right?

23:21 gfredericks: right

23:21 julianleviston: Lewix: ergo… some seqs ARE lists, others aren't...

23:21 Lewix: but all lists are seqs.

23:22 gfredericks: julianleviston: I think that's what Lewix meant, you were just misinterpreting

23:22 julianleviston: gfredericks: oh ok. Sorry, I thought he thought List == Seq or something with semantic equivalency.

23:24 raspasov: hey guys, atom/STM question

23:24 julianleviston: Lewix: it doesn’t help much that there are a bunch of things that make you think they’re all the same coz they start with the letters s e q, but they’re not exactly the same…

23:24 raspasov: so if from one thread I do something like (def x (atom 0)) (swap! x + 1) @x

23:25 jonh: Lewix initial example was a cons though, thats why list? says false

23:25 raspasov: I am guaranteed to get @x to be 1, that's clear

23:25 what about other threads though? if there's updates coming to the x atom, are all other threads guaranteed to see "latest" state or just a "valid" state when deref-ing x?

23:26 Lewix: julianleviston: What I was saying all along is - vectors, lists, lazyseq are all sequential, lists and lazyseq are both seq and they're all collection. So when we document what we return, shouldn't we used the right term to avoid confusion

23:26 s/used/use

23:27 gfredericks: Lewix: and what's the right term in the case of cons?

23:27 Lewix: if we return lazyseq we don't want to say we return seq - it leads to confusion. That was all i was trying to say - I guess there was some confusion or I didn't express myself properly

23:27 (doc cons)

23:27 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

23:27 Lewix: ,(doc cons)

23:27 julianleviston: Lewix: I’m curious if that precision has any real world ramifications, though? The docs seem to explicitly refer to the level of detail that is particular to the context… so if “seq” (meaning the abstraction) is the guarantee, they tend to say that… perhaps I’m wrong, tho… it’s usual.

23:27 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

23:28 Lewix: julianleviston: even if it doesn't have real implications - better be safe than sorry especially when it does not cost much

23:28 jonh: ,(type (cons 1 [2 3]))

23:28 clojurebot: clojure.lang.Cons

23:28 julianleviston: Lewix: not if the level of “vagueness” is actually what’s precisely intended, tho…

23:28 Lewix: gfredericks: right term is lazyseq I think

23:29 gfredericks: Lewix: it's not a lazy seq

23:29 Lewix: gfredericks: If it's a seq and it's not a list, chances are it's a lazy seq I thought

23:29 gfredericks: there are other kinds of seqs besides lazy & list; and the idea is that you shouldn't have to care what kind it is

23:29 julianleviston: Lewix: a seq is something that adheres to that protocol, isn’t it? that’s the limit of the guarantee of that function signature, righ?

23:30 (inc gfredericks)

23:30 nice explanation!

23:30 Lewix: gfredericks: I dislike that train of though. I really care about precision

23:30 thought*

23:30 julianleviston: Lewix: it *is* precise.

23:31 Lewix: precisely not detailed.

23:31 amalloy: clojure, the best precisely-vague language

23:31 julianleviston: amalloy: lol. Protocols are “precisely vague” :)

23:31 Lewix: if you expect it to return a seq then it would mean that it could also return a list. How precise is that?

23:32 (However in our situation it does not return a list)

23:32 julianleviston: Lewix: It’s precise because if you choose something that builds or deals with seqs, you care about the properties of seq’ing… and not the extra properties.

23:32 Lewix: if you wanted a list, don’t ask for a seq. Likewise if you want a set, don’t use a vector!

23:35 raspasov: I don’t really remember, but I remember that the rich hickey ants talk goes into it quite well… https://www.youtube.com/watch?v=dGVqrGmwOAw

23:36 raspasov: julianleviston: yea I thought it does (I have seen this video multiple times - maybe a time for a re-watch) lol, it uses java AtomicReferences, which should ensure that changes are visible to all threads

23:36 julianleviston: raspasov: he explains the different types of refs and what you want to use each for, and the guarantees of each.

23:36 jonh: Lewix: (list? (cons 1 nil)) :)

23:37 Lewix: jonh: I'm still looking for the simple and easy part - especially after your example...

23:37 raspasov: julianleviston: I think problem is in my code most likely, so investigating there first : ) pretty sure changes are always visible

23:37 julianleviston: raspasov: oh it depends on “when” you’re talking about, I guess… from what I understand, everything happens in atomic sets… so you have a consistent view of the world… so they would all see the state, but only at the point in time at which you ask for the value (by dereffing)… does that cover your q?

23:38 raspasov: julianleviston: yes, basically...

23:39 jonh: Lewix: leaky abstractions, kinda feels javascript esque

23:39 julianleviston: raspasov: yeah, gotta make sure each thread isn’t getting its own separate atom

23:39 raspasov: julianleviston: or like, a different state of the same atom

23:39 Lewix: jonh: exactly

23:39 julianleviston: jonh: whatcha mean?

23:39 jonh: , (list? (cons 1 nil))

23:39 clojurebot: true

23:40 julianleviston: raspasov: um… yeah, I think you might not want an atom, depending on what you’re after… you need dosync and whatnot. no?

23:40 justin_smith: Lewix: the easy /simple part is concreyr types rarely matter. what matters are thr interfaces.

23:40 julianleviston: jonh: Sorry… not really sure waht your point is :S

23:41 justin_smith: *concrete that is

23:41 raspasov: julianleviston: yea, thanks, I'm familiar with refs, etc thanks for your input :) debugging now

23:41 julianleviston: raspasov: sorry :)

23:42 jonh: sorry to hear that

23:42 julianleviston: jonh: I’d love to know, if you care to explain :)

23:42 ,(type (cons 1 nil))

23:42 clojurebot: clojure.lang.PersistentList

23:43 julianleviston: That seems to be a list.

23:43 … and it has returned a seq. Just like the docs for cons say it should.

23:44 your abstraction has to be reified in SOME concrete entity, right? It happens to be a list from cons at clojure’s current version.

23:45 jonh: not really sure how that’s a leaky abstraction… ?

23:46 justin_smith: Lewix: imagine if I were asking what type '/' returns...

23:46 julianleviston: justin_smith: I just had a thought - maybe they want typed clojure!

23:46 justin_smith: should send them to that project.

23:49 Lewix: you might like this: https://github.com/clojure/core.typed

23:50 Lewix: and judging from our convos here, I think you’d LOVE haskell, if you haven’t already learned it.

23:51 Lewix: justin_smith:

23:51 ,(type \/)

23:51 clojurebot: java.lang.Character

23:52 julianleviston: Lewix: erm… \/ is the backslach char…

23:52 justin_smith: Lewix: I meant the division operator, and what it returns varies based on context but the applicable interface is Number

23:52 julianleviston: backslash even.

23:52 justin_smith: julianleviston: it's forwardslash

23:52 julianleviston: justin_smith: soz… guh. Yeah.

23:53 justin_smith: Lewix: the rules for what kind of Number you get back don't belong in the docs for '/', they belong in the docs on the math operators

23:54 Lewix: justin_smith: like most languages

23:54 justin_smith: Lewix: similarly, seq suffices for documenting cons, but there is extensive clojure documentation on what a seq means, and which things can be considered seqs, etc.

23:54 Lewix: most of the time, "seq" or "Number" are enough to go on

23:54 Lewix: ./ is not a data structure

23:54 justin_smith: Lewix: sometimes, you really want to get into the details

23:55 Lewix: nor is cons

23:55 cons RETURNS a data structure

23:55 Lewix: list is

23:55 julianleviston: Lewix: it *would* be nice if there was a bit by bit path pedagogical learning environment, like Racket has…

23:55 justin_smith: Lewix and in fact, / can return data structures, for example ##(/ 2 3)

23:55 that is a data structure

23:55 Lewix: justin_smith: my issue is not about cons

23:56 my issue is if you tell me it return a bottle i expect a bottle

23:56 if you tell me it returns a seq i expect a seq

23:56 justin_smith: Lewix: and there are at least 20 things that are seqs

23:56 seq is a general category

23:56 Lewix: exactly

23:56 justin_smith: like Number

23:56 returns a Number

23:56 same thing

23:56 julianleviston: Lewix: what if you return a number, and I give you 5.0 ? But… that’s not a number… yes it is…. it’s a float… which is a number.

23:56 justin_smith: err

23:56 / returns a number

23:56 cons returns a seq, same thing

23:57 Lewix: not the same thing

23:57 justin_smith: Number is an interface describing many numeric types

23:57 seq is an interface describing many ordered collections

23:57 julianleviston: :)

23:57 Lewix: let's just agree to disagree

23:58 julianleviston: um… no, justin_smith isn’t incorrect.

23:58 Lewix: ,(doc /)

23:58 clojurebot: "([x] [x y] [x y & more]); If no denominators are supplied, returns 1/numerator, else returns numerator divided by all of the denominators."

23:58 justin_smith: Lewix: can you describe to me how the disparate classes Double, Float, Rational etc. can all be Numbers, but somehow a list can't be a seq?

23:58 Lewix: much better than

23:58 ,(doc cons)

23:58 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

23:58 justin_smith: Lewix: in fact, the docs for seq are much more precise

23:58 / doesn't even mention numbers

23:58 Lewix: which doesnt tell you that in its seq it does not include list unless you provide nil as the second arg

23:58 julianleviston: Lewix: are you having a problem with the fact that one of the arguments is named seq there?

23:59 Lewix: justin_smith: right but its better in the sense that its not incorrect

23:59 justin_smith: Lewix: it explicitly says it returns a seq

23:59 Lewix: or partially incorrect

23:59 justin_smith: and it always does

23:59 julianleviston: Lewix: the docs for / don’t actually tell you the type it returns at all!

Logging service provided by n01se.net