#clojure log - Jan 31 2015

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

0:00 justin_smith: Mr0rris0: there is a gestalt effect where once you get past a certain threshold it all starts to synergize

0:01 (yes, I intentionally used ubscurantist phrasing for that :P)

0:01 rhg135: really, justin_smith? unperceivable fault in verbiage.

0:02 Mr0rris0: cool

0:03 i put nnscript on here earlier today, looks like it tells you when the day switches over

0:14 so how far along are you guys into this world/path/skill level

0:16 ianhedoesit: what do you mean?

0:16 Mr0rris0: yeah

0:16 ...

0:16 i dunno

0:16 the more advanced areas

0:17 its relative i guess

0:17 ive been on computers nearly all my life but nothing advanced or of much use

0:18 justin_smith: I'm level 100, still working on my elite suit of armor

0:18 Mr0rris0: lol

0:19 so going by that logic im at level .5

0:19 rhg135: i've been on certain chans where the programmers are lv. 0.001

0:19 don't be discouraged

0:19 Mr0rris0: yeah of course

0:20 justin_smith: go grind on some low level 4clojure problems, make a small project, you'll level up fast enough

0:20 Mr0rris0: ok

0:20 rhg135: clojure makes it easier to level up imo

0:22 Mr0rris0: im about 26 been on computers since about 5. its been easy to use them without learning an awefull lot

0:22 TEttinger: justin_smith is at level...

0:22 (identity justin_smith)

0:22 clojurebot?

0:22 clojurebot: clojurebot has a poetic soul

0:22 rhg135: lazybot is... lazy

0:22 oh

0:22 wrong bot lol

0:22 TEttinger: $karma justin_smith

0:22 right it is lazybot

0:22 justin_smith: oh wow, lazybot is out

0:22 TEttinger: and lazybot is missing

0:22 yep

0:23 Mr0rris0: compared to say my grandma or my mom, im an expert but compared to you guys im like them compared to me

0:23 rhg135: you'd be surprised

0:23 justin_smith: TEttinger: oh, were you going to compare karma to experience level?

0:23 Mr0rris0: i think you would lol

0:23 it takes alot to know what you dont know

0:23 TEttinger: justin_smith, yeah your helpful level is over 9000

0:23 rhg135: i havent written a single line in weeks cuz life

0:24 justin_smith: TEttinger: the secret is figuring out how to help other people is a great way to get better myself

0:24 TEttinger: yep!

0:24 but you have 4x my karma!

0:24 justin_smith: rhg135: starting around the new year I got super scatterbrained / distracted, had a hard time getting any real programming work done

0:25 only in the last week or so is the magic juice starting to flow again

0:25 it's weird how it happens

0:25 I think it might have been a sleep quality thing...

0:25 Mr0rris0: could be

0:25 rhg135: it is, justin_smith. but in my case it's completely by choice

0:25 Mr0rris0: if the infomercials are correct a lack of sleep causes toxins to build up

0:25 ianhedoesit: 30.2118 < rhg135> clojure makes it easier to level up imo

0:26 Mr0rris0: i saw that once late in the night

0:26 rhg135: i'm past the withdrawl i think

0:26 ianhedoesit: rhg135: I agree. I just started with Clojure in the last couple weeks and it's changed my life.

0:26 rhg135: definitely

0:26 Mr0rris0: your kidding, thats a testimonial right there

0:26 :D

0:26 justin_smith: clojure's design makes many of the right choices a lot easier to make

0:26 rhg135: it was 'what am i doing' later

0:26 Mr0rris0: ive lost like 20 lbs just reading about clojure

0:27 justin_smith: haha

0:27 "and I feel great!"

0:27 Mr0rris0: :D

0:27 rhg135: I used to write python, part of my code folder disgusts me

0:27 ianhedoesit: not only do the right choices become easier to make, but complex and difficult problems because much easier to understand, I think.

0:28 Mr0rris0: what helped you absorb it so fast ian?

0:28 knowing other languages already?

0:28 rhg135: it's completely natural

0:28 TEttinger: Maxazax, from the makers of Dexazam

0:28 ianhedoesit: well I'm not exactly a beginner with computers anyway (around a decade of programming), but Clojure is just so nice. I have a hard time putting it into words

0:28 TEttinger: I think I might still have the clojure prescription drug name generator

0:29 rhg135: it exists?

0:29 Mr0rris0: i found a old book in my loft in the barn about Basic the language

0:29 ianhedoesit: Clojure is exactly the opposite of everything I've done up until now and I feel like I see things clearly now

0:29 (the rain is gone)

0:29 Mr0rris0: ever tried about 1000mg of Fukitoll?

0:30 i cant do more than one

0:30 but i was a name generator champion back in the day

0:30 band name is whats popular in someplaces

0:30 those generators can be funny

0:34 TEttinger: heh, I'm proud of the heavily obfuscated/compressed cthulhu text generator

0:34 Mr0rris0: whats that cthulhu

0:34 TEttinger: unfortunately it needs lazybot to be effective.

0:34 (let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 500 w)"."])))

0:35 since clojurebot won't paste to refheap

0:35 ,(let[a #(apply str(flatten %))r repeatedly p partition N rand-nth n #(a(N(concat(repeat %"")(mapcat p[1 2 3]%&))))v #(n 0"aioeu""iaai")w(fn[](let[b(n 6"!.""""...")s[(n 0"STKNYPKLG""GlThShNyFt""ZvrCth")(r(N[1 2])#(do[(v)(n 9(map str"'-"(r 2 v)))(n 0(concat"lpstnkgx"[(N["h""gl""gr""nd"])(v)])"rlthggghtsltrkkhshng")]))]][b(if(seq b)[" "s][(n 3",")" "(.(a s)toLowerCase)])]))](re-find #"[A-Z].+"(a[(r 10 w)"."])))

0:35 clojurebot: "Thiathiagh... Gek."

0:35 justin_smith: that's a lot of truncation

0:36 TEttinger: that's with 10 words generated and starting at the first that meets certain criteria, IIRC

0:38 https://www.refheap.com/96713 there we go

0:40 I have a bad scifi alien name generator, in the vein of George Lucas https://www.refheap.com/96714

0:42 the one that started it all, a fake greek word generator https://www.refheap.com/96715

0:43 ianhedoesit: TEttinger: neat!

0:43 TEttinger: it's fun stuff

0:43 ianhedoesit: yeah

0:43 TEttinger: I also used it for an indie game idea generator

0:44 output below http://ideone.com/0MG8ED

0:45 ranging from "sports game where you destroy clothing" to "semi-autobiographical 4x game where you guide travelers through a house of horrors"

0:47 ianhedoesit: TEttinger: did you post that on reddit at some point?

0:48 justin_smith: "minimalist interactive-fiction/ball-and-paddle/strategy game where you rescue executives" haha

0:50 I would totally play "chesslike game where you command puppies" because I like puppies.

0:52 "gore-drenched dating-sim game where you gamble on Russian roulette" has a remarkable amount of coherency to it as a proposal

0:53 ianhedoesit: justin_smith: maybe someone will stumble upon those game ideas and implement them with play-clj!

1:01 krat0sprakhar: hi all, i spent some time working through this awesome tutorial of building a crud app with compojure..

1:02 http://www.jarrodctaylor.com/posts/Compojure-Address-Book-Part-1/

1:02 is there something like this for clojurescript

1:02 ?

1:02 justin_smith: krat0sprakhar: there is a clojurescript todo app example out there

1:02 krat0sprakhar: I would probably start with figwheel

1:02 krat0sprakhar: on that blog you mean?

1:03 justin_smith: http://swannodette.github.io/todomvc/labs/architecture-examples/om/

1:03 krat0sprakhar: i don't know react :(

1:03 i can cljs w/o om right?

1:03 justin_smith: the tutorial covers it, you don't use react directly

1:04 you don't need to use om, but that tutorial is a really good one

1:04 krat0sprakhar: so to use om / reagent dont you need to know react?

1:04 oh ok

1:04 justin_smith: https://github.com/swannodette/om/wiki/Basic-Tutorial

1:04 ianhedoesit: justin_smith: "An indie game where you haunt the world and it's WAY retro."

1:04 justin_smith: nice

1:05 krat0sprakhar: justin_smith: to be productive with om / reagent, does know need to learn react?

1:07 justin_smith: krat0sprakhar: I don't really think so. and om isn't super complex. even if you did need to learn it, react is just a js framework (better designed than many)

1:07 krat0sprakhar: ohk..

1:07 and you mentioned figwheel

1:07 where does that fit in?

1:08 justin_smith: yeah, if you were starting a project from scratch, that simplifies a lot of the clojure / clojurescript setup

1:08 so you can get a browser repl etc.

1:08 krat0sprakhar: so thats compojure for the backend and om on the frontend?

1:08 justin_smith: yeah

1:09 krat0sprakhar: if you dont mind me asking .. how does your dev env look like?

1:09 emacs?

1:09 clojurebot: emacs is "it has them, they are tricky to use"

1:10 justin_smith: krat0sprakhar: I use emacs, with inferior-lisp-mode to embed the repl

1:10 krat0sprakhar: ah ok.. great...

1:10 justin_smith: most people prefer cider though, but it has too many moving parts for me

1:10 Jaood: justin_smith: there is a inferior-clojure-mode

1:11 justin_smith: Jaood: oh, I had no idea

1:11 krat0sprakhar: i just connect vim to a running repl

1:11 justin_smith: krat0sprakhar: with fireplace.vim?

1:11 Jaood: justin_smith: https://github.com/clojure-emacs/inf-clojure

1:11 krat0sprakhar: justin_smith: yeah!

1:12 tim pope is just awesome.. :D

1:12 justin_smith: Jaood: next time I want to waste time setting up emacs I may try it

1:12 Jaood: krat0sprakhar: you should read about react on their website if you are going to play with om, at least to understand its concepts and approach to the virtual dom

1:12 justin_smith: Jaood: the reason I use inferior-lisp is it is super simple and just works

1:12 krat0sprakhar: Jaood: ah .. thought so..

1:13 Jaood: justin_smith: yeah, that its almost like inferior-lisp just a bit more clojureish

1:13 krat0sprakhar: i saw a few videos on egghead.. and wanted to ask.. if react is V in mvc

1:13 what are people using for m and c?

1:14 backbone?

1:14 clojurebot: backbone is awful

1:14 krat0sprakhar: lol :D

1:14 Jaood: justin_smith: you don't need the cider-nrepl dep

1:14 rhg135: model's been datascript and c custom for me

1:14 justin_smith: Jaood: to be honest seeing the author is enough to scare me away from it, but I may try it eventually.

1:15 krat0sprakhar: justin_smith: haha.. whats wrong with Batsov?

1:15 rhg135: datascript? whats that

1:16 rhg135: krat0sprakhar, an in mem db for cljs

1:16 justin_smith: he's the guy behind cider. in over a decade using emacs it's only been with cider that I have truly hated using emacs.

1:17 JustinusIII: cursiveclojure

1:17 justin_smith: yes, cursive is really good if I could give up my emacs habit :)

1:17 krat0sprakhar: or, if i could give up my vim bindings :P

1:17 also nightcode is pretty cool

1:18 justin_smith: doesn't idea have vi bindings? or are they just not good enough

1:18 JustinusIII: i think, you can set emacs keybinding in intellij

1:18 justin_smith: JustinusIII: I don't use emacs keybindings, I use evil mode inside emacs. I use emacs for the features not the UI.

1:20 krat0sprakhar: JustinusIII: any good tutorial for cursive.. i have some free time this weekend.. will try setting it up.. :D

1:20 cfleming: krat0sprakhar: Try IdeaVim for IntelliJ, it's not perfect but it's meant to be pretty good.

1:21 krat0sprakhar: It has some problems with the Cursive REPL editor unfortunately.

1:21 krat0sprakhar: cfleming: thanks, will give that a shot

1:21 Jaood: I would say lein repl is good enough and just use whatever editor you like

1:21 cfleming: krat0sprakhar: There aren't a lot of good tutorials, but the doc is reasonable: https://cursiveclojure.com/userguide/

1:21 krat0sprakhar: Ping me here or by email if you have questions

1:22 Jaood: lein repl with tmux actually :)

1:23 krat0sprakhar: cfleming: Oh, didnt realize you are Colin Fleming! I've seen your talk.. really liked it! :D

1:24 cfleming: krat0sprakhar: Thanks! Glad you liked it.

1:25 krat0sprakhar: tbaldridge also has some videos on getting started with Cursive here: https://tbaldridge.pivotshare.com/search/cursive/videos

1:25 tomjack: cursive is the only reason I have any hope that I may be able to use clojure in production before my next job

1:25 Jaood: if Hickey could get away with just the 'jave -cp clojure.jar clojure.main' repl at the beginning then we should too :P

1:26 cfleming: tomjack: How's that?

1:27 krat0sprakhar: cfleming: thanks for the link.. seems like a lot of great videos at a reasonable price

1:27 tomjack: if I'm trying to convince a coworker to try clojure and cursive doesn't exist, what am I supposed to say?

1:27 "use sublime and `lein repl`?"

1:28 cfleming: krat0sprakhar: Yeah, definitely. The first Cursive one is free though.

1:28 tomjack: "learn emacs"? "light table"?

1:28 krat0sprakhar: tomjack: yeah.. what so bad in that?

1:28 cfleming: tomjack: Yeah - I'm hopeful Cursive will help drive Clojure adoption.

1:28 Jaood: cfleming: are you going to release a paid version this year?

1:28 tomjack: "install cursive" is the only answer I can give with a straight face

1:28 justin_smith: tomjack: ed, and java -cp clojure.jar clojure.main

1:28 tomjack: :)

1:29 cfleming: justin_smith: Just poke the bytes in, man

1:29 justin_smith: I am gonna make ed.clj

1:29 cfleming: Jaood: Yes, I am

1:29 justin_smith: so you don't need to leave the repl

1:30 tomjack: cfleming: huh, do you make cursive? if so, thank you :)

1:30 cfleming: tomjack: I do indeed - you're welcome!

1:31 Jaood: cfleming: does cursive supports connecting to a remote repl?

1:31 cfleming: Jaood: Yep

1:32 Jaood: https://cursiveclojure.com/userguide/repl.html

1:32 tomjack: do you get locals printed inline in the code with 14?

1:32 cfleming: tomjack: Sadly, no, although I'm working on the debugger right now. Expression eval finally works, though, which is awesome.

1:32 tomjack: I just upgraded to 14 and installed cursive, but don't have it set up (working on a java project with .edn)

1:33 cfleming: tomjack: At least with Clojure, you do with Java obviously

1:33 tomjack: right

1:33 Jaood: cfleming: nice, are going to support boot or wait for the hype to settle and see if it catchs on?

1:33 cfleming: tomjack: Unfortunately to do that in Clojure means macroexpanding everything

1:34 Jaood: I'm definitely planning support, hopefully soon - I'd like to use it to build Cursive itself.

1:34 tomjack: I'll make a quixotic attempt to have a few or more buyers lined up when it's for sale

1:34 ah

1:34 cfleming: tomjack: That sounds like a fine objective to me :)

1:34 tomjack: I haven't actually tried riddley yet, but my hope is that it makes that kind of thing feasible

1:35 cfleming: tomjack: Cursive's new macroexpander is actually a hacked around riddley

1:35 tomjack: hacked around, as in you hacked around it?

1:36 cfleming: tomjack: Whether or not I can get that inline painting working for debugging, I can definitely use it for LightTable-style inline REPL eval

1:36 tomjack: Yeah https://github.com/cursiveclojure/riddley/blob/master/src/cursive/riddley.clj#L182-L249

1:37 tomjack: The Cursive macroexpander is actually pretty nice now - you can expand interactively but it still properly respects &env

1:38 tomjack: I didn't know there was a macroexpander. cool

1:38 jonathanj: is there a more idiomatic way of writing: (or (:a {:a nil}) 42)

1:38 cfleming: tomjack: It's new as of a couple of weeks ago

1:38 Jaood: cfleming: do you know if Hickey has tried cursive? :)

1:38 cfleming: tomjack: No doc yet, sadly, but should hopefully be fairly intuitive

1:38 justin_smith: jonathanj: not if {:a nil} is an expected possible value

1:39 tomjack: jonathanj: no

1:39 justin_smith: otherwise there is (:a {:b 1} 42)

1:39 cfleming: Jaood: Yeah, he's slowly moving over to it

1:39 Jaood: Once I have a non-nREPL REPL he'll be on it full time

1:39 tomjack: hah

1:40 cfleming: Jaood: Stuart Halloway is using it too

1:40 tomjack: what are some reasons someone might want a non-nREPL REPL?

1:40 Jaood: cfleming: that's pretty awesome

1:41 cfleming: tomjack: https://gist.github.com/levand/b1012bb7bdb5fcc6486f

1:41 (Luke Vanderhart also uses Cursive, and is bugging me for a non-nREPL REPL)

1:41 tomjack: Reduced complexity, basically - middleware is a bit of a nightmare

1:43 tomjack: now that I think about it, a lot of stuff about cider drives me nuts

1:44 e.g. error buffers as in the gist

1:46 cfleming: tomjack: https://gist.github.com/cursiveclojure/593ee7421e765d1b0dba (from the 0.1.44 release email)

1:46 Jaood: cfleming: why did you support nrepl first instead of just clojure.repl? or you building some repl from scratch?

1:53 cfleming: Jaood: actually, initially I had a clojure.repl REPL, but then I migrated to nREPL because basically everyone uses it, and it's easier to develop against.

1:53 Jaood: yeah, I can see how its easier for IDE integration

1:57 cfleming: No doubt

1:57 Still, a surprising number of people don't like the complexity and are moving back

1:59 krat0sprakhar: cfleming: how can i see inline doc and source

1:59 in cursive?

2:00 cfleming: krat0sprakhar: https://cursiveclojure.com/userguide/documentation.html

2:01 JustinusIII: krat0sprakhar: If you have used IntelliJ, Ctrl + Alt + A will do the magic for all actions

2:02 krat0sprakhar: you mean cmd + shift + A?

2:02 thanks cfleming

2:02 JustinusIII: yes, shift

2:02 cfleming: krat0sprakhar: On OSX, yeah

2:03 tomjack: hmm, macroexpansion doesn't seem to work for me

2:04 but, I'm still using emacs for clojure. I'll check it out more another day

2:04 cfleming: tomjack: You need a REPL running, and you need the current namespace loaded into the REPL

2:05 tomjack: yes, got that

2:05 cfleming: tomjack: Do you get an error or something?

2:06 tomjack: https://www.refheap.com/657f9d68355dc3c0d0f024fa8

2:06 that was when I tried inside the ns's file

2:07 I don't seem to get an error when trying inside the repl prompt

2:07 cfleming: tomjack: Interesting, thanks - I saw that once or twice but thought I had fixed it.

2:07 I think you'll have to do it from the ns's file

2:07 And you have the editor focused when doing this?

2:08 Which platform are you on?

2:08 tomjack: ah

2:08 when I used the menu bar, it worked

2:08 cfleming: tomjack: Weird

2:08 tomjack: but with, uh, that command which lets you type whatever, I got the error

2:08 I'm on ubuntu using xmonad

2:08 which does make intellij generally unhappy

2:09 cfleming: tomjack: Interesting, I wonder if in that case the command popup still has the focus - I should be able to reproduce that, thanks.

2:09 tomjack: Normally you'd have that bound to a key and run it from within the editor - that should work, as will the menu

2:10 tomjack: I'm planning to highlight the form you just expanded too, since it can be a little confusing to see what happened

2:11 tomjack: hmm

2:12 this is when I try to step forward https://www.refheap.com/aaa4a8bc0c1ab0cbe67da84a8

2:12 yeah, bound a key

2:13 hmm, but only on my macro

2:13 cfleming: tomjack: Hmm, do you have the caret within the macro form, or after it?

2:14 tomjack: also, https://www.refheap.com/2161643929b2c26a5ce4701fb

2:14 ("error during macroexpansion")

2:14 not sure if that's you or me, but my form works when eval'd

2:14 s/during/performing/

2:15 cfleming: tomjack: Oh, it'll be me - not sure what's going on there, though

2:15 tomjack: (the form expands to a keyword)

2:15 cfleming: Can you check the log (Help->Show log in <whatever it is on Linux>) and paste the full stacktrace?

2:15 tomjack: Ah, interesting - I didn't know you could do that.

2:16 tomjack: That'll be the problem, then - the expander adds metadata to all the forms it expands so I know what it did.

2:17 ,(do (defmacro x [] :test) (x))

2:17 clojurebot: :test

2:17 cfleming: Ok, I'll fix that

2:17 tomjack: can do, lemme try to figure out where to start

2:17 do I need to worry about sensitive content in the logs? :/

2:18 cfleming: tomjack: No worries, I can reproduce now that I know the macro expands to a keyword - that's definitely the problem.

2:18 tomjack: I haven't gotten it to expand my macro yet, even when it doesn't expand to a keyword

2:18 cfleming: Can you expand a defn or something like that?

2:18 tomjack: one thing is that sometimes the forms I pass to my macro contain non-standard usages of ~

2:18 yeah, core stuff has worked

2:18 (and it's really cool, btw)

2:19 cfleming: Thanks - I think it'll be good once the kinks are worked out

2:19 I'd expected more feedback on it, but I haven't heard anything

2:19 So this is really helpful, thanks

2:20 So on your macro, you always get that NPE?

2:21 tomjack: segment of idea.log https://www.refheap.com/6734006ed9455289a5819d595

2:21 cfleming: Actually, looking at the code, I have a few places where I assume that the expansion is a list

2:21 tomjack: ah

2:21 for me it's always either a keyword or a vector

2:21 keyword threw the metadata problem, vector seems to do nothing I guess

2:21 cfleming: tomjack: That would explain it - I'll fix that for the next build

2:22 tomjack: nice, luckily I picked a strange macro :)

2:22 (or unluckily)

2:22 cfleming: Heh, no doubt

2:23 Yeah, this was actually really hard to do well. It's amazingly tricky to correctly correlate elements in the editor with elements in the expansion

2:23 All those NPEs I see in your log will be the non-list problem, I think

2:24 Two different incarnations of it

2:29 tomjack: Ok, I think I can fix that reasonably easily - hopefully I'll get that fix in the next drop. Thanks for all the help!

2:29 tomjack: random feature request: tidy qualified keywords. sorry, now I'll stop.

2:29 but relatedly, I once made a patch to EdnReader which provided a way to configure substitutions for keyword namespaces while reading

2:30 my eventual tentative conclusion was that the problem of bearable well-qualified Named things should be solved by the tools, not the reader

2:32 'namespace folding' I guess

2:35 cfleming: tomjack: Yeah, that should be easy - I already do it for symbols

2:36 tomjack: Cursive already automatically shortens keywords in the actual editor when completing, renaming and so forth

2:38 tomjack: And don't stop, feature requests are always good

2:38 tomjack: hmm, I just want it in edn as well

2:38 cfleming: How would that work?

2:38 tomjack: unclear :)

2:38 would need some config I guess

2:39 cfleming: I mean, how can you have macros in EDN?

2:39 tomjack: I mean, I want to use well-qualified keywords (and reader literals, maybe symbols) in .edn files

2:39 but not have my eyes bleed

2:40 not sure how to make that happen, but I vaguely suspect it should be in the editor

2:40 cfleming: tomjack: Ah, sorry, I thought we were still talking about macros - I see. I can easily code-fold them in Cursive.

2:41 But I'd have to know which prefixes to fold.

2:41 tomjack: I hadn't realized qualified keywords complete in .clj, though, that is pretty sweet

2:41 yeah

2:42 cfleming: You can find usages on keywords, too - try Ctrl-Alt-F7 on a keyword

2:43 That finds usages of the keyword anywhere in your project, and also local bindings destructured from then using :keys

2:44 You can rename keywords too, which will also rename destructured bindings

2:45 So for EDN, would you want to configure the prefixes per file, or per project?

2:45 tomjack: yeah, I dunno

2:45 it's tricky

2:45 cfleming: I could automatically take them from prefixes you've used in code, as long as they're consistent

2:45 tomjack: should the config go in the editor too? or might we adopt a convention which describes aliases in the edn itself?

2:46 cfleming: Sure, if there's a convention I can use it.

2:46 One gotcha with code folding is that it will mess up your formatting in some cases

2:46 Since formatting doesn't take the foldings into account

2:46 tomjack: (describing aliases in the edn seems tricky because edn (rough Rich quote) "has object-at-a-time, not document, semantics")

2:47 cfleming: Well, have a think about how you'd like it to work and let me know, it seems like a generally useful feature

2:48 tomjack: it's been a recurring thought for quite some time, unlikely to find a satisfying answer

2:49 (the feature request was just keywords inside macroexpansion, which seems more straightforward design-wise)

2:50 cfleming: Yeah, that one's trivial

2:53 tomjack: I guess the most satisfying answer right now is "put your edn in .clj files"

2:53 ..and then you're stuck with data_readers.clj. humm

2:54 cfleming: Yeah, and Cursive will try to interpret your EDN as code, which will drive you bonkers

2:55 But I'm assuming that per-file, you would want a consistent mapping of namespaces to prefixes, right?

2:55 tomjack: (well, it would sortof be code, I mean like this: https://github.com/Datomic/codeq/blob/master/src/datomic/codeq/core.clj#L22 )

2:57 cfleming: So there, you'd want e.g. :db.cardinality/one displayed as ::card/one?

2:58 tomjack: well, I don't know even that

2:59 cfleming: That makes fulfilling your desires a little tricky :)

3:00 It's tough, I actually have a similar problem at the moment - I need to get some declarations from code out into EDN

3:00 tomjack: yes, I meant to stick a paragraph break between cursive and "how to use reverse-DNS without going insane"

3:02 cfleming: And currently it's fairly eye-bleeding. I'm considering having an :impl-ns some.long.ns and :aliases [[some.other.ns :as ns1] [yet.another.ns :as ns2]], and then interpreting that myself after reading the EDN in

3:02 tomjack: then what goes in the EDN with that out-of-band bit in place?

3:03 :ns2/foo

3:03 ?

3:03 cfleming: Yeah - they're symbols in my case, so foo -> some.long.ns/foo and ns1/bar -> some.other.ns/bar

3:04 tomjack: the only problem I have with that approach (besides the cost of walking the data an extra time, which probably won't often matter) is that it won't necessarily work inside arbitrary reader literals

3:04 but then I'm not even really sure if that's a problem

3:05 motivating examples include datomic's db/id and db/fn

3:05 cfleming: Yeah, fortunately in my case the data is a) broken up into small bits, so I'll just read the whole file in and work on it in memory, and b) is reasonably simple, i.e. I have no need of reader literals

3:07 This is a mini-IoC container for Cursive extensions

3:09 tomjack: extensions as in user supplied clj code?

3:12 cfleming: Yeah

3:12 tomjack: I was wondering about that today, glad to hear it's planned

3:13 cfleming: I'm gradually working towards that, at first so that users can support symbol resolution for macros in libs they develop or use, and then later for more things

3:13 tomjack: huh

3:13 I have been wondering how I to approach a dev env for a toy language

3:14 someday, maybe, as editor extensions, with the toy language code directly in the clj

3:16 cfleming: I actually have users who are interested in adding support to Cursive for internal DSLs, so that they can then ship Cursive to their users to edit the DSL

3:16 For financial modelling

3:16 tomjack: I'd also wondered if someday I may be able to spawn custom repls, in the same spirit as cljs stuff

3:16 ah, interesting

3:17 cfleming: Custom REPLs is trickier, I'm actually about to abstract my REPL code to support more REPL types, not sure if/when I'd expose that to users though

3:17 tomjack: I know a financial modeller who'd be very interested to hear that

3:17 though they use emacs

3:17 cfleming: Something like Pixie would be a good usecase for it though

3:18 Mr0rris0: why

3:18 tomjack: hadn't seen pixie

3:18 cfleming: tomjack: Get him to drop me a mail if he's interested

3:19 Plenty of people have come over to Cursive from Emacs, although a lot of people still use both I think, depending on what they're doing

3:20 tomjack: "hint to the JIT that certain values are constants, that certain functions are pure, etc. This can all be done from inside RPython..."

3:21 Mr0rris0: someday im gonna understand all of this i swear to god almighty

3:21 tomjack: why should we have to hint? pixie + purity seems interesting

3:23 cfleming: tomjack: IIRC there's a monad-style effects control system being considered

3:24 tomjack: inspired by eclj?

3:24 (which I really hope there will be a talk about)

3:25 (because I don't understand it at all)

3:26 cfleming: Yeah, I haven't spent the time trying to understand that yet

3:27 tomjack: I wish the link wasn't to oleg, I never understand oleg

3:29 cfleming: Yeah, there's no-one like him to make you feel dumb

3:41 blockzombie: I'm trying to use zippers with xml. using clojure.xml and clojure.zip seems to work but I thought I could make nice path query style forms... is this an external lib? clojure.data.xml ?

3:41 (-> z zip/right zip/right zip/node) etc. works well

3:42 but I want (-> z :tagname :tagname ...)

8:16 imanc: if I add (:gen-class) to an (ns) and an associated :main myproj.core in the project.clj I get: $ lein run

8:16 Exception in thread "main" java.lang.RuntimeException: No such var: clojure.core

8:16 any ideas why?

8:18 oh wow, newb error!

8:22 sashton_: is there a way to find out how many items are in an async chan? I'm trying to add some monitoring to my app, and would like to know the progress of some work.

8:22 or is there a better way?

8:45 luxbock: I'd like to be able to evaluate local bindings in my editor inside a let-form when I code

8:47 so my plan is to create a function that takes a quoted Clojure let-form as its argument, extracts the bindings, runs it through clojure.core/destructuring, and then separate the gensym'd locals from the local bindings I'm after

8:51 then eval the gensym'd symbol->value pairs, and replace each occurance of a gensym'd symbols inside the local-bindings of the destructuring result

8:53 actually I'm not sure if this makes a lot of sense to even myself yet

9:04 Mr0rris0: sounds interesting lux

9:04 your ahead of me atleast, im not sure what any of that is yet

9:04 hellofunk: luxbock: i don't think you can count the number of pending items on a channel, but you could of course update a count every time your put! and decrement the count every time you take!

9:05 luxbock: hellofunk: hmm? I'm not using channels/core.async at all

9:05 hellofunk: luxbock: i'm sorry i meant that reply for sashton_

9:05 justin_smith: sashton_: not unless you make your own custom chan impl

9:05 luxbock: ah

9:06 I want to be able to do two things actually

9:06 justin_smith: sashton_: that is, you would need a custom chan impl for querying the count of the chan

9:07 luxbock: take a let-form, and simplify so that all the value-side of the expressions are evaluated, and return that

9:07 so that I can do that inside my editor to see what each local-binding is evaluating to

9:07 hellofunk: luxbock: what editor are you using?

9:07 luxbock: Emacs

9:08 hellofunk: luxbock: doesn't the emacs tool for evalue the form at point do what you need? it's a part of cider, but of course you'd have to be using cider to use it

9:08 luxbock: sending code from Emacs to Clojure and back is easy enough with cider

9:08 hellofunk: *evaluate

9:09 luxbock: hellofunk: that would get me the evaluation result for the body of the let-form

9:09 justin_smith: hellofunk: there's form at point, but not for getting an arbitrary value of a local

9:10 hellofunk: hm, i'm confused. can't you evaluate any form, not just a top-level let, but anything with cider? i think i can. I can type (let [x (+ 1 1)]..) and just see the evaluation of 1 + 1 if I want

9:11 justin_smith: hellofunk: in (let [a 0 b (inc a) c (+ b b)]) can you get the value of c?

9:11 hellofunk: i was just thinking that after i typed it. i haven't tried. perhaps i should this moment

9:12 luxbock: I'm toying around with ideas for trying to reduce the REPL-based feedback loop of writing code -> seeing results even further

9:14 I already have a function that expands a function-call with the body of the function getting called, which I find amazingly useful when you can use that in-place in my editor

9:14 hellofunk: i see what you are after now and no you can't do what justin_smith proposed with cider. interestingly, this seems like a frightening feature: Invoke clojure.walk/macroexpand-all on the form at point and display the result in a macroexpansion buffer.

9:15 luxbock: I think if I can combine this with the let-related stuff I was talking about then it'd be incredibly powerful

9:15 hellofunk: lol when i first read that i thought it said display the macroexpand-all in the mini-buffer! lol

9:15 lodin: luxbock: I've been sketching on the same thing.

9:15 hellofunk: that would be one heck of a mini buffer output

9:15 luxbock: lodin: cool, do you have anything out there yet?

9:15 hellofunk: luxbock: what you describe sounds like how the light table tools work

9:15 lodin: luxbock: Nope.

9:16 luxbock: hellofunk: I think expanding in-place is much better since then you can manipulate that code even further

9:16 * hellofunk gives thumbs up

9:16 luxbock: hellofunk: with these ideas my work flow is transitioning from the REPL to the *cider-scratch* buffer

9:17 hellofunk: luxbock: i've never seen a cider-scratch buffer before

9:18 luxbock: I end up with tons of code in there, which helps me think about the problem further

9:18 the Clojure compiler in my head is not strong enough where I could just lie in my hammock and solve problems like Rich Hickey :)

9:19 *cider-scratch* is basically just a dummy Clojure-buffer that evaluates to the currently active ns

9:19 it has some extra features as well but I don't use those much, so it's much the same as just creating your own dummy-buffer

9:21 Glenjamin: has anyone used https://github.com/chlorinejs/chlorine ?

9:24 sashton_: hellofunk: yeah, a thought i had was to inc and dec an agent if there wasn't a built-in way to get the pending count

9:24 hellofunk: luxbock: i'm pretty sure the hammock idea is about having NO compiler in front of you, and no computer for that matter

9:25 if you are properly practising the Hammock, then to others you should appear to be asleep, in Rich's words.

9:27 man i think i'm asleep, talking about sleep. luxbock just saw your clause "in my head"

9:27 * hellofunk takes a break from the machine for a few moments

9:41 matt`: I'm trying to do a running total, but it doesn't seem to be totalling :D Can anyone spot my doofus mistake? http://pastebin.com/BPB6U3T2

9:42 justin_smith: matt`: dotimes is calculating things that do not change total

9:42 (+ total x) does not increase total

9:42 it just calculates an addition (that dotimes then throws away)

9:42 matt`: Bugger

9:43 justin_smith: matt`: I think you want (apply + (repeatedly number-of-rolls #(die-roll sides)))

9:43 that does some number of die rolls, and adds them all up

9:43 matt`: :-O

9:44 Wow thanks, I'm off to look up 'repeatedly' too, I came across that on clojuredocs but it didn't seem appropriate

9:45 Thanks again for your help

9:45 justin_smith: np

9:47 matt`: That worked btw justin_smith

9:48 justin_smith: oh, good

9:52 Glenjamin: anyone got a favourite hickey talk which isn't on this list? http://thechangelog.com/rich-hickeys-greatest-hits/

9:58 matt`: Is a # in front of a function a way to access the object instad of the returned value that the object would produce?

10:00 fairuz: matt`: do you mean something like #(...) ?

10:01 matt`: yes, that's right

10:01 justin_smith: matt`: #() is a shortcut for fn

10:01 fairuz: it's the same thing as (fn [args] ...)

10:01 justin_smith: ,'#(+ % %)

10:01 clojurebot: (fn* [p1__25#] (+ p1__25# p1__25#))

10:01 lodin: matt: #(...) is a function, it's sugar for (fn [] ...) in this case.

10:02 matt`: that's great, thanks, just trying to get my head around it

10:02 justin_smith: matt`: do you know how (fn [] ...) is used?

10:03 lodin: matt: You could also write (map die-roll (repeat sides)) to get an infinite list of die-rolls. Then you use (take) to get the number of rolls you want.

10:03 matt`: justin_smith: It's an anonymous (lambda) function right?

10:04 justin_smith: yes

10:04 like defn but without creating a global definition

10:04 matt`: I take it an infinite amount of rolls like that wouldn't run the function infinitely?

10:04 justin_smith: matt`: no, because of laziness

10:05 matt`: I've heard that term quite a few times now - it's lazy because it doesn't acutally do it until it's required?

10:05 justin_smith: ,(apply + (take 3 (map #(inc (rand-int %)) (repeat 6))))

10:05 clojurebot: 10

10:05 justin_smith: ,(apply + (map #(inc (rand-int %)) (repeat 3 6))))

10:05 clojurebot: 8

10:06 lodin: ,(take 3 (repeat 6))

10:06 clojurebot: (6 6 6)

10:06 lodin: Oops.

10:06 :-)

10:06 justin_smith: ,(repeat 3 6)

10:06 clojurebot: (6 6 6)

10:06 lodin: justin_smith: Just showing the concept.

10:06 justin_smith: ,(apply + (repeatedly 3 #(inc (rand-int 6))))

10:06 clojurebot: 8

10:06 justin_smith: right

10:07 wow, terrible rolls!

10:07 this would be like the worst d&d character ever

10:07 matt`: I'm having a little trouble tbh, I come from C - I can see the awesome power of functional programming but it's pretty alien to me

10:07 justin_smith: ,(reduce + (repeatedly 3 #(inc (rand-int 6))))

10:07 clojurebot: 13

10:07 matt`: Lol! That's what this is for

10:07 Kinda

10:07 I'm writing some functions to help me run a dungeonworld game

10:08 justin_smith: here's 4d6, drop the lowest:

10:08 ,(reduce + (rest (sort (repeatedly 3 #(inc (rand-int 6))))))

10:08 clojurebot: 9

10:08 justin_smith: oh wait

10:08 matt`: I did one of those in lisp, I'll post my code

10:08 justin_smith: ,(reduce + (rest (sort (repeatedly 4 #(inc (rand-int 6))))))

10:08 clojurebot: 13

10:09 matt`: (defun stat ()

10:09 ;; Generate 4 d6 results, discard the lowest

10:09 (apply #'+ (rest (sort (list (d 6) (d 6) (d 6) (d 6)) #'<))))

10:09 lodin: matt: Use let binding generously and it becomes easier to grasp.

10:09 matt`: Tnx lodin

10:09 justin_smith: matt`: that is like literally the code for the last thing I printed

10:09 if d is inc rand-int

10:10 matt`: Hah, maybe I am getting functional programming after all :)

10:10 justin_smith: matt`: the only real difference is that you literally spell out every call to d, and I use repeatedly to specify how many times it is done

10:12 matt`: I'm going through your code examples, Clojure can be elegant

10:13 lodin: matt: Also, as soon as possible, understand how to use (-> ...) and (->> ...).

10:16 justin_smith: ,(->> #(inc (rand-int 6)) (repeatedly 4) rest (apply +))

10:16 clojurebot: 8

10:17 lodin: It's nicer when it's aligned vertically. :-)

10:18 matt`: lodin: I've been looking at ->, isn't it just for readability?

10:18 justin_smith: matt`: -> / ->> make some code much clearer, yes

10:18 lodin: matt: Sure.

10:18 justin_smith: and make certain errors much less likely

10:19 lodin: matt: But it's a good alternative to using let bindings where you just repeat the name on the next line.

10:19 matt`: Right. Gotcha.

10:19 Much tidier

10:21 lodin: I particularly like (-> ...) over nesting the functions since the name and the rest of the arguments don't get spread apart (in contrast to (->> ...)).

10:22 justin_smith: lodin: ->> works with collection functions, -> works for functions on associatives

10:22 matt`: I've heard nesting functions is frowned upon, I can see why.

10:26 lodin: justin_smith: -> would be more useful with reduce if three argument reduce took the initial value first. Coincidentally, usually have a reduce' that does just that. :-)

10:26 justin_smith: lodin: it's intentional that functions on collections all take the collection as the last arg

10:27 lodin: justin_smith: reduce works well with ->>, but not ->. I'm only talking about the initial value (which sometimes is associative).

10:31 Glenjamin: reduce is fairly low level, if i was doing a reduce within a threading form i think i'd extract into a named function

10:37 lodin: Glenjamin: The same would probably apply for map.

10:37 Glenjamin: map is generally a bit higher level than reduce

10:37 it depends what you're doing i guess

10:37 (reduce +) is pretty straightforward

10:38 lodin: Glenjamin: Yeah. In my use cases it's more like map. I have a set of stuff I want to reduce into another object through a function, and you'd just end up creating plural versions of the function.

10:38 Like map would be move into a plural version.

10:39 Glenjamin: i'm not sure what you mean by that

10:48 lodin: Glenjamin: If you have (-> x (foo a) (foo b) (foo c)) you can rewrite that into a reduce, (reduce foo x [a b c]).

10:48 Glenjamin: the threading form is much clearer there imo

10:49 lodin: Glenjamin: except something you can't use the threading form, because you really have (let [ys ...] (reduce foo x ys))

10:50 And want you also had initially was a threading form doing other stuff to x, and want to get the reduce in there.

10:51 s/want/what/

10:52 So now you either create a foo-all function so you can have that in your threading form, or write (#(reduce foo % ys)).

10:53 But that second option is not good if you happened to have a #() form where foo is.

10:53 So you might rewrite using partial is possible, or spell out the fn form.

10:54 Or you use your own reduce' which takes the initial value first, and you're done. :-)

10:54 Glenjamin: can you give a concrete example? i'm still not really following

10:55 lodin: s/is poss/if poss/

10:56 Glenjamin. OK, hold on.

10:56 Glenjamin: thanks

11:15 crack_user: hello guys

11:15 arav93: Has the android app for clojure repl been updated?

11:16 crack_user: I am looking at reagent and I constantly see this code "(-> % .-target .-value)" in :on-field, but I don't find in any place what does it means

11:17 someone can explain or show where is it in documentation?

11:17 clojurebot: Huh?

11:18 crack_user: for example " :on-change #(reset! value (-> % .-target .-value))"

11:19 lodin: Glenjamin: http://pastebin.com/yhFK5Lyf

11:20 Glenjamin: crack_user: http://clojuredocs.org/clojure.core/-%3E

11:20 that bit of code is roughly equivalent to "e.target.value" in javascript

11:21 crack_user: humm, I already know about the threads functions, my doubts is more about the .- and % syntax

11:22 TMA: crack_user: #(... % ...) is equivalent to (fn [%] (... % ...))

11:22 lodin: crack_user: % is the first argument in the function created by #(...).

11:23 crack_user: I get it

11:24 lodin: Glenjamin: Does that example make it clearer?

11:24 Glenjamin: lodin: yes, it does

11:24 i'd probably say define (defn add-edges [g es] (reduce #(apply dep/depend %1 %2) g es)) because `add-edge` isn't actually that useful

11:26 although i'm not sure the threaded version is worth using at all

11:26 lodin: Glenjamin: I knew you would say that, so assume that there's more going on in the thread.

11:26 Glenjamin: unless you're combining the top version with the bottom version

11:26 lodin: :-)

11:26 Glenjamin: yeah, i guessed there might be

11:26 lodin: Glenjamin: For instance, first you might want to remove some edges.

11:26 Glenjamin: but yeah, add-edge doesn't seem bit enough to extract

11:27 *big enough

11:27 but add-edges (with the reduce inside) is

11:27 clojurebot: Excuse me?

11:27 lodin: Glenjamin: I just added it because it get's tiresome to write apply all the time.

11:27 Glenjamin: right, but you're only using apply because you have a pair

11:27 and you only have a pair because you have a list of pairs

11:27 if you only had one, you'd just use dep/depend

11:27 lodin: Glenjamin: So assume that the API had add-edge, or that depend takes a pair.

11:29 But you see, the reduce form is very similar to a map form.

11:29 Glenjamin: right, but reduce is more of a black box

11:30 you know what's going on with a map, a reduce could do anything - which i think is why i find it a bit "weird" in a thread like that

11:30 i dunno, might just be me

11:36 imanc: is there a decent step through debugger for clojure? (I'm using vim)

11:36 profil: Does it exist a lisp which is similiar to clojure but is compiled to machine code just like common lisp?

11:52 or is it possible to compile clojure so that it is not dynamic?

12:06 r4vi: profil: pixie is the clojure inspired lisp that compiles to native code

12:08 well kind of; it generates it's own native vm

12:14 profil: r4vi: ah, nice.. To bad its not entirely native. I was looking for something to write small apps like a window manager without having to touch common lisp or scheme

12:15 r4vi: ah so you want a no deps clojure

12:15 I seem to remember something that cross compiled clojure -> scheme -> native

12:16 profil: not sure how mature but here it is https://github.com/takeoutweight/clojure-scheme

12:17 profil: I guess I could learn scheme, I like the minimalism, but I have read that its hard to write portable scheme programs..

12:27 imanc: ,(apply (fn [x & more] (prn x more)) [1 2 3 4 5])

12:27 clojurebot: 1 (2 3 4 5)\n

12:28 imanc: why??

12:28 why is rest passed back into the fn?

12:29 and given it does that, how does (apply str [1 2 3 4 5]) work?

12:30 Glenjamin: (apply str [1 2 3]) === (str 1 2 3)

12:31 Graawrimatiger: hi ! I'm a little baffled: how come (flatten (vector <list of maps>) is almost instant, while (flatten <list of maps>) seems linear ? Both yield same result, it seems

12:31 imanc: oh man

12:31 n00b mistakes

12:31 profil: ,((fn [x & more] (prn x more)) 1 2 3 4 5)

12:31 clojurebot: 1 (2 3 4 5)\n

12:31 profil: imanc: ^

12:32 Glenjamin: Graawrimatiger: how are you measuring them?

12:32 also

12:32 ~flatten

12:32 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.

12:32 imanc: OK, this now makes perfect sense .. thanks!

12:34 Graawrimatiger: Glenjamin: I measure them with the built-in "time" function. Also, (mapcat identity) or (concat) instead of flatten both yield same results : "slow" if I use it directly on a list of maps, really quick if I apply `vector` first

12:35 Glenjamin: $source flatten

12:35 bah

12:35 where's lazybot :(

12:35 profil: ,(source flatten)

12:35 clojurebot: Source not found\n

12:35 profil: :(

12:37 Glenjamin: i can't see any obvious reason for that in the source Graawrimatiger, maybe try using criterium (a more detailed benchmarking tool) to compare them

12:38 flatten seems to use tree-seq, which just uses lazy-seq and mapcat

12:38 Graawrimatiger: hum

12:39 maybe it has something to do with lists being linked-lists while vectors are arrays ?

12:39 Glenjamin: that shouldn't really make much of a difference for a straightforward linear walk like that

12:39 Graawrimatiger: ha

12:43 all in all, I'm not missing some hidden trap there, right ? Vector will maintain the order of the list if i'm correct, so both results should always be identical ?

12:43 Glenjamin: well, lists can be lazy

12:43 or, more accurately, vectors can only be eager

12:43 Graawrimatiger: I'm not using laziness here

12:45 Glenjamin: can you post some code samples?

12:46 Graawrimatiger: just re-tried something, seems I was mistaken : mapcat identity doesn't flatten the list inside the vector (it only removes the vector, which seems logical) ; if I want the same results, I have to use flatten on the vector

12:48 (i'm uploading some code samples)

12:53 Glenjamin: here is the original map I use for the tests (some instaparse AST in enlive format) : http://pastebin.com/E5d5Q72q

12:54 Glenjamin: it's possible that some part of the procedure is doing lazy work at a different point, maybe try using the profiler to find out if it's important to you

12:55 csd_`: In the context of accumArray, what would the symbolic representation of the accumulation function (\/), where this represents an upside down carrot, mean?

12:56 caret

12:57 Graawrimatiger: O_o i don't get it : if I store this list in a var, for exemple "mylist", (flatten mylist) and (flatten (vector mylist)) take the exact same time (really quick); if I do the same comparison while using the 'inline' result of the list (ie obtaining the result from function calls and flatten it directly from it), there is this big speed difference ><

12:57 (well it's not really important, I was just a bit puzzled by this)

13:00 lodin: Graawrimatiger: How would a flattening for perform? (for [xs xss, x xs] x)

13:01 justin_smith: which is identical to nested mapcats btw

13:01 Graawrimatiger: lodin: sorry, I don't quite grasp how to flatten with for... ?

13:02 lodin: Sorry, gotta go.

13:03 justin_smith: ,(for [xs [{:a 0 :b 1 :c 2} {:d 3 :e 4}] x xs] x)

13:03 clojurebot: ([:c 2] [:b 1] [:a 0] [:e 4] [:d 3])

13:03 Graawrimatiger: oh

13:03 justin_smith: ,(for [xss [{:a 0 :b 1 :c 2} {:d 3 :e 4}] xs xss x xs] x)

13:03 clojurebot: (:c 2 :b 1 :a ...)

13:05 Graawrimatiger: it performs "quickly", not "badly linearly" (^^")

13:06 justin_smith: Graawrimatiger: were you consuming the individual results when benchmarking? because a vector would definitely be slower if not

13:06 compared to something potentially lazy

13:07 Graawrimatiger: justin_smith: I benchmarked while saving (time (def <name> (<several calls to get the original list I linked on pastebin>)))

13:09 justin_smith: ,(def n (flatten (repeatedly range)))

13:09 clojurebot: #'sandbox/n

13:09 justin_smith: Graawrimatiger: n is infinite

13:09 Graawrimatiger: it wasn't evaluated at all

13:09 doing the def did no work

13:10 so of course that is instant

13:10 this is why one should use criterium for benchmarking, it makes these mistakes less likely

13:11 Graawrimatiger_: (sorry, disconnected)

13:11 justin_smith: Graawrimatiger: did you see the def of n?

13:11 Graawrimatiger_: (felt like I wasn't clear so (time (def x (flatten original_list))) ;=> 90msecs, and (time (def y (flatten (vector original_list)))) ;=> 0.38msecs ; at the end, (= x y) ;=> true

13:12 justin_smith: ,(def n (map println (flatten (repeatedly range))))

13:12 clojurebot: #'sandbox/n

13:12 justin_smith: it returns instantly

13:12 nothing prints

13:12 no work was done

13:12 it should have printed a series of numbers up to the maximum possible integer, over and over

13:12 (if it had done anything)

13:12 timing a def of a flatten is not a fair coparison

13:12 *comparison

13:13 Graawrimatiger_: oh

13:13 justin_smith: flatten is lazy

13:13 it doesn't calculate anything until you consume the output

13:13 Glenjamin: ahah

13:14 Graawrimatiger_: but then again, after doing the defs above, (time x) and (time y) both take the same time (almost nothing). Wouldn't one of them be way longer if it needed to be realized ?

13:14 justin_smith: Graawrimatiger_: this is why you shouldn't use time to benchmark things btw, there is a lib called criterium that makes these mistakes less likely

13:14 Graawrimatiger_: (time x) does not force the result

13:14 Graawrimatiger_: oh

13:15 justin_smith: Graawrimatiger_: you need to consume the contents, or use something like "doall" or "dorun" on it

13:15 Graawrimatiger_: so all in all, there's no "magical way" to flatten a list of lists in O(1), I guess... ?

13:15 justin_smith: absolutely not

13:15 Graawrimatiger_: :/

13:15 whomp: so is let just a concise way of doing a bunch of defs?

13:15 justin_smith: you have multiple lists, the lower bound is O(n) for the number of lists

13:16 whomp: that was all that got tested, was creating the defs

13:16 l3dx: in compojure, is it possible to map just a subset of the routes with a given middleware?

13:16 justin_smith: l3dx: yes, a middleware is just a function that takes a handler and returns a new handler

13:16 whomp: justin_smith, ?

13:16 justin_smith: l3dx: use the middleware on the routes you want wrapped

13:17 whomp: all that got timed was running def - the contents of hte things def'd were not forced, so at least in the case of a list input are not evaluated

13:17 whomp: the laziness of flatten would mean that the work would get done later as the elements are accessed

13:18 (which was not timed)

13:18 whomp: justin_smith, so def is lazy, let is not?

13:18 justin_smith: whomp: no, that's not what I am saying at all

13:18 whomp: lol maybe i'll just read some more

13:18 Graawrimatiger_: justin_smith: okay; so if I have this structure ( a_list a_list a_list ...) from doing a map (of an instaparse parser function) on a list of strings, there's no way to optimize something in between to avoid the "long" flatten at the end ?

13:18 justin_smith: whomp: if you do (time (def n (something lazy))) all you have timed is the amount of time it takes to run def

13:19 whomp: justin_smith, ok ty

13:19 justin_smith: Graawrimatiger_: mapcat the instaparse instead of map / flatten

13:19 Glenjamin: flatten/concat/mapcat are "optimised" in the sense that they are all lazy

13:19 Graawrimatiger_: justin_smith: hum, whomp asked you something else entirely; I think your last answers were for me... ?

13:19 justin_smith: Graawrimatiger_: no

13:19 Graawrimatiger_: oh, nevermind so ^^"

13:19 justin_smith: Graawrimatiger_: except the one I directed at you

13:20 hellofunk: l3dx: one easy way to group those routes you want effected into a single defroutes, then use the middleware on that group. you can combine this resulting handler with other route groups you've defined w/o middleware into one big handler.

13:20 justin_smith: (inc hellofunk)

13:20 that's a much better way of saying what I was trying to say

13:20 l3dx: cool. thanks! I'll give it a try :)

13:21 hellofunk: l3dx: here's an example: https://github.com/hellofunk/hellofunk-lein-template/blob/master/resources/leiningen/new/hellofunk/src/h/examples.clj

13:22 Graawrimatiger_: justin_smith: oh well, mapcating the instaparse yields the desired result in only one step, thanks ! it's also linear time (time (mapcat...), no defs) so I guess that's the best I can get like you said

13:22 thanks a lot :)

13:22 justin_smith: Graawrimatiger_: (time (mapcat ...)) does not force the laziness either!

13:23 you need to consume the result, or no work is done

13:23 the easy way is doall / dorun

13:23 (time (dorun (mapcat ...)))

13:23 Glenjamin: although note that neither recurse deeply

13:23 justin_smith: (time (mapcat f coll)) won't even call f once

13:24 Graawrimatiger_: justin_smith: hm (time (dorun (mapcat ...))) and (time (mapcat ...)) both take the same time

13:24 justin_smith: Graawrimatiger_: that's surprising

13:24 maybe I am wrong in this case...

13:24 Glenjamin: how many items are in this list?

13:24 justin_smith: ,(time (range))

13:24 d'oh

13:25 clojurebot: "Elapsed time: 0.047057 msecs"\n(0 1 2 3 4 ...)

13:25 justin_smith: AHA!

13:25 Glenjamin: aha?

13:25 justin_smith: yeah, that call to (range) was "infinite"

13:25 Glenjamin: ,(doc time)

13:25 clojurebot: "([expr]); Evaluates expr and prints the time it took. Returns the value of expr."

13:25 Graawrimatiger_: justin_smith: I'm using the 'lein-ultra' plugin to run a repl, which changes a lot of things (only visual though), could it be that one feature is interfering here ?

13:25 justin_smith: Glenjamin: so if you don't consume the result inside the time form, you don't force any laziness

13:25 Glenjamin: yeah

13:26 justin_smith: Graawrimatiger_: no

13:26 Graawrimatiger_: you can't accurately calculate the time a lazy thing took without explicitly consuming its results (recursively if it has nested laziness)

13:26 flatten and mapcat are both lazy

13:27 criterium is a benchmarking library that makes that mistake less likely though

13:27 (and gives much more accurate timing results)

13:27 hellofunk: justin_smith: if using time at the REPL, i would think it would try to realize the whole sequence since REPL printouts are a form of consumption

13:28 justin_smith: hellofunk: unless you have print-length limited as clojurebot does, sure

13:28 Graawrimatiger_: oooh

13:29 justin_smith: hellofunk: also time will not end up timing the realization

13:29 hellofunk: because the forcing of the lazy result will happen after time returns the lazy object

13:29 hellofunk: so the whole thing gets realized, but your timing is fictional

13:29 hellofunk: oh intersting.

13:30 justin_smith: here is a rather intersting tidbit i came across once, on the subject of time: https://gist.github.com/hellofunk/7d424d173125b5dc9640

13:30 justin_smith: hellofunk: just think about the order of execution: you time the generation of the lazy-seq (no work done), that lazy seq is returned, time calculates its result and prints it, your repl consumes and prints the lazy seq, and then *finally*, after the time is calculated, the seq is forced

13:31 hellofunk: justin_smith: that makes sense

13:31 Graawrimatiger_: justin_smith: oh, that would explain the whole thing I guess

13:31 going to try criterion then

13:31 justin_smith: *criterium

13:32 Graawrimatiger_: woops

13:32 yeah, meant that x)

13:32 justin_smith: also, as I mentioned before, doall or dorun would have helped too (and are still useful sometimes in criterium)

13:32 Graawrimatiger_: justin_smith: yeah but since I have the same results with or without doall/dorun, something is still missing

13:32 imanc: ,(take 3 (repeat (/ (+ (rand-int 255) 255) 2))))

13:32 clojurebot: (147 147 147)

13:33 imanc: I'm assuming that (repeat... is causing the output of rand-int to be repeated, rather than calling the evaluating the function on each iteratoin

13:34 l3dx: hellofunk: worked perfectly!

13:34 Glenjamin: ,(doc repeatedly)

13:34 clojurebot: "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

13:35 hellofunk: l3dx: glad to hear it!

13:38 imanc: ahh repeatedly did it - thanks Glenjamin

13:39 justin_smith: Graawrimatiger_: so you did (time (dorun (mapcat f ...)))

13:39 Graawrimatiger_: justin_smith: yes

14:43 justin_smith: ,(time (map #(*' % % % % % % %) (range)))

14:43 clojurebot: "Elapsed time: 0.148038 msecs"\n(0 1 128 2187 16384 ...)

14:43 justin_smith: ,(time (doall (map #(*' % % % % % % %) (range))))

14:43 clojurebot: eval service is offline

14:44 justin_smith: ,(time (doall (map #(*' % % % % % % %) (range 100))))

14:44 clojurebot: "Elapsed time: 0.754953 msecs"\n(0 1 128 2187 16384 ...)

14:44 tcrayford____: justin_smith: reminder that in compiling that code, cleaxjure is writing a class file to disk, so it'd likely be faster in a real server

14:44 justin_smith: tcrayford____: I'm showing the difference in time taken

14:45 tcrayford____: related to the excange with Graawrimatiger_ above

14:45 tcrayford____: oh

14:45 * tcrayford____ scrolls up

15:03 hellofunk: ,(doall (time (map #(*' % % % % % % %) (range 100))))

15:04 clojurebot: "Elapsed time: 0.103278 msecs"\n(0 1 128 2187 16384 ...)

15:06 hellofunk: ,(time (doall (time (map #(*' % % % % % % %) (range 100)))))

15:06 clojurebot: "Elapsed time: 0.105691 msecs"\n"Elapsed time: 1.933527 msecs"\n(0 1 128 2187 16384 ...)

15:33 whomp: how is it that (take 5 (map identity (range)) doesn't go on forever?

15:34 tcrayford____: whomp: laziness

15:34 whomp: ah i see now, tcrayford____, ty

15:34 tcrayford____: whomp: did that completely answer it? I was writing a longer answer (that one was super glib)

15:35 whomp: yeah cuz it reminded me of lazy seqs lol, i'm re-learning the language

15:35 tcrayford____: haha ok then :)

15:35 happy I could help

15:44 patrkris: hi folks. I am trying to add customer encoders to cheshire, but do I need to do it in every namespace I use cheshire? can it be added globally somehow for my whole library?

15:44 tcrayford____: patrkris: adding an encoder is a global change

15:44 so you can put them all in a namespace or something, and as long as that's required somewhere

15:44 then you're good

15:44 patrkris: tcrayford____: I believe I tried that, but let me just try again

15:45 tcrayford____: patrkris: for sure

15:48 patrkris: tcrayford____: seems you were right. must've done something stupid before :) thanks

15:52 tcrayford____: patrkris: dope! Glad I could help out :)

15:52 patrkris: I've been running like that in production for like, 2 years haha

15:56 michaelr525: hi

15:58 dweave: Anyone have trouble getting stack trace not to show on every error in cider? It’s extremely useless

15:59 only seems to do so for some errors

16:01 AeroNotix: dweave: specific exceptions? Repeatable?

16:01 Which version of CIDER?

16:01 also, #clojure-emacs

16:01 dweave: doesn’t seem repeatable trying to figure that out though.

16:01 version 0.8.2

16:02 AeroNotix: dweave: perhaps the exception buffer is getting hidden

16:02 dweave: i have this warning: WARNING: CIDER's version (0.8.2-snapshot) does not match cider-nrepl's version (0.8.1)

16:02 tcrayford____: dweave: check your JVM doesn't have -XX:+OmitStackTraceOnFastThrow as well

16:02 dweave: AeroNotix: I want the error buffer to get hidden

16:03 tcrayford____ how do i check that

16:03 AeroNotix: dweave: I'm gonna say that you don't have the above setting

16:03 unless you've put it there manually.

16:03 dweave: what setting AeroNotix

16:03 I have this: (setq cider-show-error-buffer nil)

16:03 AeroNotix: dweave: what do you think that setting does? :)

16:04 tcrayford____: AeroNotix: that setting is on by default on the jvm ;)

16:04 michaelr525: will be starting a fresh new web app. thinking of starting with chestnut (figwheel, om, weasel, ring) and then adding system (component) and sente. anything else/instead you'd recommend?

16:04 dweave: “Configure whether the error buffer with stacktraces should be automatically shown on error:”

16:04 AeroNotix: tcrayford____: aha, ok then.

16:05 tcrayford____: AeroNotix: it only affects specific exceptions, and I don't think it's the problem here though

16:05 AeroNotix: right

16:05 tcrayford____: seems like #clojure-emacs kinda thing to me

16:05 dweave: i’m confused which setting are we talking about

16:06 i’ll try clojure-emacs thanks

16:13 michaelr525: will be starting a fresh new web app. thinking of starting with chestnut (figwheel, om, weasel, ring) and then adding system (component) and sente. anything else/instead you'd recommend?

16:15 tcrayford____: michaelr525: depends on what your app's doing really

16:16 michaelr525: oh and friend and liberator :)

16:17 tcrayford____: ui, crud, authentication, ElasticSearch as datastore

16:18 tomjack: I can't afford the modeline cost of #clojure-emacs :)

16:19 tcrayford____: michaelr525: I'm probably a bit more conservative than you here - I tend to only add libraries as I *need* them for things

16:20 michaelr525: tcrayford____: all web applications need this common base: ui, client-server communication, security, web services, data layer

16:20 on top of that you'd want good architecture and some development sugar, thus component, figwheel

16:21 tcrayford____: so this list is only the base stuff which 100% will be used

16:23 tcrayford____: michaelr525: yea. I tend to start with a much smaller set of things at the start (but then again my current app has ~80 direct dependencies)

16:25 raspasov: michaelr525: ElasticSearch as datastore?

16:25 michaelr525: tcrayford____: xcactly :)

16:26 tcrayford____: echoing raspasov there, I don't trust elasticsearch as far as I can throw it

16:26 michaelr525: raspasov: the app will be around querying stuff from ES so we though of using it as the operational DB as well for app CRUD

16:27 don't trust it in what sense?

16:27 raspasov: only put data in ES that you're 100% sure you're ok to completely lose

16:27 tcrayford____: ^^

16:27 it loses data

16:27 michaelr525: oh really

16:27 interesting

16:27 raspasov: https://aphyr.com/posts/317-call-me-maybe-elasticsearch

16:27 read this

16:27 michaelr525: ok, thanks

16:27 tcrayford____: note that they've done a *lot* of work since that post

16:28 but our ES cluster at work (which is only for logstash) still throws away it's data every few weeks (without us telling it to)

16:28 raspasov: ^^ lol

16:29 michaelr525: heh

16:29 tcrayford____: are you on the latest version?

16:29 raspasov: yea I was running ES in prod on just two nodes, not good experience

16:29 tcrayford____: michaelr525: yeah, we were

16:29 (I've been on vacation for 3 weeks, so things might have changed)

16:30 raspasov: maybe another re-write happened since then? :D

16:30 tcrayford____: haha :(

16:31 (https://github.com/elasticsearch/elasticsearch/issues/3145#issuecomment-27455667 is still open haha)

16:31 raspasov: my advice is: use MySQL or PostgreSQL if your data is within a few TB, and use Riak or Dynamo if it's bigger than that, you can use ES to load data from those sources for searching

16:32 but never as a primary store of data

16:32 tcrayford____: raspasov: agree with that

16:32 raspasov: I made that mistake once and not doing it again lol

16:34 someone needs to re-write ES in Clojure, it will prob be 10x less code and 10x less bugs lol

16:37 michaelr525`: hmm.. '

16:37 have I missed anything?

16:38 tcrayford____: http://clojure-log.n01se.net/

16:38 michaelr525`: 10x

16:56 imanc: if a function relies on some global var that isn't passed in explicitly, is the function then impure / tainted?

16:56 tcrayford____: imanc: guess so, on some levels

16:56 imanc: though like, if your function calls `map`, it's relying on a var ;)

16:57 imanc: yeh

16:57 tcrayford____: generally if it calls another pure function, imo that's ok

16:57 raspasov: if that var is never modified, in a way, no (I guess lol)

16:57 Bronsa: the solution is easy

16:57 tcrayford____: raspasov: right, but if you reload it at the repl you've modified it ;)

16:57 Bronsa: (let [map map] (defn my-f [..] ..))

16:58 raspasov: well but if you reload with the same value, you haven't? :)

16:58 imanc: hm, i've been messing with quil and doing some animation stuff to get acquainted with clojure. But most functions need to rely on a global vars for screen width/height, and it seems clunky to pass these in each time. Obviuosly these are constants, but I'm wondering if this then taints the function

16:58 Bronsa: now my-f won't be affected by var redef :P

16:59 tcrayford____: imanc: I'd typically pass those in always

16:59 it gets a bit more verbose, but you win in being able to test/maintain/etc

16:59 raspasov: yea generally I agree ^^

16:59 imanc: tcrayford____: yeh, I've been wondernig about how to write unit tests for these also

16:59 makes sense

17:00 Bronsa: imanc: just pass in an opts arg to all your functions and use a map {:width .. :height ..}

17:00 danlentz: thanks to those that pointed out a potential race condition in my monotonic timestamp generator last night. I rewrote it based on the comments recieved: https://gist.github.com/danlentz/301a0f056ffd9c6605a9

17:01 imanc: @Bronsa cool, that sounds like a solution.

17:01 Bronsa: danlentz: why are you using MapEntry?

17:02 danlentz: i wanted a single cons cell

17:02 ie a pair

17:02 tcrayford____: seems better to just deftype or defrecord it

17:02 (if that was for perf)

17:02 Bronsa: danlentz: (defrecord Pair [k v])

17:02 danlentz: i believe records are slower than types, no?

17:03 Bronsa: no

17:03 tcrayford____: depends how much it matters

17:03 danlentz: it matters

17:03 Bronsa: danlentz: they are not slower

17:03 tcrayford____: Bronsa: yeah they are ;)

17:03 danlentz: i need a two slot tuple, i dont need a record with a map interace

17:03 raspasov: I believe deftype is more barebones than defrecord

17:03 tcrayford____: danlentz: in which case (deftype Pair [k v])

17:03 danlentz: im pretty sure deftype

17:04 Bronsa: tcrayford____: no they are not. they just implement more abstractions

17:04 danlentz: but i dont quite understand the reasoning why a mapentry would not be as fast

17:04 as a custom deftype

17:04 tcrayford____: danlentz: that one isn't a perf arg

17:04 just that it seems "odd" or "weird"

17:04 danlentz: oh

17:04 yeah, yes weird

17:05 im a common lisper I yearn for a cons cell :)

17:05 tcrayford____: Bronsa: records implement IMeta, so they inherit at least an additional function call on every `assoc` for example

17:05 Bronsa: danlentz: also there are key and val functions that work on mapentry anyway, no need to use .key/.val directly

17:05 tcrayford____: Bronsa: that's also very slightly slower ;)

17:05 Bronsa: tcrayford____: moot argument, deftypes don't support assoc at all out of the box

17:06 raspasov: I've done something like this https://gist.github.com/raspasov/c3a45a669b74de717050

17:06 (this will never return the same number)

17:06 danlentz: not thread safe

17:06 is it?

17:07 tcrayford____: it is

17:07 `synchronized`

17:07 but uh, that involves a lock vs a CAS like your one does, so it might be slower

17:07 raspasov: yea I haven't benchmarked, but locks on longs are pretty damn fast I think

17:08 Bronsa: tcrayford____: all I'm arguing is that it makes no sense to say "records are slower than types", they share the same implementation. the way one uses records might be slower than the way one uses types (i.e. (:foo x) vs (.foo x)) but you can still use the .foo syntax with records if you need that

17:08 tcrayford____: Bronsa: roughly agreed haha. If you start digging, they are *for sure* slower, even if you use the same syntax, but in most applications that ain't gonna matter so much

17:08 Bronsa: and keyword lookup on records is really fast anyway

17:09 danlentz: raspasov: i forked that gist tho thanks

17:09 raspasov: danlentz: if you care for the utmost performance you should benchmark the atom's CAS vs (locking) macro in Clojure or some Java solution like I posted

17:09 tcrayford____: (you're starting to look at things like the extra memory allocation because defrecords store two extra pointers compared to deftype etc at that point though)

17:10 raspasov: danlentz: np, cheers :)

17:10 tcrayford____: Bronsa: just depends how deep you're gonna dig, and at that point you should prolly be using C or C++ or Rust or something without a GC

17:10 danlentz: well, there is some value is trying to be more idiomatic clojure rather than ‘locking’ or dropping to java

17:10 raspasov: yea def

17:10 Bronsa: tcrayford____: whatever, I don't believe that instantiating two extra fields null will make any difference

17:11 raspasov: this is pretty much the only bit of Java I've used lol

17:11 tcrayford____: Bronsa: I don't trust myself to benchmark at that level of performance ;)

17:11 danlentz: i just finished a weight balanced binary tree which was very very very sensitive to allocation

17:11 i tried clj-tuple

17:11 object array

17:11 and deftype

17:11 raspasov: danlentz: what are you working on - some sort of storage/database?

17:11 danlentz: so, deftype and clj-tuple were about equivalent

17:12 tcrayford____: danlentz: note that clj-tuple had a new release yesterday evening that rewrites it in java

17:12 (and zach says it's noticeably faster)

17:12 danlentz: but, with deftype i was able to declare the last element as ^long, and i saved considerably,

17:12 tcrayford____: (not for any class/deftype reasons though - the code's better)

17:12 danlentz: ah

17:12 tcrayford____: but yea, the type hint is a huge win there

17:12 danlentz: probably due to my nagging and griping :)

17:13 tcrayford____: nah, I was griping at him haha ;)

17:13 danlentz: http://github.com/danlentz/clj-wbtree

17:13 im still working on it but its within 10% of sorted-set

17:13 tcrayford____: danlentz: post your benchmarks in that repo

17:13 raspasov: cool!

17:14 tcrayford____: (and yea - looks dope)

17:14 danlentz: wbtree only typically will beat rbtree for very large collections, and also I have an extra cost because I have a “universal” ordering relation

17:14 ive really been learning a lot its been a really good exercise

17:15 tcrayford____: danlentz: how are you measuring performance?

17:15 danlentz: well, specifically for building trees

17:16 i dont have rigorous benchmarks, that is just a very rough estimation

17:17 going to play with criterium

17:17 justin_smith: danlentz: criterium is not hard to use

17:17 tcrayford____: would highly recommend it :)

17:17 it's as easy as calling `time` from core

17:17 just like, the numbers are kinda real

17:17 danlentz: but first I had to get it at least in the ballpark — up until now it was like 20x slower than sorted set so my priority was on big fixes not high confidence measurement

17:17 raspasov: yea use Criterium https://github.com/hugoduncan/criterium it's very nice

17:17 tcrayford____: danlentz: that's mostly what I was asking there. Measuring performance on the JVM even somewhat accurately is near impossible ;)

17:18 justin_smith: guys, I think we need at least six people to tell danlentz to use criterium, if anyone else can pitch in

17:18 tcrayford____: things I've seen: run the same benchmark twice in the same JVM: second time is 4000x slower (note: *exactly* the same JVM)

17:18 danlentz: hey anybody know of a good library i can use?

17:18 :)

17:18 tcrayford____: (that was specific to that benchmark)

17:18 raspasov: justin_smith: yes I think so :D

17:20 tcrayford____: (lesson there: if you use criterium, you need a new JVM per benchmark, or the numbers will lie)

17:20 danlentz: the monotonic timestamp is for my clj-uuid library so I needed that to be really fast so I can generate v1 uuid’s on multiple cores really fast

17:20 http://github.com/danlentz/clj-uuid

17:21 or reasonably fast anyway.

17:27 justin_smith: haha, a var called +tick-resolution+ - you really do miss common lisp

17:27 imanc: is there a decent debugger for clojure? Or do people generally resort to printing stuff to stdout? :)

17:27 justin_smith: imanc: best experience will likely be cursive

17:28 imanc: ahh

17:28 googling

17:28 cfleming: imanc: https://cursiveclojure.com/userguide/

17:28 justin_smith: cursive is an editor plugin for doing clojure in the intellij idea ide

17:29 cfleming: imanc: I've just been working on the debugger recently, it works pretty well now. More improvements in the next release (in a week or so probably)

17:29 imanc: cool - i use pycharm (intellij) so it should be easy to use

17:29 cfleming: Yeah, it should all be familiar

17:30 Cursive can't plug into PyCharm unfortunately, although it might be able to in the future

17:30 imanc: presumably i can instlal a vanilla intellij and use that?

17:31 cfleming: Yes

17:31 Works fine with the community edition

17:31 imanc: awesome

17:32 do you guys generally use midje for writing tests?

17:32 justin_smith: clojure.test

17:33 cfleming: What justin_smith said

17:33 Go for simple, IMO

17:33 imanc: koay

17:36 glosoli: Hey. when I am in cider repl mode, I seem to get company mode completion every time I type some text, yet it doesn't seem to work that way when I am in cider mode, any ideas how to get the same thing in cider mode ?

17:37 danlentz: justin_smith: i do love CL deeply but Clojure is my adopted home and I like it here

17:37 justin_smith: danlentz: :)

17:38 danlentz: the tooling is still a little painful

17:38 justin_smith: it's true, there are some rough edges compared to a decent cl

17:38 danlentz: everyone I encourage you to go to gittip and donate a few dollars a month to bhatsov

17:39 the better the tooling, the more viable our language becomes to a wider marketplace

17:39 justin_smith: danlentz: my experience has been better since I stopped using stuff by bbatsov actually

17:39 danlentz: he does cider, no?

17:39 justin_smith: right

17:39 o0rebelious0o: I'm fairly new to using clojure having used it briefly over summer for a (pretty basic) DSL implementation but it's been really nice to look at and play with

17:39 I hear #clojure is a pretty nice community unlike some other language IRCs

17:40 danlentz: i believe cider can overtake slime because it is architecturally more sound

17:40 but it has a way to go

17:40 sobel: o0rebelious0o: in my experience, it's comparable with #postgresql which is about as good as it gets on IRC

17:41 danlentz: in particular, although I never particularly loved the slime debugger, it was really really helpful as compared to clojure/cider’s error reporting

17:41 tomjack: when I switched to cider some months back, I thought I was very late wrt trends

17:41 cfleming: Sorry, I missed this earlier: danlentz, you should be using criterium

17:42 danlentz: oh, criterium. right. totally forgot.

17:42 imanc: o0rebelious0o: yeh, I have noticed that. People are cool on here.

17:42 justin_smith: haha

17:42 danlentz: no i use cider

17:42 o0rebelious0o: sobel: can't say I've ever used it

17:42 danlentz: but for CL i used slime obviously

17:42 slime for clojure was not very good by comparison

17:43 justin_smith: danlentz: clojure breakpoint / step debugging is possible, but I think cursive is the only environment that really has it conveniently available.

17:43 danlentz: i never used it because it was mutually exclusive with my common-lisp slime installation. That actually prevented me from playing with clojure for a very long time

17:43 cursive, huh?

17:43 thats the intellij plugin?

17:44 hmm

17:44 people seem to like intellij

17:44 sobel: o0rebelious0o: if you end up needing postgresql support, you might just be glad to know there's a great channel for it

17:44 cfleming: danlentz: Yeah, IntelliJ is really pretty amazing. Of course, it's a full-blown IDE which isn't to everyone's taste.

17:45 danlentz: cider has made dramatic improvement though. I think there has been a lot of time up front establishing a good framework

17:45 cfleming: danlentz: But JetBrains are amazing when it comes to dev tooling

17:45 danlentz: abandoning legacy slime-derived approach

17:45 sobel: JetBrains have been doing great tooling for a very long time

17:45 their tools make Eclipse look like amateur hour tbh

17:46 danlentz: I used it for about 4-5 months during a scala gig over the summer. I don’t think emacs is even usable doing scala and I tried. Its awful

17:46 sobel: and i'm no eclipse hater

17:46 rcbevans: I've used intellij for java and python with pycharm, intrigued by c-lion too

17:46 cfleming: sobel: I hear Eclipse has come a long way in recent years, but I was traumatised by early versions - I haven't touched it for years

17:46 rcbevans: and android studio is based on it and that seems to work pretty great

17:46 imanc: pycharm is nice- though I felt like a quitter ditching vim to use it

17:47 cfleming: imanc: There's nothing wrong with moving to pain-free tools

17:47 rcbevans: lars vogel seems to be doing a lot of work to push the eclipse foundation forward

17:48 I think they realised they were a bit long in the tooth in comparison

17:48 intellij seemed to not suffer from some of the sore spots I had with eclipse

17:49 tbaldridge: I often wonder if Eclipse just suffers from the fact that it's not a commercial product

17:50 cfleming: tbaldridge: That, and it also really helps that all the JetBrains products are made by one company with a consistent vision - it's all really coherent.

17:50 rcbevans: cfleming: +1

17:51 cfleming: rcbevans: We use inc round here :)

17:51 (inc rcbevans)

17:53 rcbevans: inc cfleming ah sorry, I'm pretty new to IRC, don't really know what I'm doing ^^

17:53 (inc cfleming) ah sorry, I'm pretty new to IRC, don't really know what I'm doing ^^

17:53 sveri: phpstorm lead me to intellij, pretty awesome too

17:53 rcbevans: oh wow, failing hard here

17:53 cfleming: Hehe, no worries, it's more of an in-joke than anything

17:53 Bronsa: rcbevans: no the bot is dead :(

17:53 cfleming: Bronsa: That too

17:55 pandeiro: funny i just opened intellij for the firstish time

17:55 Bronsa: cfleming: don't worry I'll write a note on paper, you'll get your inc

17:55 pandeiro: totally overwhelmed

17:55 imanc: sveri: yeh, I've used phpstorm also - hope to never use php again though. Causes outbreak of hives.

17:55 rcbevans: on clojure related stuff :), where is a good place to get started? I've been doing some project euler questions by myself, but I have no idea if the clojure I'm writing is really even good clojure for what i'm doing

17:56 are there any good resources to go through, I have the joy of clojure and O'Reilly clojure cookbook

17:56 i've seen 4clojure mentioned some places too

17:56 imanc: rcbevans: I'm reading the JoC atm, and messing around with a nice gfx library called quil.

17:57 raspasov: rcbevans: I personally like http://clojurekoans.com/

17:57 justin_smith: rcbevans: for automated exercises, 4clojure and the clojure koans are decent

17:57 raspasov: rcbevans: also Aphyr's blog "Clojure from the ground up" series are excellent https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome

17:58 just go through the blog and find "clojure from the ground up" - there's a bunch

17:58 rcbevans: that looks ace

17:58 hadn't seen clojurekoans

17:58 I'll def give that a look

17:59 I was on the train friday and wanted to download an offline version of 4clojure, cloned a couple of 4clojure-offline type repos

17:59 neither seemed to work all that well though

17:59 justin_smith: rcbevans: 4clojure itself is open source

17:59 though you wouldn't likely want to run it on your phone

18:00 rcbevans: well I was on a laptop

18:00 does it have a repl type version? or just run a web stack and local copy of the site?

18:00 justin_smith: rcbevans: it's literally the code that runs the site

18:01 rcbevans: orly

18:01 probs shoul have looked at that

18:01 ah "Setup instructions for running locally"

18:02 *facepalm*

18:03 andyf: Anyone have recommendations for books or web sites that teaches about various aspects of web server development like: what is a session? where is it typically stored in a server and why? what is carried across a TCP socket that indicates the session, how secure is it, and why? between the level of a TCP socket and the web server, what do different web server containers/platforms do between them, and what are the relative

18:03 advantages of each?

18:03 justin_smith: andyf: all of that could be cleared up by reading the code for ring

18:03 andyf: good question regarding an actual book though, that would be interesting to see

18:05 imanc: andyf: maybe reading the source of some frameworks would answer those questions. E.g. sessions identifiers are stored in cookies, which are sent back to the browser on each request. The session data is then stored in whatever backend storage is configured - a file, a database, etc.

18:05 andyf: So ring has one 'standard' method it uses for representing sessions, and it is good enough for most purposes? Or it allows multiple different implentations depending upon unique needs someone may have?

18:06 justin_smith: andyf: wrap-session is a middleware that attaches a hash-map to the request, under the key :session

18:07 andyf: imanc: Sessions tend to last over one to several dozen requests, typically? Is it important to store them in persistent storage on the server because they can last even longer? Or because of load balancing over different physical servers for different requests from the same user?

18:07 justin_smith: andyf: it can use configurable storage backends (I believe there is a protocol you can implement?) but the defaults are cookie or in-memory and in either case you can have an optional encryption key for the cookie

18:08 andyf: the default in-memory session storage is an atom (for ring's wrap-session) and maps from an identifier in the user's cookie to the data

18:08 andyf: the code to wrap-session, and the various things it calls, are relatively straightforward

18:08 imanc: andyf: if you're load balancing then you need to remove any state from the appers. Often a medium such a memcached or redis, or a plain database running on external servers is used to persist session information

18:09 sveri: imanc: hehe and a lot of other things :D

18:09 imanc: * from the app servers

18:09 sveri: yeh indeed

18:10 andyf: Are there web servers that don't bother storing sessions in persistent storage, keeping it only in memory?

18:10 justin_smith: andyf: sure, for things like login state

18:11 andyf: not onerous to require a user to log in again if the server restarts and you only have one server

18:11 favetelinguis: are there any tools i can use to read a XML file and generate clojure code?

18:11 justin_smith: andyf: typically the "log in"

18:11 will map some data from the db into app memory

18:11 which keeps further request times lower

18:12 favetelinguis: generate code, or clojure data structures? clojure.xml is good for the latter

18:13 favetelinguis: justin_smith: no i want to genereta arbitrary code

18:13 justin_smith: favetelinguis: you'd have to design your own DSL for that I think.

18:13 but I would use clojure.xml to implement it

18:14 cfleming: Bronsa: Awesome, thanks! I need all I can get.

18:15 Xack: hm, currently modifying a leiningen template, wondering how i can test it without uploading to clojars

18:15 justin_smith: Xack: lein install

18:16 Xack: ahhh, thanks!

18:17 Bronsa: cfleming: I too have been robbed of my internet points because of lazybot being offline in the past, nobody deserves this.

18:17 justin_smith: clearly my improvements were not sufficient

18:17 we need a distributed lazy-bot array

18:17 with redundant laziness in waiting

18:18 Bronsa: justin_smith: you failed us

18:18 justin_smith: (dec justin_smith)

18:20 imanc: installing oracle java on ubuntu is a PITA

18:20 justin_smith: imanc: really?

18:20 (not in my experience)

18:21 imanc: any particular difficulty?

18:21 imanc: maybe i'm doing it wrong - I had to remove all trace of openjdk, download it into /usr/bin/java or something, and I'm now adding a PATH to porfile

18:21 justin_smith: imanc: that is like multiple layers of wrong

18:22 imanc: yeh?

18:22 justin_smith: imanc: there is a directory called /etc/alternatives

18:22 imanc: I'd hoped to be able to do apt-get install oraclejava :)

18:22 justin_smith: it's not free, so that's not an option

18:22 imanc: so what do I need to do with etc/alternatives?

18:22 justin_smith: imanc: it contains symlinks. If you replace the symlink called java, with one pointing to the java you want, that becomes the default java command

18:22 cfleming: Bronsa: There's no justice in this world. From what I can tell, it's all justin_smith's fault.

18:23 imanc: ahh OK

18:23 so it overrides anything else

18:23 justin_smith: imanc: /etc/alternatives/ allows multiple versions of anything to be installed, but it establishes which one is the default

18:23 danlentz: justin_smith: the correct answer was definitely use a custom type because i can declare both slots primitive

18:23 justin_smith: imanc: yeah, I have 5 jvms installed right now

18:23 danlentz: oh, cool

18:23 danlentz: (deftype Pair [^short k ^long v])

18:23 imanc: OK, that sounds cool

18:24 danlentz: https://gist.github.com/danlentz/301a0f056ffd9c6605a9

18:24 justin_smith: imanc: there is also an "update-alternatives" command, but all that does is automate the process of replacing the symlinks in /etc/alternatives to one pointing to the locations you want

18:24 danlentz: fwiw

18:24 imanc: how does that work with your JAVA_HOME and JRE_HOME env variables?

18:25 justin_smith: imanc: tbh I never set those, never have

18:25 Bronsa: danlentz: FWIW the type-hint at line 32 on the argvec is totally useless

18:25 danlentz: also deftype defines a ->Pair function, no need for `pair`

18:25 imanc: i guess if java is in a public path, then there's no ned

18:26 danlentz: ok, wait

18:26 justin_smith: imanc: if you do "ls -l /usr/bin/java" you'll see it is a symlink to "/etc/alternatives/java"

18:26 danlentz: the ^Pair on the argvec avoids reflection on .k, .v no?

18:26 justin_smith: imanc: by replacing "/etc/alternatives/java" you decide which java gets run

18:27 Bronsa: danlentz: the type hint on current-state does, the one on [^Pair current-state] is useless

18:27 justin_smith: (and as I mentioned before, /etc/alternatives/java is also a symlink)

18:28 cfleming: Bronsa: type hints are exclusively used for removing reflection in interop, right? There are no other subtle uses of them?

18:28 danlentz: the ^Pair on the return val of the fn does not avoids reflection when adding the .k and .v of the result of swap?

18:28 cfleming: Bronsa: I'm hoping to be able to mark unused hints in Cursive

18:28 Bronsa: danlentz: type hints on return value of fn only work in the context of defn

18:29 danlentz: ok b/c new-state is Pair anyway

18:29 Bronsa: oh.

18:30 good tip.

18:30 Bronsa: cfleming: eh, uhm they also affect method matching + primitive usage

18:30 cfleming: Bronsa: Oh, right, the primitive hints work differently.

18:31 Bronsa: I hate type hints.

18:31 cfleming: I hate metadata in general.

18:31 Bronsa: that too

18:31 and its weird evaluation semantics

18:31 cfleming: Especially during macroexpansion

18:39 imanc: how do you install cursive?

18:42 justin_smith: imanc: https://cursiveclojure.com/userguide/

18:45 andyf: imanc: It is perfectly possible to install Oracle Java in your home dir on Ubuntu, and not worry about /etc/alternatives, /usr/bin, etc. But to do that you will need to set JAVA_HOME env variable, and add ${JAVA_HOME}/bin to your PATH.

18:46 imanc: andyf: presumably $JAVA_HOME/jre/bin is also needed?

18:46 as JRE_HOME

18:46 andyf: I've never needed to do that.

18:46 imanc: ahh - i followed some instuctions and did that

18:47 andyf: imanc: I guess I should say that when I've installed Oracle Java on Ubuntu this way, I was only using it from the command line, not from a web browser.

18:51 imanc: In the Oracle Java 1.8.0 JDK I have installed, jre/bin is a strict subset of what is in bin

19:00 lodin: I just realized that (defprotocol P (m [x])) (defrecord R [] Object (m [x] "m") P) (m (R.)) works.

19:01 justin_smith: lodin: is there a misplaced paren in that?

19:02 wait, why does P happen after the protocol impl for m?

19:02 lodin: justin_smith: Exactly.

19:03 justin_smith: lodin that makes my brain cry

19:03 lodin: You can put the interfaces anywhere, as long as the first things in an interface.

19:03 s/things/thing/

19:03 err, can. not. type.

19:04 "is an".

19:05 justin_smith: It makes sense from a Java perspective, I guess.

19:08 justin_smith: I guess the ordering I have always seen was just a convention for clarity

19:28 lodin: justin_smith: Yeah. My first assumption was that defrecord does what extend-type does.

19:44 justin_smith: The sneaky thing is that you can write (defrecord R [...] P1 P2 (m ...)) if m is in both P1 and P2 and should be the same. (Of course, it's more likely that it shouldn't be the same, and then you have to use extend-type.)

19:44 justin_smith: weird

19:45 lodin: justin_smith: defrecord also defines Java methods (.m in this case), and there can only be one Java method m.

19:46 Or can it nowadays? Haven't look at Java for several years.

20:25 tcrayford____: lodin: it's one method m per type signature

20:25 you can have m(Object, Object) and m(Object) just fine

20:27 lodin: tcrayford: Yeah, sure. Meant that you can't qualify the name with an interface (as you can in e.g. C# if I'm not mistaken).

20:30 tcrayford____: yeah, you cannot

20:30 wouldn't be surprised if that went all the way down to the bytecode spec even ;)

20:42 justin_s3ith: justin_s3ith: that sure is a weird irc client you have

21:22 cfleming: tomjack: I've fixed those bugs for the next drop

21:47 tomjack: cool

21:47 thanks!

22:12 cfleming: tomjack: No problem, if you'd like to try a dev build with the fixes before I release let me know

23:09 riceandbeans: question

23:10 I hear of more and more things moving to clojure, and I'm going to need to support it, but I find the JVM abhorrent, are there any viable implementations of clojure NOT in the JVM?

23:10 dyreshark: riceandbeans: clojureCLR?

23:10 justin_s3ith: riceandbeans: clr, or js (but that still needs to compile via the jvm)

23:11 riceandbeans: any particular reason for not liking the jvm?

23:13 riceandbeans: aside from security issues and inherent memory leaks, it also has same nasty networking tendencies that cause it to break in certain operating systems where it supports ipv6 only by tunneling through ipv4

23:15 justin_s3ith: citation needed on inherent memory leaks, I have web servers stay up for months, and likey they would have stayed up for years except for restarting for code updates

23:16 dyreshark: ^^

23:16 riceandbeans: JVMs leak, it's pretty much a feature

23:16 justin_s3ith: least leaky vm I know of

23:16 dyreshark: how have you determined that they leak memory?

23:17 riceandbeans: because you tell them a max amount of heap memory and they go 5x over and never stay within their bounds

23:17 in all my years of SA work, never once seen a JVM stay within its bounds

23:17 justin_s3ith: riceandbeans: then you are saying you don't understand java's command line flags?

23:17 rhg135: also do native code even have limits?

23:18 riceandbeans: JVMs can have hard limits

23:18 justin_s3ith: rhg135: sure, OS imposed limits are always possible

23:18 dyreshark: rhg135: they do -- the OOM killer is a pretty hard limit to bypass ;)

23:18 riceandbeans: whether or not they respect them is another thing

23:18 rhg135: oh well yeah, but that covers the jvm too lol

23:18 justin_s3ith: riceandbeans: in my experience, my vm dies when it is forced past the hard limit, and I have seen no exception to that

23:19 riceandbeans: I've just seen in take down servers in a cluster

23:19 justin_s3ith: also the security concerns are when you are client side running unknown code, it's quite solid compared to the alternatives on the server side

23:20 and client side running unknown code is a crapshoot no matter what

23:20 anyway, yeah, clojure can run on the clr, but isn't as mature for that target

23:20 riceandbeans: you have to submit to oracle, who's in bed with the us govt

23:20 justin_s3ith: it can compile to js, but from within a jvm process

23:20 riceandbeans: most people lock at very specific jvm requirements

23:21 most people never patch their jvms

23:21 justin_s3ith: you don't need oracle's jvm, there is openjdk, an open source project.

23:21 riceandbeans: oracle doesn't like to patch their jvms

23:21 which comes from oracle

23:21 justin_s3ith: and I promise, that javascript engines you will find and the clr are less reliable and less secure than any recent jvm

23:21 seriously

23:21 riceandbeans: openjdk is a product of oracle

23:22 justin_s3ith: it's an open source, community project, with backing from oracle

23:22 riceandbeans: clr means I'll have to run mono, which is hardly usable

23:22 justin_s3ith: riceandbeans: I guess you probably shouldn't use clojure at all

23:22 rhg135: clojureclr, riceandbeans but be warned

23:23 riceandbeans: openjdk is a product of oracle, it's free, it's owned by them, it's partly gpl, but also has closed source and commercial parts in it too

23:23 the only official developer of the code is oracle

23:23 justin_s3ith: openjdk is 100% open source

23:23 debian ships it

23:23 TEttinger: riceandbeans: there's always Common Lisp, which also received a ton of Department of Defense funding back in the day

23:24 justin_s3ith: debian won't even ship the emacs manual in the regular repos, because the license isn't permissive enough

23:24 riceandbeans: openjdk is not in base

23:24 it's in non-free

23:24 rhg135: icedtea compiles from source for me

23:25 p_l: SBCL is public domain, that's enough for "freedom"?

23:25 riceandbeans: in order to submit code to be part of openjdk you have to sign a waiver that you forfeit right to your code and surrender it to oracle and sun, and it has to be approved by oracle before it can be accepted

23:25 dyreshark: FWIW, twitter apparently uses OpenJDK with a few tweaks for their prod servers https://engineering.twitter.com/university/videos/twitter-scale-computing-with-openjdk

23:25 justin_s3ith: riceandbeans: I just went into aptitude, openjdk is not in nonfree

23:25 dyreshark: so if twitter chose to use it, chances are it's not *that bad* as a platform

23:25 TEttinger: I've personally been curious about alternative JVMs, like Avian, but that one's a pain to compile so that the standard lib has enough to run clojure

23:26 riceandbeans: twitter doesn't care about security

23:26 TEttinger: lol

23:26 scottj: https://packages.debian.org/sid/openjdk-6-jdk

23:26 justin_s3ith: riceandbeans: that's a contributor agreement for inclusion in the official repo, not a condition for modifying the code

23:26 dyreshark: whatever you say riceandbeans :)

23:26 riceandbeans: they're as much in bed with feds as oracle and facebook

23:26 dyreshark: have a nice night

23:26 * dyreshark departs

23:27 TEttinger: we sure end up with our fair share of conspiracy theorists here in #clojure. remember that one guy who wouldn't run any code that he couldn't read himself?

23:27 riceandbeans: if your basis for the argument is the larry ellison is a great guy and his company is awesome, so it's a great product, you're not going to convice me of anything

23:27 justin_s3ith: riceandbeans: similarly clojure has a contributor agreement that must be signed before they will consider including your code in the official codebase. It is open source, and you can fork and distribute it all you like without said agreement.

23:27 This does not make it in any way nonfree software.

23:27 scottj: riceandbeans: https://packages.debian.org/search?keywords=openjdk&searchon=names&suite=stable&section=main note the main at the end there

23:28 TEttinger: riceandbeans, you know the internet that you're using right now was once a DoD project?

23:29 riceandbeans: that's new, because I used debian at 3.0, and stopped at 7.4, and it was throughout then, never in main

23:29 due to java's licensing

23:29 scottj: riceandbeans: we've never argued java is good because larry is a great guy, we always said it was ok because he is an ok sailor.

23:31 riceandbeans: I'm aware of arpanet

23:31 raspasov: I have a sequence that looks like this ([14227624954630003 3] [14227624954630004 4] [14227624954630005 5] [14227624954630006 6] [14227624954630007 7] [14227624954630008 8] [14227624954630009 9] [14227624954630010 10])

23:31 justin_s3ith: riceandbeans: anyway, you seem determined to hate the jvm, and it's not really worth my energy to expend much more effort convincing you otherwise. It sounds like you will likely be happier if you don't support clojure, and let people who want to use clojure go elsewhere.

23:31 riceandbeans: it's not that simple

23:31 raspasov: (reduce (fn [result new]

23:31 [(conj (nth result 0) (nth new 0))

23:31 (conj (nth result 1) (nth new 1))]) [(lazy-seq []) (lazy-seq [])] x)

23:31 riceandbeans: puppet is going to be fully moving to clojure from ruby

23:31 justin_s3ith: raspasov: use a paste site please

23:31 raspasov: anything more idiomatic than this for splitting it into two collections?

23:32 scottj: riceandbeans: it's in main in squeeze, or debian 6.0

23:32 justin_s3ith: riceandbeans: yeah, I know some cool dudes who do clojure there

23:32 riceandbeans: the entire project is being ported to clojure

23:32 so anyone using puppet will need to support clojure

23:32 justin_s3ith: riceandbeans: I assure you that the clojure they are doing at puppet is not portable away from the jvm

23:33 TEttinger: $google avian jvm

23:33 no lazybot still?

23:33 justin_s3ith: amalloy or Raynes need to restart it, I don't have the permissions (though I do have a login on that server)

23:34 riceandbeans: whatever happened to parrot?

23:34 https://en.wikipedia.org/wiki/Comparison_of_Java_virtual_machines

23:34 justin_s3ith: riceandbeans: it's out there, and not really being used in anger from what I can gather

23:35 wait, parrot is the new perl vm

23:35 did it ever have plans to support java?

23:35 riceandbeans: I thought it did

23:36 justin_s3ith: anyway, clojure is a bytecode compiler, so unless parrot is bytecode compatible with the jvm, it won't run clojure

23:36 riceandbeans: it supports a lot of languages

23:36 justin_s3ith: OK

23:36 clojure does not generate java, it directly generates bytecode

23:36 so you need either direct clojure support (which nobody has) or jvm bytecode compatibility (in other words you need to be a jvm)

23:37 riceandbeans: jvm bytecode is java

23:37 justin_s3ith: no

23:37 java is a language

23:37 jvm bytecode is a machine language for a virtual machine

23:37 clojure generates bytecode, it does not generate java

23:38 raspasov: anything more idiomatic? thanks! :) https://gist.github.com/raspasov/499b9aa5d0b0d0b91bf8

23:40 justin_s3ith: raspasov: you could use destructuring like so - (fn [[r0 r1] [n0 n1]] [(conj r0 n0) (conj r1 n1)])

23:40 tomjack: [(map first x) (map second x)] ? :)

23:40 raspasov: yea that's true, I was looking for something even more than that :)

23:40 justin_s3ith: tomjack: heh

23:41 raspasov: tomjack: but that generates two sequences, doesn't it?

23:41 justin_s3ith: tomjack: the reduce has the advantage of only walking the input once

23:41 raspasov: yours generates two sequences too

23:41 tomjack: yeah, but I figure it's unlikely you care

23:41 raspasov: oh really?

23:41 tomjack: perhaps you do

23:41 raspasov: I mean

23:41 I meant

23:41 justin_s3ith: raspasov: your result has two sequences inside it

23:41 riceandbeans: justin_s3ith: so you're telling me, if I write hello world in clojure and I wrote the same in scala, and compiled it to bytecode, the bytecode would not be identical

23:41 raspasov: walking it once, instead of two sequences - yes the result is two sequences

23:41 justin_s3ith: riceandbeans: absolutely not

23:42 raspasov: used the wrong language :)

23:42 riceandbeans: vvkvebkiuhcbtdthitebjgltrnuvdrhiunnfhkhhvtjv

23:42 vvkvebkiuhcbjglklrndvdldultbrhejbjjfuuflbien

23:42 justin_s3ith: riceandbeans: both generate jvm bytecode, but they have different infrastructure for bootstrapping the runtime parts of their languages

23:42 raspasov: ok thanks guys!

23:44 justin_s3ith: riceandbeans: on the other hand it is trivial to call java code from clojure, clojure code from java, scala code from clojure, clojure code from scala etc. etc.

23:48 riceandbeans: I was under the impression that JVM languages translated the parent language code to java before compiling

23:48 justin_s3ith: riceandbeans: none of the ones that are any good

23:48 java the language sucks

23:48 the jvm byte code / vm is much better

23:49 anyway, I am turning in for the night, best of luck

23:49 tomjack: scala code from clojure, trivial? hmm

23:50 justin_s3ith: tomjack: it compiles to classes you can invoke via interop

23:50 cfleming: It's relatively trivial but very ugly

23:50 tomjack: ISTR looking only at classes and methods, it seemed nightmarish

23:50 ah, you just have to know what to look for I guess?

23:50 justin_s3ith: cfleming: pretty is a higher standard

23:50 cfleming: Yeah, you have to know how it mangles its classes, and some understanding of how it encodes traits etc

23:51 justin_s3ith: No doubt.

23:51 There's a company near here using datomic with Scala clients, actually

23:51 Although that's the other direction, of course

Logging service provided by n01se.net