#clojure log - Sep 12 2014

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

0:27 sdegutis: is Delegate a horrible name for an app?

0:33 TEttinger: sdegutis: it is great if you want to make a blame-passing app. like, I don't want to do this, let me consult Delegate to see who to give the project to

0:33 sdegutis: :)

0:33 rpaulo: heheh

0:40 craigglennie: What’s the current state-of-the-art for web-scraping - is it Enlive?

0:42 danielcompton: sdegutis: make sure it doesn't violate the single responsibility principle and you're fine

0:43 sdegutis: heh

0:43 I have given up on naming my app.

0:43 danielcompton: craigglennie: think it's Amazon Turk still

0:43 sdegutis: I'm just going to call it Concierge.app and be done with it.

0:43 danielcompton: sdegutis: Mac app?

0:43 sdegutis: yes

0:43 craigglennie: danielcompton: You mean MTurk? I’m thinking more of something equiavlent to Python’s beautifulsoup or lxml

0:44 danielcompton: Something to help me parse data out of HTML

0:44 jarjar_prime: hello all!

0:46 seancorfield: craigglennie sure sounds like Enlive to me...

0:46 danielcompton: sdegutis: cool, what does it do?

0:47 sdegutis: you give it a script and it runs your script, and it gives you an api for your script to use that hooks into low-level GUI APIs

0:47 or something

0:48 danielcompton: sdegutis: what's the use case?

0:48 sdegutis: scripting your gui

0:48 i.e. write 4 lines so that any time you press a global hotkey, your mouse cursor moves to the center of the focused window

0:48 craigglennie: seancorfield: thanks

0:48 sdegutis: or bind some global hotkeys to move windows around

0:50 is there a version of Clojure for embedding in a C app?

0:51 sm0ke: https://github.com/raph-amiard/clojurescript-lua

0:51 sdegutis: requires a jvm still?

0:52 sm0ke: i guess you could compile it , but yes for dev jvm would be required

0:52 sdegutis: why oh why jvm do you have to be so different, fricken hipster

0:53 everything is written in C except suddenly theres java and now nothings compatible with anything else

0:53 sm0ke: java is written in C you know

0:53 sdegutis: thats the worst part!

0:53 p_l: actually what is really incompatible... is C++

0:53 sdegutis: its like its mocking us! just sitting there like "haha im written in C but completely incompatible with C"

0:54 sm0ke: :P

0:54 p_l: Java got JNI and I had seen stuff that looked like it had embedded Java

0:54 sm0ke: have you looked ar jnr

0:54 sdegutis: welp

0:54 gonna name my app Concierge.app

0:54 sm0ke: its frekin awesome

0:54 https://github.com/jnr/jnr-ffi

0:54 sdegutis: although someone told me it has, umm, certain connotations

0:55 but i cant find anything bad in the dictionary or wikipedia page about it

0:56 sm0ke: why would you want to write in clojure if your stack doesnt have jvm

0:56 write in ocaml, haskell, scheme, guile

0:56 and a hundered more

0:56 sdegutis: +1

0:57 sm0ke: sdegutis: still here?

0:57 sdegutis: hi

0:57 sm0ke: oh i though you will part from #clojure

0:57 sdegutis: why

0:58 sm0ke: nothin

0:58 sdegutis: k

0:58 danielcompton: sdegutis: "Adult" concierges exist and mean pretty much what you think they mean

0:58 sdegutis: crap

0:58 ugh

0:59 there are no names.

0:59 all names are taken.

0:59 i have been trying to name this app for like 4 months no

0:59 *now

1:00 sm0ke: chauffer

1:00 sdegutis: i wanted to do Minion.app but everyone will think of those dumb yellow things

1:00 i might do Lackey.app

1:00 but i have no idea what people think when they hear lackey

1:00 danielcompton: sdegutis: OTOH adding adult to any word makes it sound bad. Concierge sounds pretty good to me

1:01 sm0ke: sdegutis: Sevak.app

1:03 sdegutis: lol Manager.app

1:03 yeah ill stick with Concierge

1:04 if at least 20% of the people i tell this to say the adult-concierge thing, its gone. otherwise ill keep it

1:10 TEttinger: YourNameIsToby.app

1:10 sdegutis: correct

1:12 dorkmafia: technomancy: https://github.com/rplevy/clojure-python found this

1:13 i'm going to give it a spin now

1:57 TheMonarc: greetings, is there a good clojure book for someone who is new to both clojure and FP?

1:58 new to FP part not as important (did a little LISP in college)

1:59 dbasch: TheMonarc: you may like http://joyofclojure.com/

2:00 actually http://www.amazon.com/The-Joy-Clojure-Michael-Fogus/dp/1617291412/

2:16 zanes: TheMonarc: You might also like http://www.braveclojure.com/

2:16 Has the added benefit of talking about tooling.

3:08 zot: morning :) i'm new to it, and seeking the most natural/elegant way to iterate through a string, splitting at a regex, but iterating through both matches, and the goo in between

3:09 thus: regex: "\d" with an input of "asdf 2 ff 33" -> seq ["asdf ", "2", " ff ", "3", "3"]

3:09 is there something that i'm not finding to do this cleanly?

3:09 (i can make my own groupings both inside and outside of the expression, but thought there might already be a better way

3:13 engblom: zot: http://clojuredocs.org/clojure_core/clojure.string/split

3:14 zot: engblom: i found that, but it drops the matching bit. re-seq appears to only yield the matching bit, and i haven't found a single thing threads them (or keeps them) together :)

3:20 Bronsa: zot: you can use interpose on c.s/split and re-seq if you don't mind running over the string twice

3:22 err, interleave

3:22 zot: interesting, but the matching expression isn't fixed

3:22 yeah, that looks much better. have to do first match manually to see which seq leads, but that's the right idea :)

3:23 Bronsa: ,(require '[clojure.string :as s])

3:23 clojurebot: nil

3:23 Bronsa: ,(defn f [p s] (interleave (s/split s p) (re-seq p s)))

3:23 clojurebot: #'sandbox/f

3:23 Bronsa: ,(map (partial f #"\d") ["1 a 2 b" "a 1 b 2"])

3:23 clojurebot: (("" "1" " a " "2") ("a " "1" " b " "2"))

3:24 Bronsa: uhm

3:24 zot: looks pretty good to me :)

3:24 thanks!!

3:24 Bronsa: zot: it's dropping the last match on the first string

3:24 zot: doh. missed that.

3:25 your karma is still on the up for this weekend ;)

3:25 but i'm curious about the dropping bit

3:25 babygau: https://www.refheap.com/90139

3:27 tobik: zot: if you change your regexp you can probably do this with re-seq

3:27 ,(re-seq #"\d|[^\d]*" "asdf 2 ff 33")

3:27 clojurebot: ("asdf " "2" " ff " "3" "3" ...)

3:28 Bronsa: nice tobik

3:28 zot: tobik: i was playing with that idea already, but my regex is much more complicated, so it was more like: #"(.*)(?:({{[…]}})|(.*))*"

3:28 but failing, as complicated regexs often do

3:29 i needed a quick and dirty way to do some light templating, including env var substitution, and file content substitution. perhaps the other approach is to ask what already exists :)

3:30 and i'm missing a * after the inner [token_letters]

3:31 actual code i'm trying: (print (re-seq #"(.*)(?:({{@[A-Za-z0-9_]+}})(.*))*" "ao {{FOO_BAR}} do")

3:31 but doesn't compile

3:36 tobik: ,(re-seq #"\{\{@[A-Za-z0-9_]+\}\}|[^\{\{@[A-Za-z0-9_]\}\}]+" "ao {{FOO_BAR}} do")

3:36 clojurebot: ("ao " "FOO_BAR" " do")

3:38 zot: tobik: thanks :) it hurts my brain.

3:39 i dno't see how the second half of the expression works though — it's a multi-character match.

3:39 is there a way to make .* not greedy?

3:40 tobik: i don't think so

3:40 zot: then i think i just have to split on "{{|}}" and do a tiny "parser" with the interleave thing as input stream

3:41 maybe easier in the end

3:41 tobik: can't you just use a templating library for this?

3:41 zot: that's what i was asking before — i hadn't found sometihng that does what i need, and originally hoped it would be 15m of (learning experience) code to write. naïve.

3:42 tobik: you can probably adapt selmer to your needs

3:42 https://github.com/yogthos/Selmer

3:46 babygau: https://www.refheap.com/90139

3:56 Bronsa: zot: http://sprunge.us/EEKh?clj if you're curious, this should work as expected for every input string

3:59 babygau: repeatedly pasting the same link won't help you getting answers if you first don't tell us what's not working

4:00 babygau: Bronsa, sorry bro, I thought put my question in the link make my question look cleaner :(

4:00 Bronsa, I can't compile #clojurescript to normal #javascript

4:01 Bronsa, the output (as you can see over the link) looks weird >.<

4:04 Bronsa: babygau: I have never used cljsbuild, but reading gulpfile.js it looks like you should find the output of your ns in gulpjs/core.js

4:06 babygau: Bronsa, you're right, I found the compiled core.js but I don't know why it doesn't compile to `gulpfile.js` but `core.js`???

4:06 lazybot: babygau: Yes, 100% for sure.

4:09 Bronsa: babygau: as I said, I don't use cljsbuild so I can't really answer that question. you might want to wait until people in the US start waking up and ask that again

4:09 babygau: Bronsa, what do you use then :-P

4:09 Bronsa: I don't use cljs at all

4:10 babygau: Bronsa, tks bro :)

4:18 PeakCode: I get a 404 page when I try that link (https://www.refheap.com/90139). Do you have to be signed in?

4:19 tobik: its gone now

4:19 PeakCode: OK, I see.

4:21 babygau: PeakCode, https://www.refheap.com/22172234ac498cee3cc18214d

4:25 PeakCode: babygau: What is the path to the core.cljs file?

4:29 babygau: I suspect that :source-paths should be just ["src"] instead of ["src/gulpjs"].

4:30 babygau: PeakCode, nope, as I read in #clojurescript up & running, it must be src/gulpjs because my namespace is gulpjs.core

4:35 PeakCode: babygau: So the path to core.cljs is src/gulpjs/gulpjs/core.cljs then?

4:37 babygau: PeakCode, it is src/gulpjs/core.cljs

4:38 PeakCode: babygau: I'm pretty sure you have to either change :source-paths or the path to core.cljs. :source-paths should point to the root of your source tree.

4:39 babygau: PeakCode, tks bro, pls give me a sec, I will check it out immediately

4:43 PeakCode, I changed `:source-paths ["src"]` but the code in `gulpfile.js` is still the same

4:47 tobik: babygau: try this https://www.refheap.com/f946f21767954ea1b1afe82a6

4:48 babygau: tobik, I will try it now

4:50 tobik, it WORKED!

4:51 tobik, I don't even have to put :target :node, I think the prob is in :optimizations

4:51 tobik, PeakCode, I changed :optimizations :simple the the code run

4:52 djcoin: babygau: tobik pretty cool experiment :)

4:56 babygau: tobik, PeakCode, tks you guys

4:56 PeakCode: babygau: OK, great! Perhaps adding :output-dir would have worked with :optimizations :none. You can also try :optimizations :whitespace.

5:05 babygau: PeakCode, it doesn't work bro :)

5:26 zot: Bronsa: thanks, this is awesome :)

5:34 AeroNotix: when I run component/stop on a component system, does it call stop on every component?

6:56 thesaskwatch: Hi .. I can use (source x) to view source of x ... but what if it's defmulti .. can I list / view defmethods of it in repl?

7:09 sm0ke: is there a variant of (let [..]) which signifies non ordered declaration?

7:10 Bronsa: sm0ke: letfn is parallel, but as its name suggests, can only bind functions

7:10 sm0ke: Bronsa: i am not really concerned if its parallel, more on readability

7:11 Bronsa: then no

7:11 sm0ke: like i use (if) for two condition and (when) for one

7:11 ok

7:12 Bronsa: sm0ke: maybe you want if-let/when-let?

7:13 sm0ke: no thats not the point,

7:13 my point it

7:13 Bronsa: sm0ke: your last phrase seemed to suggest that :)

7:13 clgv: AeroNotix: hopefully, isnt that the point of that hierarchical composition?

7:14 Bronsa: sm0ke: you want (let [a b b 1] a) ;=> 1 right?

7:14 sm0ke: if i see a (let [a .. b ,..]) i cannot say if a and b are dependent on each other

7:14 not without looking deeply into what a and b does

7:14 Bronsa: sorry I have to run

7:14 sm0ke: no prob

7:14 clgv: sm0ke: but you know that "a" cannot depend on "b"

7:15 sm0ke: clgv : (let [a 1 b (inc a)[)

7:15 clgv: yeah the otherway round is possible ;)

7:15 sm0ke: -.-

7:15 clgv: so you want that common lisp let back?

7:16 sm0ke: no i just want to have a code convetion, lets say there is a (let ) for bindings which depend on each other and (let**) for non dependent bindings

7:16 clgv: sm0ke: is writing that yourself an option? I could give you a hint how to achieve it

7:17 sm0ke: yes it is easy

7:17 but my point was if other people are foloowing something

7:17 what will i do alone in my own world

7:18 clgv: well, the question is if other people do rank this as important as you do

7:18 I for myself do not

7:19 sm0ke: yep not critical but would be nice for readability imo

7:19 clgv: but could also lead to pretty awful nesting of let and let*

7:20 ah "let**" you said ^^

7:33 SagiCZ1: hi

7:34 ,(= (conj [[5 6] [7 8]] [0 1]) (conj '([5 6] [7 8]) [0 1])

7:34 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

7:34 SagiCZ1: ,(= (conj [[5 6] [7 8]] [0 1]) (conj '([5 6] [7 8]) [0 1]))

7:34 clojurebot: false

7:34 SagiCZ1: i need to do the first thing, but with list and not vector

7:35 append element to the end of list

7:36 ,(cons 4 '(0 1))

7:36 clojurebot: (4 0 1)

7:36 SagiCZ1: ,(conj '(0 1) 4)

7:36 clojurebot: (4 0 1)

7:36 SagiCZ1: they both do the same thing

7:36 how is that useful?

7:37 clgv: SagiCZ1: thats not possible efficiently. why do you need that for a list exactly?

7:38 SagiCZ1: well one of my functions is returning list

7:38 ,(vector '(4 5 6))

7:38 clojurebot: [(4 5 6)]

7:38 clgv: cant you change it to a vector and keep it a vector?

7:38 SagiCZ1: ,(vec '(4 5 6))

7:38 clojurebot: [4 5 6]

7:38 SagiCZ1: okay then..

7:39 clgv: most of the time you want vectors anyway

7:39 TEttinger: ,(concat '(0 1) '(4))

7:39 clojurebot: (0 1 4)

7:39 clgv: TEttinger: not efficiently though and not type preserving ;)

7:39 TEttinger: yep

7:39 ,(class (concat '(0 1) '(4)))

7:39 clojurebot: clojure.lang.LazySeq

7:39 clgv: and not arbitrarily stackable ;)

7:41 SagiCZ1: and adding to end of vector is O(1) ?

7:41 clgv: yes

7:42 SagiCZ1: is vector also implemented by some tree?

7:42 clgv: yeah. son in fact its log_{32}(n)

7:58 SagiCZ1: is there a print statement that also returns what it printed? something like (defn print-return [x] (println x) x) ?

7:58 ,(defn print-return [x] (println x) x)

7:58 clojurebot: #'sandbox/print-return

7:59 clgv: nope, but probably defined hundreds of times ;)

7:59 SagiCZ1: (print-return {:b 4 :a 5})

7:59 clgv: okay :)

7:59 clgv: there is the "spyscope" library that does something similar

8:17 inad922: Hi

8:17 How can I go left and write in the interpreter?

8:18 + up/down for walking history?

8:19 engblom: inad922: Do you mean inside of REPL? Is not the arrow keys working for you?

8:22 clgv: inad922: do you use leiningen? if not, you should definitely change that

8:24 inad922: just with "java -jar clojure.jar" you wont' get those features

8:27 inad922: engblom: Yes, well I think inside the repl. I'm new to this. I run "clj" on the cli

8:27 clgv: inad922: how did you "install" clojure?

8:28 inad922: I recommend following the steps under "install" here http://leiningen.org/ and then use "lein repl"

8:28 inad922: clgv: pacman -S clojure. So via the package manager

8:28 clgv: inad922: probably not optimal.

8:29 inad922: what's your goal? learning the language with a quickly setup environment?

8:29 inad922: if so, give lighttable a try http://www.lighttable.com/

8:29 inad922: clgv: I want to use clojurescript for frontend development

8:30 clgv: inad922: so are you sold on any editor/IDE yet?

8:30 inad922: clgv: Yea, I use sublime. Light table seems to be the same

8:31 clgv: clgv: no lightable is definitely distinct from sublime ;)

8:31 inad922: clgv: I'm a python dev mainly, I just want to learn something more usable for frontend than js. That's just bad

8:32 clgv: but try it out, it gets you setup pretty quickly. other options are eclipse with counterclockwise, intellij with cursive, vim with vim-fireplace and emacs with cider

8:32 inad922: umm

8:32 clgv: too much choices? ;)

8:32 inad922: Why would I need anything better than a plain editor?

8:33 clgv: because of integration of editor and repl

8:33 inad922: I mean does clojure have code quality standards like pep8 for python? Static code checkers, etc.?

8:33 clgv: e.g. evaluating the content in the editor or the selected function in the repl by pressing a shortcut combination

8:33 inad922: I don't need editor integration

8:33 xemdetia: do you not use python repl for python dev?

8:33 clgv: integration of editor and repl is a must-have

8:34 inad922: xemdetia: Nah

8:34 not really it isn't

8:34 clgv: in clojure it is

8:35 inad922: Why how do imports work in this language?

8:35 and modules

8:35 namespaces, stuff like that

8:36 Is this leiningen like a package manager for clojure?

8:37 xemdetia: inad922, it's closer to maven if you are familiar with that

8:37 clgv: inad922: kind of. it fetches the dependencies you declared, from default (or specified) repositories

8:38 inad922: it starts a repl for you where all dependencies are present and you can build deployable jar archives with it

8:38 holo: inad922 yeah leiningen is awesome. do you know the story?: http://www.classicshorts.com/stories/lvta.html really worth reading. The original author is like Leiningen who defeated the ants. sometimes he lurks in this #

8:38 clgv: inad922: for clojurescript there is "lein cljsbuild"

8:38 inad922: xemdetia: Ah maven. This stuff only runs on JVM?

8:39 clgv: holo: lol what? the background is that he defeated the "ants" :P :D

8:40 holo: clgv, sure!

8:40 clgv: inad922: your dev environment will run on JVM. you'll compile javascript files from clojurescript via leiningen

8:40 holo: damn, that one took long to notice (~3 years) ;)

8:41 holo: clgv haha :D

8:41 clgv: so leiningen defeats ants but is afraid of mavens?

8:42 holo: well, every brave man has a fear to conquer!

8:42 xemdetia: inad922, the main thing to note with a functional language is that not using a repl for interactive development makes it very difficult to determine that given what input, what does this function provide as output

8:43 TimMc: holo: Every brave woman as well.

8:43 xemdetia: this is also important because the idea is 'many little functions chained together' and not 'one big code block'

8:43 TimMc: *person

8:43 holo: TimMc, sure, brave women are awesome!

8:45 TimMc: Wasn't quite what I was driving at, but I guess I'll take it.

8:46 inad922: xemdetia: I don't say you should not use a repl. I obviously do with python. I'm saying that editor integration doesn't do too much good for me.

8:49 clgv: inad922: just try one of those options and experience the benefits ;)

8:52 inad922: just using "cli" from your package manager will be a pretty poor setup as you have already noticed

8:53 inad922: clgv: Yea, I just downloaded the leiningen script

8:53 Running lein repl

8:53 It does what I wanted

8:54 clgv: :)

8:54 one step forward. but I'd go the next steps as well

8:54 inad922: Also I'm a bit frightened about the fact that this stuff runs on the JVM

8:54 Java is horrific...

8:54 xemdetia: only if you are clumsy

8:54 hyPiRion: inad922: java != JVM

8:54 clgv: as hyPiRion said!

8:54 inad922: xemdetia: I don't want to start a flame war. I don't like that language, that's it.

8:55 tbaldridge: inad922: who does? Good thing Clojure means you don't have to write in Java.

8:55 inad922: JVM is the bytecoder interpreter that runs the compiled Java code isn't it?

8:55 holo: inad922, just be afraid of the bootstrap times. if you follow the Stuart Sierra workflow though, you may save so much time

8:55 clgv: inad922: so you would not use a properly working program only because it is written in java? that's a strange world view

8:55 hyPiRion: inad922: the compiled JVM code*, but yes, that's right

8:56 inad922: clgv: If there is an alternative :)

8:57 holo: inad922 hy is fine. there is also rhine, on the llvm

8:57 clgv: ouch!

8:58 tbaldridge: holo: sadly hy is "mutation everywhere!", that's the reason I never really used it.

8:58 hyPiRion: holo: rhine is not working yet

8:58 TimMc: inad922: The JVM is a pretty different beast from Java.

8:58 Sun did a reasonably good job making them separate.

8:59 holo: tbaldridge, I'm integrating hy with fn.py now for that reason. maybe it will be awesome

8:59 inad922: TimMc: Yes, probably you're right. I don't know much about this topic.

8:59 TimMc: xemdetia: Most people are clumsy most of the time, so that's no excuse for a poorly designed language. :-)

9:00 inad922: For instance, the JVM doesn't know what inner classes or checked exceptions are.

9:00 xemdetia: TimMc, fair enough.

9:00 tbaldridge: inad922: the Clojure/JVM thing is an interesting beast. On one hand I'm not crazy about the JVM. On the other hand I've integrated fairly large libraries in Clojure.

9:01 Being able to say " you can use this mountain of existing code from clojure " is huge in the "real" world.

9:02 inad922: tbaldridge: Yes, I have to agree with that.

9:03 holo: yeah, I integrated two of my own. it's a huge win

9:03 hyPiRion: inad922: I'll just say you should try out Clojure, and if you like it, stay with it. Just be aware that, although it runs on the JVM and has Java interop, it's not related to Java the language.

9:05 And if you don't like it, then that's perfectly fine too :)

9:06 clgv: he actually wants to use CLJS ;)

9:06 inad922: hyPiRion: Yeah well. I give it a try. I really like how well clojurescript integrates with already written js libraries. Also it seems like a well designed language unlike js. I just want to find an alternative

9:06 hyPiRion: clgv: oh well, cljs then!

9:07 tbaldridge: inad922: personally I enjoy working with CLJS more than CLJ. You fire up cljsbuild and set it to auto re-compile. Then as you edit files they recompile in about 0.5 sec. Refresh the browser and you're on your way

9:07 clgv: btw. are the days of the "hashcode versions" of cljs counted?

9:07 tbaldridge: clgv: I highly doubt it

9:08 clgv: tbaldridge: is there a definied/described state for it to reach 1.0?

9:09 tbaldridge: clgv: so I'll give you the reasoning I got from Rich once when I asked when core.async would hit beta...

9:09 inad922: tbaldridge: Nice. That's good for testing. Do you use clojure on the backend too?

9:10 tbaldridge: "Why are people so concerned about alpha,beta, etc.? Are they thinking that it somehow won't change after it hits beta? We try not to change public APIs, so why does beta matter? It's not magically stable or perfect because someone sticks 1.0 on it"

9:11 clgv: so I think the idea on that stuff is, if it works for you, use it. CLJS only gets more stable, version numbers are meaningless. :-)

9:11 clgv: tbaldridge: well it expresses the confidence of the maintainer. so we are lucky clojure has releases at all? :P

9:13 xemdetia: gmail set the groundwork for the mostly permanent beta future

9:13 tbaldridge: clgv: but that would suggest that the confidence of the maintainer is something that has an absolute value.

9:14 clgv: tbaldridge: well it is at least indirect communication between maintainer and user

9:15 tbaldridge: clgv: examples...Games from Blizzard are playable in alpha and beta. While games from EA often crap on the day after release. Gmail got out of beta after 10 years?

9:15 clgv: tbaldridge: I mean there is a version scheme and from the usual context it implies that there should be a 0.1 or 1.0 at some point ;)

9:16 tbaldridge: ok on that argument, why not just counting up from 1 for release numbers but instead employ a version scheme that implies some magical future versions that won't happen?

9:16 tbaldridge: clgv: I get what you're saying, and I'm just arguing to make a point. But I do agree with those who state version numbers are rather worthless things, and it bugs me when managers say things like "Eh...don't use Kafka, it's only at v0.8"

9:17 clgv: tbaldridge: hehe, managers are why you need internal and external versions :P

9:17 use "the new ClojureScript 2014/04" :P

9:18 dnolen_: clgv: that is in fact what Google Closure Compiler / Library does

9:18 clgv: dnolen_: the counting-up version scheme?

9:19 dnolen_: clgv: no version is just the date

9:19 truebuddi: newbie here so wanted to check if this can be written using thread-first -> macro??? (remove-person "Krishna" (add-person "Krishna" default-trip)) ... where add-person and remove-person both take a string and a map

9:19 dnolen_: com.google.javascript:closure-compiler v20140814, http://search.maven.org/#artifactdetails%7Ccom.google.javascript%7Cclosure-compiler%7Cv20140814%7Cjar

9:21 SagiCZ1: how do i load a file in clojure using relative path?

9:24 nvm got ti

9:24 *t

9:24 *it

9:24 clgv: truebuddi: you probably need ->> since the map is last position

9:28 SagiCZ1: how can i find an element by tag after using xml/parse?

9:28 AeroNotix: with midje teardown/setup is there a way to make something run before all the facts and after all the facts?

9:28 truebuddi: clgv: I was playing around with -> .. (-> data fn1 fn2) ... right? so i was trying to use (partial ...) and i get results I dont understand ..

9:28 ((-> (add-person "Krishna" default-trip) (partial remove-person "Krishna"))) => "Krishna"

9:29 ((->> (add-person "Krishna" default-trip) (partial remove-person "Krishna"))) ==> gives me a map that I originally wanted

9:29 (->> (add-person "Krishna" default-trip) (partial remove-person "Krishna")) gives me back a partial :(

9:30 ToxicFrog: ...yes, it does

9:30 Because that gets rearranged into (partial remove-person "Krishna" (add-person "Krishna" default-trip))

9:30 Did you mean (->> default-trip (add-person "Krishna") (remove-person "Krishna")) ?

9:31 truebuddi: ^

9:32 truebuddi: ToxicFrog: (->> default-trip (add-person "Krishna") (remove-person "Krishna")) this is what I wanted ... now I have to analyze it

9:33 ToxicFrog: (add-person "Krishna") as is throws arity mismatch exceptions .. but it can be used in ->> without using partial ... thats interesting

9:33 clgv: truebuddi: usually for usage in threading macros, map and plain values that might be threaded should be the first argument and sequences/sequential ds should be the last argument

9:33 ToxicFrog: truebuddi: -> and ->> are macros, they rearrange the code before it gets evaluated.

9:33 milos_cohagen: truebuddi: use macroexpand to help your understanding

9:33 ,(macroexpand-1 '(->> default-trip (add-person "Krishna") (remove-person "Krishna")))

9:33 clojurebot: (remove-person "Krishna" (add-person "Krishna" default-trip))

9:33 ToxicFrog: Yes, that

9:35 truebuddi: clgv: i had add-person [person trip] where trip is a map .. and you recommend trip to be first and person to be the later argument?

9:36 ToxicFrog: truebuddi: that would be more consistent with the clojure stdlib, yes

9:36 clgv: truebuddi: if it shall be used in threading often, then yes

9:36 ToxicFrog: e.g. assoc/dissoc take arguments [map key] rather than [key map]

9:36 truebuddi: ToxicFrog: in that case how would ->> work out?

9:37 clgv: truebuddi: ->> is the reserved for sequential datastructures and clojure's sequence functions, e.g. map, filter ...

9:37 "reserved" ;)

9:39 truebuddi: clgv: once i swapped the order of params like you suggested, i can use the -> as in (-> default-trip (add-person "person1") (remove-person "person1"))

9:41 to understand how -> rearranged .. i am using macroexpand but it gives me what looks like =====> (remove-person (clojure.core/-> default-trip (add-person "person1")) "person1")

9:42 is there anyway i can see that it actually did a (remove-person (add-person default-trip "person1") "person1")

9:42 ToxicFrog: -> has more expansion stages, IIRC.

9:43 ,(macroexpand-all '(-> default-trip (add-person "person1") (remove-person "person1")))

9:43 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: macroexpand-all in this context, compiling:(NO_SOURCE_PATH:0:0)>

9:43 ToxicFrog: Huh.

9:43 ,(macroexpand '(-> default-trip (add-person "person1") (remove-person "person1")))

9:43 clojurebot: (remove-person (add-person default-trip "person1") "person1")

9:43 ToxicFrog: truebuddi: ^

9:44 truebuddi: ToxicFrog: I get ... but the inner -> isnt expanded ... (remove-person (clojure.core/-> default-trip (add-person "person1")) "person1")

9:45 ToxicFrog: truebuddi: using macroexpand-1 or macroexpand

9:45 ,(macroexpand-1 '(-> default-trip (add-person "person1") (remove-person "person1")))

9:45 clojurebot: (remove-person (add-person default-trip "person1") "person1")

9:45 ToxicFrog: Huh.

9:46 Also, what version of clojure are you using, the internals of -> may be different between your version and the bot's version

9:47 truebuddi: pretty old i guess [org.clojure/clojure "1.5.1"] ... just did a lein new and playing with cursive .. did not look at which version . thought lein new will take care of using the latest

9:47 clgv: truebuddi: if you see the recursive expansion you have an older clojure than 1.6

9:49 truebuddi: Fixing my project.clj to use latest version but is there a clojure function that returns the version? .. something like (version ) ??

9:49 lazybot: truebuddi: Uh, no. Why would you even ask?

9:49 truebuddi: lazybot: sorry?

9:50 zerokarmaleft: ,*clojure-version*

9:50 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

9:50 augustl: truebuddi: lazybot is a bot :)

9:51 truebuddi: augustl : new here .. so easily fooled :(

9:53 gotta go .. thank you all..learned a few things today ... will be back again in the evening with more questions.. thanks again

9:57 clgv: ,(clojure-version)

9:57 clojurebot: "1.7.0-master-SNAPSHOT"

10:01 inad922: This lighttable is pretty cool

10:01 I like it

10:01 TimMc: I should give it another shot some time.

10:03 SagiCZ1: can i simplify this or make it nicer?

10:03 ,(drop-last 1 (drop 1 (range 10)))

10:03 clojurebot: (1 2 3 4 5 ...)

10:04 verma: ,(doc range)

10:04 clojurebot: "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity. When step is equal to 0, returns an infinite sequence of start. When start is equal to end, returns empty list."

10:04 TimMc: ,(range 1 (dec 10)

10:04 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:04 verma: ,(range 1 10)

10:04 clojurebot: (1 2 3 4 5 ...)

10:04 TimMc: ,(range 1 (dec 10))

10:04 clojurebot: (1 2 3 4 5 ...)

10:04 TimMc: SagiCZ1: But you probably mean a seq that is not a range. :-)

10:04 SagiCZ1: sorry that i didnt specify it but its should work for any coll.. i want to drop first and last

10:05 can i use -> somehow?

10:05 TimMc: That only rearranges your syntax.

10:05 Is that all you want?

10:06 verma: ,(doc butlast)

10:06 clojurebot: "([coll]); Return a seq of all but the last item in coll, in linear time"

10:06 verma: ,((comp rest butlast) (range 10))

10:06 clojurebot: (1 2 3 4 5 ...)

10:06 SagiCZ1: verma: thanks, that looks pretty good

10:07 any reason to prefer rest to next?

10:07 verma: (-> (range 10) butlast rest)

10:07 ,(-> (range 10) butlast rest)

10:07 clojurebot: (1 2 3 4 5 ...)

10:07 verma: SagiCZ1, rest is lazy, but I guess wouldn't matter since we want the last element out as well

10:07 SagiCZ1: ,(-> (range 10) drop 1 drop-last 1)

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

10:08 SagiCZ1: threading -> doesnt work with more than 1 param?

10:08 TimMc: SagiCZ1: -> doesn't magically know which things are arguments to fns

10:08 verma: SagiCZ1, you gotta parent them

10:08 SagiCZ1, you gotta paren them

10:09 SagiCZ1: ,(-> (range 10) (drop 1) (drop-last 1))

10:09 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

10:09 verma: ,(doc drop)

10:09 clojurebot: "([n] [n coll]); Returns a lazy sequence of all but the first n items in coll. Returns a stateful transducer when no collection is provided."

10:09 verma: SagiCZ1, use ->>

10:09 SagiCZ1: ,(->> (range 10) (drop 1) (drop-last 1))

10:09 clojurebot: (1 2 3 4 5 ...)

10:10 SagiCZ1: so -> and ->> difference is only if it appends the param as last or first right?

10:10 verma: SagiCZ1, yeah

10:10 SagiCZ1: cool stuff

10:10 verma: :)

10:11 TimMc: SagiCZ1: Well... last, or second.

10:11 SagiCZ1: so it generally works for functions with params like [n coll] or [coll n] ..

10:14 verma: SagiCZ1, not necessarily, you can do much more with -> and ->>

10:15 SagiCZ1, there's no need to use them with just seq's, they are meant to insert things into expressions, so you can use them pretty much any way you like

10:15 TimMc: SagiCZ1: You can really abuse them.

10:16 verma: (-> (go (get-me-food)) <! (print))

10:16 TimMc: &(-> [a 1] (let a))

10:16 lazybot: ⇒ 1

10:16 verma: nice TimMc :)

10:17 TimMc: Even this is an abuse: ##(-> + var meta :since)

10:17 lazybot: ⇒ nil

10:17 TimMc: &(-> + var meta :added)

10:17 lazybot: ⇒ "1.2"

10:18 verma: :)

10:21 TimMc: (var is not even a macro, it's a special form)

10:22 szymanowski: hello, i've implemented a custom vector-like data structure and I would like the "count" function works on it, how can i do this?

10:22 tbaldridge: szymanowski: have it implement clojure.lang.ICounted

10:23 szymanowski: thank you tbaldridge

10:23 tbaldridge: szymanowski: actually it's just Counted: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Counted.java

10:23 szymanowski: ok thank you

10:28 CookedGryphon: Hey, I'm writing a test.check generator and have a vector of events. What I want to do now is batch those events to simulate the way they arrive in my real app, anyone know how i'd do that?

10:28 (so I have the full stream of events that i'd like to arrive, now I want to randomly slice up that vector so they arrive in batches

10:32 TimMc: CookedGryphon: I would get test.check to also a generate for you a vector of chunk sizes, and then have the inner portion of your test chunk the vector "deterministically" based on that chunk size list.

10:33 so ask for a pair of data, chunking instructions.

10:34 legittalon: What do Clojure wielding developers call themselves?

10:34 CookedGryphon: that makes sense

10:41 Fender: hi there, is there some best practice how to program async stuff?

10:41 for example debug go-loops - once created they kind of run forever unless I implement a channel specific stop command

10:41 but this is also cumbersome

10:42 smizell: Hello all, I came in here a few days ago talking about an idea where you could use JSON as code (Lisp flavored). I threw a very minimal example together for fun and thought I'd just link it here. Feel free to throw your head back in laughter. https://github.com/smizell/geneva

10:42 Fender: also, sometimes my channel msgs are printlned and they overwhelm my emacs when there are many of them

10:44 stw: SegFaultAX: thanks for the help yesterday, I was able to isolate the process in it's own thread and then interrupt it after a timeout

10:46 CookedGryphon: TimMc: I'm generating my chunks such-that the sum of the vector of ints adds up to the length of the vector, but in most cases this means I generate a much longer vector than I need... Any ideas as to how I can generate a chunking vector that works with the number of elements I actually have?

10:48 stompyj: legittalon: clojurians

10:48 note: I made that up

10:49 iclojoclasts

10:49 ToxicFrog: Goddamnit, core.typed

10:50 legittalon: I’m tryna decide if I want to go all in on Haskell or Clojure, first.

10:51 clgv: and that depends on the nicknames?

10:51 legittalon: Yes.

10:51 No.

10:51 cbp: clojodites

10:51 clgv: ah well, throw a coin ;)

10:52 ddellacosta: legittalon: Haskell is incredible, seriously mindbending, and insanely deep. Clojure is awesome and has a great community.

10:53 TimMc: CookedGryphon: If you've said more than your 2 messages as 10:34 and 10:45 ET, I missed them due to a probably router reboot.

10:54 legittalon: My native tongue is Javascript. Right now I’m interested in Clojurescript which seems pretty cool. But the parens are annoying but not insurmountably so. I’m also interested in Elm which is heavly influenced by Haskell.

10:55 I think the resources for Clojure are way better. I want a Haskell Koans.

10:55 ddellacosta: legittalon: fear of parens is absolutely the worst reason to not choose a lisp.

10:55 legittalon: It wouldn’t be the main reason.

10:56 Or really a reason.

10:56 TimMc: CookedGryphon: Can you give an example of the kind of test data you would like to send, and what the invariants are?

10:56 cbp: you get more twitter cred if you choose haskell

10:56 ddellacosta: legittalon: gotcha. Wasn't sure from your statement above, just wanted to make that clear...

10:56 ToxicFrog: I should try out clojurescript one of these days, now that I have an actual use for Javascript (specifically, making Android apps)

10:56 legittalon: Honestly I really WANT to learn Haskell first but I can’t find very good beginner resources.

10:57 dnolen_: legittalon: the classic books are good starting points, Simon Thompson or the Paul Hudak one

10:58 ddellacosta: legittalon: some Haskell folks are jerks but there are also a lot of friendly Haskell folks in #haskell. #nothaskell is also work a look.

10:58 dnolen_: I think both have relatively recent editions

10:58 ddellacosta: legittalon: which is to say, I bet they could give you some good tips too.

10:58 hyPiRion: legittalon: https://github.com/bitemyapp/learnhaskell/ and LYAH

10:58 cbp: there's that fp complete site and a bunch of online haskell courses

10:58 legittalon: Lol at the Clojure community being more helpful at learning Haskell than the Haskell community.

10:59 zerokarmaleft: legittalon: there's also an entire youtube series of lectures taught by wadler

10:59 legittalon: Awesome! Thanks for your resources.

11:00 hyPiRion: You've also got Real World Haskell, which I've heard is less theoretical than the other books. Not sure if that helps or not, but at least both are available online for free

11:01 ddellacosta: hyPiRion: I've heard that RWH is a bit dated, but that's hearsay from some folks in #haskell

11:01 CookedGryphon: TimMc: The current test is generating multi-touch input, each pointer starts with a :down, might have some number of :move events and ends with an :up or :cancel event. Each event coming through has a unique :touch-id and a persistent vector of all the touch coordinates since that pointer went :down

11:02 hyPiRion: ddellacosta: Hmm, maybe? I pick a bit here and there based on what I need to learn, but what I've seen so far in RWH is okay

11:02 CookedGryphon: TimMc: I am then checking that once all the events have run through, my system state is coherent (i.e. no buttons are stuck down or anything)

11:03 ddellacosta: hyPiRion: yeah, I just remember hearing someone mention the way it approaches exceptions, perhaps? Anyways, not to invalidate your point, probably still a great resource for beginners

11:03 CookedGryphon: and the chunking comes because in my actual implementation, for efficiency, I might skip any number of the events apart from the :up or :cancel

11:04 hyPiRion: ddellacosta: No worries, that may be the case. I'm not a good Haskell programmer, so it may very well be true

11:04 CookedGryphon: TimMc: ooh, I have just thought of a much more efficient way I could do this. I generate it as if there's an event coming through for every last coordinate, and then I randomly sample from that vector, as long as I can guarantee that I get the last point

11:05 ddellacosta: hyPiRion: I'm barely a Haskell programmer, so there is even less point for me to be talking about it...haha

11:06 TimMc: CookedGryphon: Careful with that "randomly sample" part.

11:07 CookedGryphon: TimMc: yeah, that's the bit I need help with, I know I need to make a reproducible generator

11:07 TimMc: Any randomness should be coming through test.check so that it can report the exact conditions of a failure and shrink the failures.

11:07 Or does test.check have a sampler?

11:08 hyPiRion: ddellacosta: heh. Sometimes I get an error with the message "Maybe you wanted to add the language extension X?", I add X and it works. And I how no idea why.

11:10 zerokarmaleft: ddellacosta: RWH is a bit dated, but the pedagogical approach is very good in places

11:10 CookedGryphon: TimMc: don't think so, but then I can always do what I was going to do before with the chunker vector

11:10 It would be nice if there was a cleaner way of doing it though

11:11 zerokarmaleft: hyPiRion: I've come to enjoy GHC's prescriptive error messages

11:12 ddellacosta: hyPiRion: I may possibly have had that experience using ghc...

11:12 zerokarmaleft: gotcha, good to know

11:12 zerokarmaleft: I do have to say, ghc's error messages kick the butt of Clojure's

11:13 but that's not really a fair competition

11:13 TimMc: CookedGryphon: Just ask for a sufficiently long list of random numbers that you can then massage into skips, repeats, chunkings, whatever.

11:13 * ddellacosta remembers he really has to go back to reading about logic and type theory and category theory so some day he will actually grasp Haskell

11:14 hyPiRion: zerokarmaleft: it's good error messages, I just don't understand what RankNTypes are, for instance

11:15 Or well, I kinda get it now, but eh

11:26 ToxicFrog: The type of something that returns [{} [] "a"] is (HVec Map Vec String), right?

11:28 seabre: ddellacosta: ghc is almost 22 years old, after all.

11:28 ddellacosta: seabre: what is that in regard to? that's amazing though, I didn't realize it was *that* old

11:29 seabre: ddellacosta: Well, you'd hope that in 22 years they'd figure out how to do error messages right.

11:29 and clojure is pretty young

11:29 ddellacosta: seabre: ah, yeah

11:29 seabre: Like 7 I think?

11:29 ddellacosta: seabre: but I think Clojure still has a bit of an unfair advantage there, considering we're dealing with the JVM here

11:30 in terms of exceptions. A sore spot for Clojure. ClojureScript error messages can be frustrating too. I mean, you certainly get used to them, but they are a weak point.

11:31 boodle: Hi, new to core.async, have ~100 values in a channel, can do all kinds of side-effect-ty things with them but want to return them as a seq/coll.. or sum them (transducers) but using 1.6.. any way to do this?

11:31 ddellacosta: er, I guess I meant Clojure has an unfair *disadvantage*

11:32 ToxicFrog: ddellacosta: while this is true to some extent, it does not excuse e.g. the compiler reporting syntax errors by crashing

11:33 ddellacosta: ToxicFrog: are you talking about ghc or clojure here?

11:33 tbaldridge: boodle: look at clojure.core.async/into

11:34 ToxicFrog: ddellacosta: clojure

11:36 boodle: tbaldridge: I did try that.. called close! on the chan before calling it but still getting an empty vector.. it doesn't need to be a go block or anything?

11:37 tbaldridge: boodle: I'd need to see some code

11:37 boodle: can you post a gist?

11:38 boodle: oh wait, it returns a chan, correct?

11:38 tbaldridge: boodle: yes

11:38 boodle: ah.. trying

11:51 tbaldridge: here's what I'm getting: https://www.refheap.com/90157 versus https://www.refheap.com/90159

11:52 tbaldridge: boodle, can I see the code thats writing to the channel?

11:52 boodle: I'm pretty sure you have a race condition somewhere

11:55 boodle: tbaldridge: probably due to this then: https://www.refheap.com/90160

11:56 tbaldridge: boodle: yeah, if you're getting an empty vector that probably means that whatever is closing the channel is closing it before the put! code completes

11:57 boodle: ah, any way to force put! to complete before taking? <!! ?

12:00 tbaldridge: not really (I haven't seen enough of your code to know for sure) but this code is async....so things will be async ;-)

12:00 boodle: the key is to not close the channel until all put!s are done

12:01 boodle: tbaldridge: sure but a bit stuck on the 'how'.. this is all being generated wihtin a page render (selmer template 'filters' acting as callbacks)

12:02 tbaldridge: well thank you for your time and help! Will look at redo-ing the selmer/filter stuff another way

12:25 lavokad: hi, what a is more "valuable, better" to learn for a studen of computer science in university. "Computer engineering" or "Software Engineering"?

12:26 daniel___: lavokad: what r u on about?

12:26 xemdetia: depends on your uni, but most unis 'computer engineering' is closer to EE stuff while software engineering is usually closer to CS

12:27 value depends on what you are trying to do

12:29 lavokad: here in Spain "Computer Engineering" module has Desing of operating systems, design of digital systems, technologies of networks, advanced architectures, embbeded systems, security, languages of parrelel computing, configuration of networks, distributed systems application develpment, real time

12:29 it is far from EE

12:29 that is why I cant decide...

12:30 jcsims: lavokad: which program sounds more interesting?

12:31 xemdetia: it also depends on your background too- uni is a great place to shore up where you are weak

12:31 when I went back to uni I focused more on math because I had a good foundation in systems programming

12:32 clgv: lavokad: software engineering usually has a lot of courses on how software projects should be organized

12:32 lavokad: well I think that sofware engineering is what I will need to know, when I start working, but the classes of "Software Engineering" are all about models, quality sofware, software design ...it is all about sofware organization

12:33 so maybe one can learn this reading a few books?

12:33 xemdetia: organizing the infrastructure to make good software is just as hard as writing code

12:33 lavokad: In this case i would choose "computer engineering" couse it will teach a lot of concepts about programming and computer in general

12:34 xemdetia:

12:34 ok :)

12:34 this is what I needed to hear

12:34 :D

12:34 xemdetia: lavokad, it's never wrong to actually go to the uni and ask

12:34 clgv: xemdetia: and even worse to measure ;)

12:34 xemdetia: something I did was look online at the syllabus for some of these classes and see what books they were using and what are the current 'popular books' on the outside

12:35 lavokad: I watched presentation videos, read their stuff, but it didnt make me decide

12:35 clgv: lavokad: yeah they usually have students counselors you can talk to

12:36 xemdetia: that's something that really helped me- some of the classes I took solely because it was a book I had not even heard of and it was very interesting (compiler theory, some computer crime law, etc)

12:36 it's not always obvious what the course covers by the syllabus at the higher levels

13:17 owengalenjones: can anyone see what is wrong with this ring/friend/compojure setup? basically any routes in public return an empty response /home works and /authorized seems to work but only redirects to /login which is empty https://www.refheap.com/90164

13:17 if I remove the call to authorize / authenticate then those routes work as well, something with how I'm using friend?

13:27 xeqi: owengalenjones: friend requires one of the params middleware, so it needs to be inside the site or api middleware

13:27 and I don't see a credential-fn, but maybe this is from a stripped down example

13:38 jeffterrell: Woohoo, Cognitect's webinar on Transit is starting in 20 minutes! http://go.cognitect.com/transitwebinar

13:39 mdrogalis: Webinar is one of my least favorite words. D:

13:39 Right up there with 'synergy'.

13:41 tbaldridge: mdrogalis: you need to embrace cross platform webinars in order to synergize your backward overflows

13:41 kenrestivo: refactor your webinar with synergy. it's agile

13:41 tbaldridge: mdrogalis: better yet: http://www.atrixnet.com/bs-generator.html

13:41 * kenrestivo ponders writing a buzzwrd-sentence generator

13:41 mdrogalis: tbaldridge: Gonna reach right through my monitor and slap you for that sentence.

13:41 kenrestivo: tbaldridge: beat me to it

13:42 mdrogalis: Oh this is lovely.

13:42 "efficiently reconceptualize resource maximizing networks"

13:42 dorkmafia: there are more people in #clojure than in ##java

13:43 tbaldridge: dorkmafia: might say more about the types of people that use IRC than anything else ;-)

13:43 dogonthehorizon: dorkmafia: I think that recently speaks to the go-getter, upward trending nature of the Clojure language

13:43 recently -> really

13:43 dorkmafia: heh

13:43 do irc rooms have a limit to the number of people?

13:43 tbaldridge: case-in-point, whenever I mention IRC to someone not in the fringes of programming the reaction I get is "IRC is still a thing?"

13:44 xemdetia: there are other groups that still use irc heavily aside from programmers

13:44 jeffterrell: I was pretty impressed at the last Cognitect webinar, on core.async.

13:44 dorkmafia: freenode is the place to be

13:45 * technomancy has flashbacks to futile attempts to get help with java libs on irc

13:45 jeffterrell: It's not a sales presentation, but a technical one, for Clojure folks like us.

13:45 technomancy: java channels are sad places where questions come to die

13:45 dogonthehorizon: It could also be that #clojure is an official channel while ##java is technically not? I don't know, I'm newer to the irc culture than most :P

13:45 kenrestivo: stackoverflow seems to have stolen a lot of the "how the hell do i...?" juice

13:46 xemdetia: irc just attracts a certain type of person

13:46 kenrestivo: quite honestly i feel a lot less stupid asking stackoverflow than asking on irc.

13:46 technomancy: kenrestivo: but then your question is memorialized for all time

13:47 kenrestivo: indeed, but so is the answer, and everyone else's too

13:47 and by "ask" i mean "google'

13:47 technomancy: oh, I thought you meant like if you were worried it was a stupid question

13:47 mdrogalis: tbaldridge: How do I use core.async channels with webinars? Is there an API for that?

13:47 kenrestivo: there's just such a volume of answers for common things, in languages like java and html, css, javascript, android, etc, on stackoverflow.

13:48 * tbaldridge not sure if mdrogalis is serious or trolling

13:48 mdrogalis: tbaldridge: I think someone needs a cup of coffee.

13:49 kenrestivo: but what irc does well is interspersing entertaining banter amongst the technical q&a's

13:50 xemdetia: irc also gets visibility to weird corner cases

13:50 which can be very interesting

13:51 technomancy: it's good for learning by osmosis

13:51 I feel almost qualified to answer certain clojurescript questions despite having never used it

13:51 onielfa: Hello, I need a book recommendation. I'd like to learn Clojure and I have 0 experience with lisp-like languages, but I have an intermediate experience with functional programming, Haskell in particular. I have access in a local book store to Clojure Programming, Programming Clojure and The joy of clojure 2edition. Which book you think will be better suit for me? Thanks in advance

13:52 xemdetia: onielfa, what's your favorite kind of pet project

13:52 oubiwann: onielfa: if you learn by looking at code, the Clojure Cookbook is a fantastic resource

13:52 aka: yeah the clojure cookbook is great

13:52 sorbo_: onielfa: I’ve read and liked The Joy of Clojure

13:53 oubiwann: onielfa: otherwise, all of the books you've mentioned are great (I own them all)

13:53 dogonthehorizon: onielfa: Currently working through the three you mentioned, Joy of Clojure 2ed has been my favorite so far. The pace is much quicker than the other two IMO.

13:53 sorbo_: what do y’all use for debugging Clojure? I mostly use tools.trace and the REPL, but not sure if there are better tools available

13:53 some have recommended hooking into the Java Debug Interface

13:54 but I sort of like to keep Java interop to a “use it when I need it” level

13:54 tbaldridge: onielfa: Joy of Clojure is probably the best Clojure book and it's a bit more advanced than the others. I'd start there and move to a different book of JoC is too advanced.

13:54 onielfa: xemdetia: Writing small backend services, for example

13:54 xemdetia: onielfa, hmm. not sure which is the best towards that end

13:54 onielfa: well

13:54 justin_smith: sorbo_: cursive is a clojure plugin for intellij idea that supports extensive debugging

13:54 aka: the webinar wll begin shortly please remain on the line...

13:55 onielfa: I am not interested in this kind of pet project

13:55 sorbo_: justin_smith: nice! I’ll look into it

13:55 I do like IntelliJ

13:55 onielfa: I am interested in learning the clojure way

13:55 the lisps concepts

13:55 xemdetia: there's nothing wrong with doing what you know the clojure way :)

13:55 onielfa: to change my mindset, the same way that Haskell did it

13:55 tbaldridge: onielfa: have you watched all the Rich Hickey talks/

13:56 xemdetia: yes that's probably a good concept starting place

13:56 justin_smith: sorbo_: there is also schmetterling, that hooks into jdi, and lets you interactively investigate state in stack frames in a very clojury way when exceptions are thrown. This is all done via websockets and a browser via clojurescript

13:56 sorbo_: I actually found that some of my philosophy courses from college were super helpful in understanding Clojure

13:56 particularly endurantism vs. perdurantism

13:56 owengalenjones: xeqi: sorry got called away, not sure I understand, friend/authenticate is getting called after the app routes get wrapped by the api-defaults

13:56 sorbo_: e.g. “this man is the same man as 10 years ago, only he’s changed since then”

13:56 and “‘this man’ is a process applied to two atoms from different points in time

13:56 justin_smith: sorbo_: no resume or step options in schmetterling though (I think cursive supports these)

13:56 sorbo_:

13:57 justin_smith: hmm, ok

13:57 justin_smith: sorbo_: Hickey references these concepts in some of his talks

13:57 sorbo_: still interesting, I’ll look at that one too

13:57 justin_smith: regarding state and identity

13:57 sorbo_: yeah

13:57 I need to watch more of Rich’s talks

13:57 tbaldridge: onielfa: I'd suggest watching most of these: http://thechangelog.com/rich-hickeys-greatest-hits/

13:57 sorbo_: coming from Ruby, I like having all the Lispy things I loved about Ruby

13:58 tbaldridge: onielfa: Rich really goes through and explains a lot of the reasoning behind Clojure

13:58 sorbo_: but also I think the Clojure way of thinking about state and identity is, if not “more correct,” easier for handling large distributed systems

13:58 justin_smith: sorbo_: very much so

13:58 bbloom: sorbo_: it's easier for handling tiny systems too :-P

13:58 sorbo_: bbloom: haha I believe it

13:58 I converted a Node project to Clojure and it was a genuinely delightful process

13:59 Bronsa: tbaldridge: I tried to link you this 2 times in the past but you were never here, take a look at this when you have a chance http://dev.clojure.org/jira/browse/ASYNC-86 :)

14:00 TimMc: sorbo_: I could really get into a presentation like "Identities and values as explained on Welcoem to Nightvale".

14:00 *Welcome

14:00 tbaldridge: Bronsa: thanks! I'll take a look and try to get it applied soon.

14:00 sorbo_: TimMc: oh man, that would be awesome

14:01 TimMc: "This man is the same man you knew yesterday... and yet he is not..."

14:02 Bronsa: tbaldridge: let me know if you have issues with that patch, it should fix a bunch of edge-cases around loops but also changes how some errors are handled

14:02 justin_smith: "ve have pervected ze prozess ov controlled mutation"

14:02 (que evil cackle)

14:03 Bronsa: tbaldridge: i.e before (go (fn [] (<! ..))) was a "whatever not found for dispatch value :fn", now it compiles fine and throws at runtime -- old behaviour can be restored if you want, just let me know

14:03 dbasch: TimMc: (not= myself (yesterday-me / 2))

14:03 I mean (/ yesterday-me 2)

14:04 justin_smith: hah

14:05 arguably the implied meaning of < rather than not=

14:05 dbasch: yeah, (< myself (/ yesterday-me 2

14:05 )) ;; can't type

14:09 justin_smith: clearly your irc client lacks paredit

14:09 sorbo_: I wonder if you can get paredit in irc from inside emacs

14:09 the answer is probably yes

14:10 xemdetia: sorbo_, erc is actually pretty nice

14:10 justin_smith: definitely yes

14:10 Bronsa: paredit on erc in my experience is unusable

14:10 justin_smith: also pretty useless

14:10 sorbo_: haha I see

14:10 justin_smith: "can you do <foo> in emacs" quickly becomes "is it actually sane to do <foo>"?

14:11 xemdetia: I use erc about 50% of the time actually

14:11 having autocomplete from irc chatter to whatever I'm working on is handy

14:12 justin_smith: it's my only client - it lowers cognitive overhead to have the same UI wherever the activity is primarily textual

14:12 xemdetia: justin_smith, I totally agree.

14:13 Jaood: irssi has basic emacs keybindings :P

14:14 the same ones you get in bash I guess

14:14 nullptr: i use erc and while i don't use paredit you at least get the general purpose paren highlighting

14:14 justin_smith: Jaood: lack of M-y kills it for me

14:14 xemdetia: Jaood, the point is that any tool I'm used to using is always there no matter what

14:14 justin_smith: to coin a phrase

14:14 nullptr: show-paren-mode

14:15 justin_smith: nullptr: or rainbow parens!

14:15 ToxicFrog: That'

14:15 zot: anybody use clostache, and happen to know of a simple way to use partials in a way that doesn't require knowing-in-advance which other templates have to be loaded? (i could use a regex parser to see, and load per template, but maybe i'm missing a more obvious/cleaner sol'n)

14:15 ToxicFrog: s something I really miss in ST. No rainbowparens.

14:17 onielfa: Sorry, I was away from the computer. Coming back to the clojure book recomendations. I have watched some of the Rich Hickey videos, and that's why I have so much interest in learning Clojure. I am very tempted to buy the The joy of Clojure but I don't know if it will be too much to start off.

14:19 justin_smith: onielfa: its a good book if you already have lisp background, but not a great intro level book

14:19 dbasch: onielfa: you should check it out, and if it's too much leave it for later. It's definitely worth reading at some point

14:19 Jaood: any opinions on smartparens vs paraedit? I started with smartparens and I haven't tried paraedit yet

14:20 technomancy: Jaood: afaict smartparens has the edge with non-lisps

14:20 Jaood: smartparens behaviour out of the box is pretty crap though

14:20 Jaood: technomancy: even using their default config?

14:20 technomancy: Jaood: last I checked

14:22 onielfa: justin_smith: so I buy joy and which one also to start off?

14:22 Jaood: I'm still tweaking it but their recommended default config didn't seem so bad to start with ;)

14:23 but maybe is just me not being a power user of that style of editing yet

14:23 justin_smith: ,(shuffle ["clojure" "programming"]) ; onielfa

14:23 clojurebot: ["clojure" "programming"]

14:23 justin_smith: it could have been the opposite easily :)

14:24 dogonthehorizon: Clojure Programming is a bit shorter in length, FWIW

14:24 sorry, reverse that

14:24 Programming Clojure*

14:24 Jaood: onielfa: Clojure programming is nice to start with, you really only need like half of book ;)

14:24 +the

14:25 justin_smith: glad to hear the shuffle chose wisely

14:28 dbasch: onielfa: you can also start with a good intro on the web, and move on to tjoc when you feel ready

14:29 onielfa: e.g. http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome or http://www.braveclojure.com/

14:31 dorkmafia: when you use a create a checkouts dir and use a local library does it pick up that projects deps?

14:33 justin_smith: dorkmafia: I find using "lein install" to add my lib to the private local repo and then adding it as a normal dep to be much simpler than checkouts

14:35 technomancy: dorkmafia: checkout deps are not transitive

14:35 guest889: any clojurians from Egypt¿

14:37 dorkmafia: justin_smith: if i do that and update the lib will it just pick up the changes?

14:37 justin_smith: dorkmafia: no, you will need to re-run "lein install"

14:38 dorkmafia: that is the drawback

14:38 but that is still simpler than checkouts, in my experience

14:38 dorkmafia: ah ic well checkouts isn't so bad then heh

14:38 justin_smith: have you ever used jython?

14:38 justin_smith: I've used tools that embedded it, but I have not programmed with it directly

14:39 dorkmafia: i'm trying to figure out how to get it to use my lib

14:39 well the skype4py lib

14:40 blaenk: I'm trying to figure out why my project hangs on lein uberjar on a separate computer

14:40 it works perfectly fine on mine

14:41 I diff'ed lein deps :tree from both and they're identical, if that's any indication of anything

14:41 justin_smith: lein versions?

14:41 writable directory?

14:41 blaenk: I also looked around for anything that may be evaluating at compile-time but I didn't find anything, and afterall the same exact code is working on the one computer

14:41 will check

14:41 mdrogalis: Can anyone think of a way to use something like Schema to validate that a map is solely composed of keywords?

14:42 (arbitrarily deeply map)

14:42 blaenk: justin_smith: yeah they're identical versions. 2.4.3, perms are fine too

14:43 justin_smith: weird

14:43 blaenk: yeah, very

14:43 it just prints out one message, 'compiling <some.ns>' but there's nothing unusual about that ns

14:43 hiredman: blaenk: likely you are doing something sideeffecty in a top level form, which clojure executes, and it happens to hang on one computer and not the other

14:43 (def db (connect-to-db-with-infinite-retries))

14:43 blaenk: they're the same compilers too though. but yeah I looked around for something like that and the only thing I could find was a kroma defdb form

14:44 ahh, wasn't aware of retries

14:44 will try removing that for now

14:44 justin_smith: blaenk: you can use jstack to find out what lein is doing while hung

14:44 hiredman: I mean, I dunno

14:44 blaenk: thanks I'll check that out

14:45 justin_smith: jstack <pid-of-lein>

14:45 blaenk: awesome

14:46 hiredman: well, the lein pid won't tell you much, you need the pid of the child jvm

14:46 (project jvm or whatever lein calls it)

14:46 justin_smith: hiredman: good point

14:47 blaenk: yeah I got that one

14:47 dorkmafia: is there a way to force clojure to run on 32 bit jvm?

14:48 hiredman: dorkmafia: if you use a 32bit jvm to run clojure it runs on a 32bit jvm

14:48 justin_smith: dorkmafia: you can tell lein which jvm to use :jvm-cmd

14:48 (in project.clj)

14:48 hiredman: clojure doesn't pick a jvm to run on, it is just a jar

14:48 justin_smith: there is an env var too

14:48 blaenk: I think I got the correct pid, and it seems like it's waiting for something https://gist.github.com/blaenk/bf8edfea2b2b3b2599a9

14:48 hiredman: clojurebot: lein

14:48 clojurebot: lein is http://github.com/technomancy/leiningen

14:48 hiredman: clojurebot: lein |is not| clojure

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

14:49 hiredman: blaenk: that is the lein jvm, not the project jvm

14:49 dorkmafia: coo i'll check out the jvm-cmd thanks

14:49 justin_smith: dorkmafia: env LEIN_JAVA_CMD="/path/to/32bit/jvm" lein ...

14:49 blaenk: hmm

14:49 hiredman: jps will list the pids of running jvms

14:49 blaenk: thanks

14:49 dorkmafia: can i put that in my .lein profiles?

14:49 hiredman: unfortunately clojure jvms tend to just show up with the name "main"

14:49 blaenk: yeah haha

14:50 sorbo_: just coming back to this, +1 for http://www.braveclojure.com/

14:50 blaenk: I think I found the project one. it's the one with a large classpath right?

14:50 dorkmafia: there is also jvm-opts

14:50 blaenk: with all my project's dependencies

14:50 sorbo_: sort of a spiritual successor to _why’s guide (Ruby)

14:50 justin_smith: blaenk: yes, probably

14:51 blaenk: alright I updated it https://gist.github.com/blaenk/bf8edfea2b2b3b2599a9

14:52 looks like line 130

14:52 justin_smith: blaenk: that thread that is at FileDescriptor.sync looks suspicious to me - it should not be spending very long on that

14:52 blaenk: oh yeah, 130 does look suspicious :)

14:52 blaenk: seems like something with pandect

14:52 line 107 I think more so

14:52 SegFaultAX: sorbo_: Haven't thought about _why's stuff in a while.

14:52 blaenk: yeah I think it's pandect

14:53 look at line 61, pandect

14:53 sorbo_: SegFaultAX: yeah, ditto. I think about him and his work every now and then

14:53 wonder what he’s up to these days

14:53 justin_smith: blaenk: so I had the right stack trace, just alerted to a different suspicious part of it :)

14:53 SegFaultAX: sorbo_: Probably still being awesome. :)

14:54 sorbo_: hopefully!

14:54 blaenk: weird thing is I'm using pandect on my computer too, and it doesn't cause any problems there

14:54 justin_smith: blaenk: it is trying to download something, maybe it is a cached download, so you don't notice it locally

14:55 blaenk: wow, surprised it's trying to download something

14:55 justin_smith: maybe I am misreading that...

14:55 blaenk: definitely seems like pandect though no?

14:55 https://github.com/xsc/pandect

14:56 amalloy: justin_smith: what?? what makes you think it's trying to download something? it looks like it's trying to write a classfile while AOT compiling

14:56 elben: I need to (do a b c), but return b. On the top of my head, I can think of using try/finally, or a temp atom, or (let [_ a r b _ c] r). Any other idea?

14:56 hiredman: yeah, I see nothing in the stacktrace about downloading anything

14:57 technomancy: elben: sometimes doto can be handy for that

14:57 amalloy: one of the namespaces that pandect.impl.message-digest depends on could be generating arbitrarily-many classfiles, via some infinite loop at compile time

14:57 justin_smith: amalloy: oh, right. I totally misread what was happening there.

14:58 elben: technomancy: not useful here, because ‘a’ and ‘b’ are java interops for resetting and closing a stream object

14:58 amalloy: https://github.com/xsc/pandect/blob/master/src/clojure/pandect/gen/hash_generator.clj looks vaguely suspicious with the nested defprotocols, but i don't think it's really an issue

14:58 blaenk: there's a new stacktrace, I'll paste it

14:58 I mean, it's been running and I just noticed that jstack shows something new, same style though

14:58 okay, it's actually compiling the rest of the files now, it's like it was caught up on something

14:59 it's like it took ages to compile pandect, or something

14:59 amalloy: blaenk: are you running this on a really slow filesystem, like over sshfs or something silly like that?

14:59 hiredman: maybe pandect probes the jvm to see what digests it supports and generates class files based on that and the jvms are different and one supports lots of digests

14:59 blaenk: nah, well I'm ssh'ed to the other computer but no not on a mounted remote fs or anything

14:59 sounds plausible

15:01 it's compiling stuff, it seems, from running jstack multiple times, it's just going very slow

15:01 the computer is much faster than mine however

15:02 barely 2/64GBs used

15:02 and very low load across the 8 cores

15:02 amalloy: GBs...used...? what does that have to do with faster?

15:02 blaenk: the disk is the bottleneck here, nothing else

15:02 blaenk: nothing, I was wondering if maybe it was low on memory and so it was going to disk? idk

15:02 justin_smith: amalloy: less data fighting for CPU cache lines?

15:04 blaenk: well at least now that the files are cached, it doesn't take too long to rebuild

15:04 I guess at first I thought it was hung since it was taking forever, waited 5 minutes for it on the same ns

15:06 TimMc: amalloy_: I've been wonderinf if my encrypted filesystem is why compiling CLojure is so slow on my machine.

15:06 hiredman: definitely

15:07 TimMc: Is that based on write-then-read latency? Throughput is generally good on this fs...

15:07 justin_smith: TimMc: I have had much luck with putting non-sensitive / higher data throughput needed stuff on a secondary drive. Luckily those things often go together for me.

15:08 hiredman: compared to what?

15:09 TimMc: hiredman: I dunno, I just don't have trouble reading/writing large files.

15:09 justin_smith: I've seriously considered mounting a ramdisk for target...

15:12 hiredman: encrypted filesystems encrypt things, non-encrypted filesystems don't, encrypted filesystems do more, doing more takes more, qed

15:13 I could easily imagine an encrypted filesystem were large files are the optimal case

15:13 TimMc: hiredman: Right, but it doesn't noticeably impact most operations on my computer -- compiling Clojure is ht eonly thing that seems to be a problem.

15:14 Jaood: all those little class files

15:14 TimMc: I sprinkled a codebase with printlns and :verboses and it was compiling a defn once a second. :-(

15:15 hiredman: that does seem excesively slow

15:15 TimMc: (possibly a factor 2 on either side of that)

15:15 Another reason to get rid of AOT!

15:16 hiredman: I would check to see if you have the same problem outside of lein

15:16 TimMc: Maybe write a program to slurp all the classfiles out of a target/ and spit them somewhere else?

15:16 or you mean compile "manually"

15:17 hiredman: that

15:17 TimMc: Worth a try.

15:17 owengalenjones: can anyone see what is wrong with this ring/friend/compojure setup? basically any routes in public return an empty response; /home works and /authorized seems to work but only redirects to /login which is empty https://www.refheap.com/90164 If I remove the call to authorize / authenticate then those routes work as well, some problem with how I'm using friend?

15:18 TimMc: I should also try compiling on a ramdisk.

15:29 xeqi: owengalenjones: (-> app defaults authenticate) does authenticate first, then the default middleware, then the app routes

15:30 for getting an opportunity to modify/handle the request

15:30 but friend needs the params middleware to have already happened

15:31 owengalenjones: xeqi: if I reverse the threading so that authenticate is first, then any of the routes results in chrome downloading an empty file

15:32 xeqi: you don't need to reverse all of them. You still want app to be the last one to handle the request

15:33 just defaults and authenticate. That way the default middlewares handle the request first, then friend gets to look at it, then your app handles it

15:34 owengalenjones: xeqi: sorry I mean if the app-site threading is reversed https://www.refheap.com/90174 then hitting any route except for /home results in chrome downloading an empty file instead of displaying html

15:39 hiredman: that defroutes at the bottom looks weird

15:39 (but maybe that works to concatenate routes, and I've just never done it)

15:39 owengalenjones: hiredman: I believe so, at least I have found several examples of people combining routes like that

15:40 xeqi: owengalenjones: what happens if you switch the order the routes in site-and-api?

15:41 so that public-site is first

15:42 bulters: anyone here watched the videos from purelyfunctional.tv?

15:43 owengalenjones: xeqi: then the routes from public work but the ones from app return an empty response :-/

15:44 amalloy: TimMc: the clojure compiler calls fsync all the time. that's probably not the optimized-for usage on an encrypted fs

15:44 TimMc: amalloy: Aha.

15:44 amalloy: (note, eg, that blaenk's compiler was stuck on fsync every time he got a stacktrace from it)

15:45 owengalenjones: having two different routes wrapped with handler/site-defaults looks super-sketchy

15:46 that sounds like the kind of route that wants to be last and only-once

15:46 owengalenjones: amalloy: right thats an artifact, Im trying to wrap one in site-defaults and the other in api-defaults

15:48 amalloy: you can't just have two top-level-looking routes one after another. like if your route/not-found is before any of your other routes, it will trigger before them and cause them never to be looked at. the stuff in wrap-defaults could be similar

15:54 arohner: is there a way to check if a core.async channel has something in it, without taking?

15:54 or blocking

15:57 bbloom: arohner: any such query would risk a race condition

15:58 amalloy: bbloom: only if you presume that the next <! should be guaranteed to not block

15:58 it could be useful as a diagnostic feature for approximating stuff, like is my channel usually full or usually empty

15:59 fifosine: Here: http://clojuredocs.org/clojure_core/clojure.core/defstruct, someone has commented that it's preferred to use defrecord over defstruct as defstruct is obsolete. Is this true?

15:59 amalloy: yes

15:59 arohner: ok, acquiring the lock is fine. I don't want to take, and I don't want to block until a value goes on the chan

15:59 hiredman: I think it is better to think of channels as a synchronization point, not as a collection that contains things

15:59 amalloy: arohner: you want to not block, but acquiring a lock is fine??

15:59 lazybot: amalloy: Definitely not.

16:00 hiredman: that said, there is value in able to ask "is someone waiting here?"

16:00 arohner: amalloy: I changed my mind about 'block'

16:00 dnolen_: arohner: there's no way to do that and there is unlikely to ever be.

16:00 bbloom: arohner: rewind a step and explain more generally about what you're trying to accomplish

16:01 hiredman: juc has some nice things for that, I find phasers are very useful

16:01 arohner: I have a thread that's in an infinite loop processing events as they arrive. I need a signal to stop the thread

16:01 stuartsierra: arohner: Closest you can get is `alt!` with a default and :priority true.

16:01 arohner: I know I can use a second go-loop, just felt verbose

16:01 bbloom: arohner: yeah, use two channels + alt

16:02 hiredman: arohner: either close the channel it recieves on, or have another channel to signal close

16:11 tbaldridge: arohner: the problem with looking but not taking is that the answer will often be wrong. Perfect way to create a race condition.

16:16 xeqi: owengalenjones: working example - https://www.refheap.com/90176

16:18 it looks like handler/site-defaults happening twice would cause a problem

16:18 probably something similar for site-defaults and api-defaults

16:19 I usually try to use a `context` to move all of the authenticated routes somewhere, so that the different middlewares can be applied safely once

16:20 something like (routes (context "/app" (-> app-routes friend api-middleware)) (-> public-routes site-middleware))

16:22 possibly with a 404 as the last one in app-routes, since there is an url difference between app and public

16:24 owengalenjones: xeqi: ahhhh yes

16:25 also

16:26 xemdetia: Is there anything better than base64

16:26 for doing base64 things

16:27 TimMc: base65

16:27 owengalenjones: xeqi: thank you so much, this was driving me crazy

16:29 xemdetia: TimMc, the sad thing is I see a base65 on github

16:29 now I don't know if you are lying to me or not

16:33 TimMc: :-D

16:34 Base64 is good because 6 and 8 have a relatively high GCD.

16:34 err

16:34 xeqi: owengalenjones: np. I seem to have gottne the flash stuff wrong, but hopefully you can take it in the way you need from here

16:34 TimMc: not 1, that is :-)

16:38 amalloy: huh, interesting. if you disassemble (fn [] [0]), it turns out that the value [0] is stored in the class's constant pool as an AFn. i would have expected either PersistentVector or Object; something in the middle is weird

16:38 xemdetia: yeah TimMc I'm just suddenly faced with the problem of 'base64 isn't quite small enough'

16:40 TimMc: xemdetia: What bytes *can't* you use?

16:40 xemdetia: exactly all of them are important

16:40 I need to squeeze the source more

16:40 amalloy: just use base2. send it in binary

16:40 technomancy: pff--morse code, come on

16:40 amalloy: it turns out this is the underlying transport used by ethernet

16:41 dbasch: xemdetia: bitcoin uses base58

16:41 xemdetia: amalloy, for what I am doing the underlying transport is humanz

16:41 hence base64

16:41 amalloy: so use like, base 26

16:41 maybe 36

16:41 dbasch: xemdetia: base58 was meant to remove human ambiguity when reading

16:41 xemdetia: dbasch, that's interesting

16:42 amalloy: dbasch: i see. 58 removes O0o Il1 or something?

16:42 dbasch: amalloy: yes http://en.wikipedia.org/wiki/Base58

16:42 technomancy: base25; remove the ambiguity between U and V for ancient roman users.

16:42 amalloy: technomancy: you need to scale down to 24 for rome

16:43 technomancy: sorry, "AMBIGVITY"

16:43 amalloy: oh right, I and J too

16:43 clojurenoob: greetings!

16:44 nairobi: clojurenoob: hello

16:44 clojurenoob: I have a very simple question that I've been unable to resolve with stack overflow inquries...

16:44 If I have two vectors, how do I determine which entries appear on one vector but not on theh other?

16:45 I've been playing with map and .indexOf and filters but they all seem to fail on me for some reason

16:45 bbloom: clojurenoob: what else can you tell us about the vectors? size, order, etc

16:45 clojurenoob: lets say for example, twenty items in each vector

16:46 order does not matter

16:46 bbloom: do the simplest possible thing: convert to a set, use filter, etc

16:46 ,(require 'clojure.set)

16:46 clojurebot: nil

16:46 nullptr: ,(difference (set [1 2 3]) (set [2 3 4]))

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

16:46 TimMc: amalloy: What do you mean [0] gets stored as an AFn? Like, something that implements IPersistentVector and so forth?

16:47 clojurenoob: alright lets try that.

16:47 nullptr: ,(clojure.set/difference (set [1 2 3]) (set [2 3 4]))

16:47 clojurebot: #{1}

16:47 amalloy: TimMc: i mean, the concrete class is obviously PersistentVector. but it's stored like: public static AFn const__0;

16:47 dbasch: ,(remove (into #{} [1 2 3 4 5]) [2 3 4 5 6 7])

16:47 clojurebot: (6 7)

16:47 clojurenoob: thanks, brb, let me try this out

16:48 bbloom: dbasch: (into #{} ...) is just clojure.core/set

16:48 dbasch: bbloom: yes, but shorter :)

16:49 amalloy: and then the static initializer is something boring like static {const__0 = new PersistentVector(new Object[] {0});}, of course. i just found it interesting that the declared type is AFn

16:49 dbasch: bbloom: actually longer, never mind

16:49 habit

16:52 clojurenoob: YAY! Fantastic thanks for your help.

16:52 both solutions worked

16:52 So thank dbasch and nullptr

16:53 TimMc: amalloy: Ah, weird indeed.

16:53 clojurenoob: much appreciated

16:54 dbasch: bbloom: actually into #{} is much faster than set

16:54 bbloom: (source set)

16:54 ,(source set)

16:54 clojurebot: Source not found\n

16:54 bbloom: &(source set)

16:54 lazybot: java.lang.RuntimeException: Unable to resolve symbol: source in this context

16:54 bbloom: $source set

16:54 lazybot: set is http://is.gd/Mya7JM

16:55 bbloom: dbasch: if that's the case, it sounds like clojure.core/set is just broken

16:55 amalloy: bbloom: yes

16:55 it doesn't use transients

16:55 technomancy: it's just old

16:55 bbloom: surely there should be a ticket for this....

16:56 amalloy: so maybe i'm stupid, but i only today realized i can use no.disassemble to disassemble arbitrary java objects, not just clojure functions

17:01 noncom|2: if (def my-symbol "java.io.File") then how do i pass it to import so that (import my-sympol) would be equal to (import 'java.io.File") ?

17:01 clojurenoob: I am really enjoying functional programming. Once you get past theh mindscrew of not having loops, vars, mutability, etc... It can be quite a bit of fun!

17:02 bbloom: clojurenoob: more of a mind UNscrew :-)

17:05 clojurenoob: yeah, when you putit htat way...

17:05 noncom|2: figured out: (eval `(import ~my-symbol))

17:06 amalloy: noncom|2: that is just a totally bizarre thing to do. you don't need to import a class to use it

17:06 all import does is let you save some characters when typing the class's name; if you don't know the name at compile time, you're obviously never typing it, so what is the import buying you?

17:06 if for some reason you really wanted to do it, you don't need to eval: import is just a function: (import (symbol my-symbol))

17:06 noncom|2: amalloy: really..

17:07 right, i do not have to import it..

17:08 i can do (.newInstance (Class/forName "ClassName"))

17:09 yeah..

17:09 amalloy: what are you doing that makes you think you want to use eval, class/forName, and runtime import? if you're not writing an IDE or a repl or something, or *maybe* a plugin system, you probably don't need any of those things

17:13 noncom|2: amalloy: an kind of an ide, right. :)

17:13 rweir: highly recommend explaining precisely what you're doing, since it feels very XY-y

17:14 (same thing happens in python a lot - people discover eval/exec/__import__/etc and start using them when there are much simpler solutions for whatever they're doing)

17:16 noncom|2: rweir: umm.. well, i have a media software development IDE built on top of the jmonkeyengine 3 which has to load and run java sketches written in processing in order to pass the texture they generato into a jmonkey texture in real time..

17:16 so the sketches can be dynamically loaded from files in any time too

17:16 since textures for sketches can be created in real time

17:17 so them are like plugins too... yeah, i guess youre right

17:19 still i think that using a classloader for the java source files will prove right in the end..

17:30 ghadishayban: bbloom: there is in fact a ticket for set+transient

17:30 as well as zipmap

17:46 noncom|2: oh no, again i am having the problem with leiningen being unable to find javac... could somebody please remind a fix to this..

17:46 i have added jdk path to PATH

17:47 zot: is there a way to cross this java/class boundary? (filter .isFile (file-seq (io/file "/tmp")))

17:47 CompilerException java.lang.RuntimeException: Unable to resolve symbol: .isFile in this context, ...

17:50 tuft: zot: (filter #(.isFile %) [])

17:51 zot: ironically i just thought to try that. and while it does compile, it returned directories. i must be doing sth else stupid.

17:53 ghadishayban: ,*clojure-version*

17:53 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

17:54 ghadishayban: ,(transduce (map inc)

17:54 (completing conj! persistent!)

17:54 (transient [])

17:54 [1 2 3 4 5])

17:54 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:54 ghadishayban: ,(transduce (map inc) (completing conj! persistent!) (transient []) [1 2 3 4 5])

17:54 clojurebot: [2 3 4 5 6]

17:54 ghadishayban: love that new idiom

17:54 amalloy: i don't think it's so much an idiom as a function

17:54 justin_smith: very cool

17:59 noncom|2: does anyone use ccw here ? how do i setup the path for javac for ccw ?

17:59 justin_smith: noncom|2: any particular reason to using ccw instead of cursive?

18:00 oh, different IDE, never mind

18:00 noncom|2: yeah, just being an eclipse fan... idea is good too, but historically i happen to use eclipse.. would you advice trying cursive ?

18:01 i also try emacs..

18:01 justin_smith: emacs is a whole other fish, if you already have a favorite environment it makes sense to stick with that

18:01 I just forgot that ccw wasn't for idea

18:28 celwell: Hi, if I have a vector of maps, what is an idiomatic way to get the map that contains a certain value for a specific key? (e.g., get the map that has an :id of 5 in [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}], ultimately I need to get "Tom".)

18:32 amalloy: celwell: ideally you would use a more suitable data structure, like a map from ids to attributes

18:32 celwell: amalloy: well it's coming from another func that get's it from a database

18:33 justin_smith: celwell: group-by helps

18:33 amalloy: sure, and once you're done reading from the database, put it into a useable data structure

18:33 you don't want your whole program to be scanning back and forth over rows forever just because that's how the database gives you values

18:34 celwell: group-by should work nicely, thanks forgot about that

18:34 falafel: ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}]

18:34 (filter #(= (:id %) 5))

18:34 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:34 falafel: ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}] (filter #(= (:id %) 5))

18:34 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:34 falafel: ok

18:35 (->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}](filter #(= (:id %) 5)))

18:35 ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}] (filter #(= (:id %) 5))

18:35 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

18:36 falafel: ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}](filter #(= (:id %) 5)))

18:36 clojurebot: ({:name "Tom", :id 5})

18:36 falafel: finally!

18:36 amalloy: falafel: type it into a real repl, get it working, then demonstrate here :P

18:36 falafel: lol

18:36 amalloy: I did, but I was copy/pasting from vim from the wrong buffer

18:37 justin_smith: ,((group-by :name [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}]) "Tom")

18:37 clojurebot: [{:name "Tom", :id 5}]

18:37 celwell: falafel: every vim buffer is wrong, should have used emacs. thanks though.

18:37 falafel: lol, carpal tunnel no thanks

18:44 justin_smith: turning caps lock into a control key, and control into xcomponse, has had very nice results

18:44 amalloy: thumb? hitting Ctl with a thumb seems pretty hard

18:45 p_l: amalloy: the trick is to use opposite hands

18:45 celwell: justin_smith: I had caps for C- but i still had pinky pain, i guess i'm just weak

18:45 justin_smith: maybe you just type more than me

18:45 p_l: though I'll admit to remapping caps from habit :)

18:46 amalloy: p_l: i'm aware of that trick, but i still dno't know how i would hit either control key with either thumb, without having to go way off home row

18:46 justin_smith: also, I have a kinesis freestyle, which allows my hands to be further apart, which helps with just about everything

18:46 amalloy: justin_smith: i've had caps-as-ctl for years now, but i've just left ctl as another control. i guess compose sounds pretty nice, maybe i should try it

18:46 p_l: amalloy: doesn't help that many modern keyboards, well, suck

18:47 amalloy: mine sucks, but it's full size. not a mac mini keyboard lite

18:47 celwell: justin_smith: i play guitar and piano in my downtime so my fingers don't really get a break

18:47 justin_smith: celwell: viola here

18:48 clojurenoob: question, how reaistic is using lighttable for a smaller clojure project?

18:49 is it normal to have so many people joining and leaving in such short intervals?

18:49 p_l: clojurenoob: do you need to deal with non-clojure parts?

18:49 and yes, that's why many people have filters that hide joins/parts

18:49 clojurenoob: p_l some text files, but I haven't hit too many issues so far.

18:50 amalloy: clojurenoob: yes, that's pretty normal. it's a crowded room. you want to configure your client to hide at least most of those

18:50 p_l: clojurenoob: I meant mostly in terms of "calling java" :)

18:50 my experience was rather... bad

18:50 amalloy: mine hides join/part of anyone who hasn't been talking ni the last few minutes

18:50 clojurenoob: ah right, nope. NO real libraries I plan on using

18:50 I'd use eclipse or something to navigate the infinite namespace that is the java core...

18:50 celwell: clojurenoob: ibdknox (creator) seems to be online.

18:50 justin_smith: clojurenoob: for a small enough project, you could probably get away with using ed. light table should be fine.

18:51 clojurenoob: seriously, celwell? That's awesome.

18:51 justin_smith: in the channel doesn't mean paying attention to the channel, but yeah ibdknox is logged in

18:58 amalloy: justin_smith: now that i've turned on my compose key, i can type devilments like this: (let [a 1, a 2] a) ;=> 1

18:59 justin_smith: see, the benefits start already

18:59 luckily, emacs displays nbsp in a bright underlined face

19:00 amalloy: yeah. i have a hard time telling it apart from underscore, in emacs, but i guess it is different

19:03 Bronsa:  _

19:03 you can definitely tell them apart when they're near

19:49 stompyj: whats the “correct” way to require the “HEAD” version of a lib that has fixes you need, but hasn’t been pushed to clojars yet/

19:49 fork+self-publish?

19:50 amalloy: stompyj: yeah

19:50 stompyj: danke

19:56 dbasch: bbloom: you probably saw this ticket already http://dev.clojure.org/jira/browse/CLJ-1384

19:56 noonian: can also just lein install locally if you don't need to publish your code right now

19:56 splunk: is there an easy way to identify namespace dependency cycles

19:57 justin_smith: splunk: don't they fail to compile?

19:57 johncash: why does (keyword INT) return nil rather than throw exception?

19:57 splunk: justin_smith: not clear--possibly?

19:58 justin_smith: not sure what type of error message to expect with a cycle

19:58 noonian: splunk: you won't be able to run the code or load it in a repl, it will give some message about a dependency cycle hehe

19:58 splunk: noonian: ah okay thanks. so what I have must be something else.

19:58 noonian: thanks!!

19:59 noonian: splunk: welcome!

19:59 ,(keyword INT)

19:59 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: INT in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:00 noonian: ,(keyword 8)

20:00 clojurebot: nil

20:00 justin_smith: splunk: Caused by: java.lang.Exception: Cyclic load dependency: [ /cyclic/core ]->/cyclic/big->/cyclic/apple->[ /cyclic/core ]

20:00 that's with a three way dependency circle

20:01 first line of the exception: Exception in thread "main" java.lang.Exception: Cyclic load dependency: [ /cyclic/core ]->/cyclic/big->/cyclic/apple->[ /cyclic/core ], compiling:(cyclic/big.clj:1:1)

20:01 much clearer than most clojure errors actually

20:04 splunk: haha indeed

20:05 I'm working with `lein test-refresh` and all of a sudden it's giving me protocol loading errors. Probably something I just broke. Thanks.

20:05 noonian: splunk: i'd recommend running lein clean every once in a while

20:05 if you are aot compiling you can get protocol errors similar to that

20:06 justin_smith: splunk: protocols and reloading code don't work together very nicely

20:06 noonian: well, lein test-refresh stays running, reloading namespaces and rerunning tests, that is going to break with protocols I would think

20:06 amalloy: it's just the angry spirit of technomancy, come alive in your code to remind you that he hates protocols

20:06 justin_smith: heh

20:07 splunk: curssesss!!!

20:08 technomancy: don't say I didn't warn you

20:08 splunk: holy smokes, yes, we tried to turn on AOT for uberjar, and yes lein clean just fixed a whole bunch of it

20:09 noonian: justin_smith: yeah, i work around those issues by using a 'reloaded'ish workflow, but i don't use anything as fancy as test-refresh

20:09 technomancy: every time someone says "lein clean fixed my problem" I hear "lein clean removed the symptoms of my problem so I can continue without addressing the actual cause"

20:10 splunk: technomancy: what in your mind is the problem? the protocols, as opposed to the reloading?

20:10 or the reloading is the problem?

20:10 technomancy: reloading is what makes programming not unbearably tedious

20:11 dbasch: technomancy: bearably tedious?

20:11 justin_smith: technomancy: http://i.imgur.com/tXkAcGY.jpg

20:11 splunk: okay, so it's just a question of making the protocols compatible with the reloading. I've heard, as noonian just mentioned, that the "reloaded" workflow is supposed to solve this

20:12 technomancy: but supporting reloading well has a cost in terms of performance in very tight bottlenecks; protocols are designed to allow you to improve performance in exchange for reloading support, which is what you have to do to get self-hosted

20:12 splunk: because, something something, objects/values in memory get re-initialized with proper references to the properly reloaded protocols

20:15 okay, so the goal would be get abstractions and/or polymorphic dispatch without the protocols.

20:15 multimethods being available the solve the latter, and like, something else longer discussion for the former about what it means to flexibly support abstractions / expression problem, whatever.

20:16 noonian: splunk: i'd also try to avoid storing state in Vars and just have your entry point function build your system

20:22 splunk: noonian: yeah I have to dig into somebody else's code to uproot that

20:23 jfojtl: hi, is there any sample web application written in clojure? Something that could server as a tutorial, but complete app?

20:24 technomancy: jfojtl: https://syme.herokuapp.com maybe; it's ~500 lines but complete and nontrivial.

20:25 splunk: jfojtl: also, see more: https://github.com/clojure-cookbook/clojure-cookbook/tree/master/07_webapps

20:25 dbasch: jfojtl: and https://devcenter.heroku.com/articles/clojure-web-application

20:26 jfojtl: thanks guys

20:26 will check it out. I knew about the cookbook, however I did not consider that as a complete app

20:28 technomancy: that's what I like about clojure. Non trivial things solved in trivial/simple/short ways

20:46 bbloom: here's a crazy question one of you fun crazy people may be able to answer.... YourKit's memory profiler can tell me which objects are highly referenced, but is there a way to get it (or something else) to tell me which / how-many / what-percentage-of objects have a ref count of 1?

20:48 ghadishayban: bbloom: step one, jmap -dump for a heap dump

20:48 step two: browse the generated heap dump with 'jhat', another built in tool

20:49 bbloom: ghadishayban: ok thanks i'll check those two out

20:50 ghadishayban: it starts a webserver that allows you to (among other things) run a little SQL dialect over the heap graph

20:52 bbloom: ghadishayban: holy hell, this is awesome

20:54 ghadishayban: I don't know how to do it with YourKit, but jhat and jmap are built into openjdk

20:54 bbloom: ghadishayban: do you know if there is a way to run such a query without the browser?

20:54 ie in the console & get plain text out?

21:07 ghadishayban: might take like 10 minutes to start depending on the size of the dumped heap

21:11 cfleming: bbloom: Eclipse MAT is also really useful for those sorts of things, it also has a query language

21:11 Bird|otherbox: will add-break-thread! allow a thread to be broken into via Ctrl-C if it's stuck in code completely outside the JVM's purview? (i.e. passing something to a native library that leads to a runaway exercise bike of sorts, my personal experience was with SQLite + JDBC taking a day or more to produce an OutOfMemoryException after a buggy join generated a result set almost 4 *billion* rows long)

21:12 cfleming: bbloom: An ex-workmate of mine was a wizard with the OQL, but I never played with it much myself.

21:13 zenoli: Anyone else having an issue with CIDER? I just updated, and I'm now getting "No response handler with id nil found".

21:13 The debug output points to nrepl-client-filter as the origin.

21:16 The error happens when trying to connect to an externally started REPL, and connection does not complete.

21:17 Version is 2014912.503.

21:17 zeitue: question what book would be good for a beginner who has no programming knowledge to learn Clojure?

21:18 Bird|otherbox: I'd probably be more inclined to start them in another language first

21:18 Clojure is still in a phase where the tooling is a bit immature and even intimidating

21:18 TEttinger: Bird|otherbox, yeah like java maybe. java's a surprisingly good language for beginners

21:19 Bird|otherbox: (some of the exceptions I get at the REPL somedays leave me scratching *my* head)

21:19 zeitue: yeah the java exceptions are pretty bad

21:19 Bird|otherbox: TEttinger: I'd personally argue that Python would be a better starting point. Java's *too* limiting

21:20 TEttinger: or even javascript, since you really need almost nothing to get started and can apply the knowledge quickly

21:20 zeitue: I see your point guys

21:44 technomancy: racket is great for beginner programmers

21:44 http://htdp.org <3

21:45 much easier to transition to clojure from later since they already have homoiconicity and immutability by default

21:45 plus the educational materials are top notch

21:45 oh, he left =(

21:48 catern: but muh sicp

21:53 kenrestivo: huh, start-stop-daemon really hates lein bin.

21:54 i guess lein bin emits things that look like ":;exec java -XX:PerfDataSamplingInterval=10000 -client -D .....", and start-stop-daemon can't exec them

21:55 truebuddi: technomancy: any advice for experienced OO dev to "thinking in clojure" ?

21:55 justin_s`: agreed Re: racket for new programmers

21:55 (inc racket)

21:56 justin_smith: (inc technomancy)

21:56 (for the racket suggestion)

22:00 truebuddi: justin_smith: based on yday discussion wrote some clj at https://gist.github.com/krishnabhargav/2a92da3f5f161c7da197 .. you mind taking a quick review for some expert tips?

22:01 justin_smith: truebuddi: checking it out

22:02 akhudek: truebuddi: I slightly prefer update-in rather than how you use assoc in +people and -people

22:02 justin_smith: truebuddi: or assoc-in

22:02 agreed

22:03 truebuddi: akhudek: will try it

22:04 justin_smith: also, something like name - for one, it is shadowing clojure.core/name which will cause an annoying warning message, for another, it is kind of pointless, it is better to document the :name key and expect it to be used directly

22:04 I understand the urge to abstract, but assoc is already abstracted - it works on maps or records

22:05 akhudek: yes, agreed

22:05 justin_smith: the way you use default-trip is definitely good - but take out the static magic (the call to (t/today) - because it makes the time the app booted "magic"

22:06 you can use a defn if you want it to always make the current day default

22:06 truebuddi: so instead of a def defaut-trip make a defn default-trip ?

22:06 justin_smith: truebuddi: remember that unlike ie. python/php/ruby you probably have one app instance that stays running for months at a time

22:06 right

22:07 truebuddi: but then doesnt it "go against" FP that function call each time returns a different value?

22:07 justin_smith: though immutible/static is better than dynamic when possible - it's just not compatible with the "today" thing

22:07 right, but you are the one who decided it should be today, and today is not immutible

22:08 a good compromise would be to make default-trip immutible and leave out the datas, then new-trip attach the dynamic defaults (the date part)

22:08 *parts

22:09 overall, for beginner clojure code, it's quite excellent though

22:10 what I like to do for usage examples is put the whole working code fragment inside (comment ...)

22:10 truebuddi: justin_smith: thank you ... ok

22:10 justin_smith: that way their editor will syntax highlight it like normal code

22:10 akhudek: good old bottom of the file tests

22:11 truebuddi: if conj for multiple items is "into" whats for "disj" ?

22:11 justin_smith: not a test, really - I see a usage example as a special form of added documentation :)

22:11 akhudek: in this case, yes :-)

22:11 justin_smith: truebuddi: conj already works with multiple items

22:11 and dissoc works with multiple items too

22:11 if they are in a collection, you can use apply

22:12 ,(apply dissoc {:a 0 :b 1 :c 2} [:a :b])

22:12 clojurebot: {:c 2}

22:12 truebuddi: hmm ...

22:12 justin_smith: oh, but these are sets, calling disj

22:13 ,(apply disj #{:a :b :c :d} [:a :b :d])

22:13 clojurebot: #{:c}

22:13 justin_smith: though into is just fine - just pointing out that apply conj works too

22:13 truebuddi: also if i use update-in .. i did a (update-in trip [:people] into persons) ... adds all persons into ;people set .. but if i replace into with conj it adds one item into set

22:14 akhudek: truebuddi: yes, you want into there

22:14 justin_smith: remember I said apply conj

22:15 akhudek: apply conj won’t work well with update-in

22:15 justin_smith: ,,(apply conj #{:a} [:b :c :d :e])

22:15 clojurebot: #{:e :c :b :d :a}

22:15 akhudek: since it will thread the previous value after apply

22:15 justin_smith: yeah, good point, into is a better choice all around

22:15 truebuddi: so whats for "-person" .. into puts in .. anything to take out ?

22:16 justin_smith: there is apply disj, or clojure.set/difference

22:16 akhudek: not that difference expects two sets

22:16 justin_smith: ,,(clojure.set/difference #{:a :b :c :d :e} [:a :b])

22:16 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

22:17 justin_smith: ,(do (require 'clojure.set) (clojure.set/difference #{:a :b :c :d :e} [:a :b])) ;; akhudek: nope

22:17 clojurebot: #{:e :c :d}

22:17 akhudek: oh interesting

22:17 justin_smith: just the first arg matters there

22:18 one thing I love about clojure is how fast you can become an "expert" if you have a small bit of curiosity and an open repl all the time

22:18 (inc clojure)

22:18 lazy-ass lazybot

22:19 probably out partying

22:19 truebuddi: whats a lazybot?

22:19 justin_smith: it's a bot on this channel, that implements our silly "karma" system

22:19 truebuddi: i see you can exec clojure code with "," ... interesting

22:19 justin_smith: yeah, it's a great tool for demonstrating how things work, or proving who is right without needing to dig up hyperlinks

22:20 you can also message clojurebot (though usually using your own repl will be more convenient I am sure)

22:22 truebuddi: good to know ...

22:25 ncthom91: hey y'all. How can I apply two forms to the "logical true" case of an if block?

22:25 justin_smith: ncthom91: do

22:25 ,(if 1 (do (print :OK) 2))

22:25 clojurebot: :OK2

22:26 ncthom91: justin_smith thanks :)

22:29 truebuddi: updated https://gist.github.com/krishnabhargav/2a92da3f5f161c7da197 with your comments

22:31 is the thread-first -> in the usage a good practice?

22:31 justin_smith: truebuddi: one more little thing - assoc is varargs

22:31 (in the example that is)

22:31 ,(assoc {} ;a 0 :b 1 :c 2)

22:31 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:32 justin_smith: ,(assoc {} :a 0 :b 1 :c 2)

22:32 clojurebot: {:c 2, :b 1, :a 0}

22:33 truebuddi: thanks for the input ..

22:35 justin_smith: oh, and I used clojure.set/difference in my code for laziness / convenience purposes here, but it's best to require clojure.set :as set in your ns block, and use set/difference

22:37 ncthom91: can anyone explain a quick syntax thing to me? in the memoize source code (http://clojuredocs.org/clojure_core/clojure.core/memoize) there's a call `(find @mem args)`

22:37 what is the @ symbol for?

22:38 justin_smith: ncthom91: it is a a reader syntax for (deref ...)

22:38 ,(macroexpand @foo)

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

22:38 justin_smith: ,(macroexpand '@foo)

22:38 clojurebot: (clojure.core/deref foo)

22:38 justin_smith: there we go

22:38 macroexpand will often help with the weirder parts of clojure

22:38 truebuddi: btw clojuredocs.org is outdated and theres a new docs site with some complex name ... saw it on r/clojure the otherday

22:38 ncthom91: interesting

22:39 justin_smith: truebuddi: ncthom91: yeah grimoire

22:39 http://grimoire.arrdem.com/

22:39 ncthom91: so (let [mem (atom {})]) assigns a reference to `mem`, not an actual map

22:39 makes sense

22:39 justin_smith: yeah, that's what atom does

22:39 ncthom91: reminds me of my ocaml days

22:39 justin_smith: yeah, ocaml and clojure share some important concepts

22:39 though sadly ocaml never figured out how to do proper concurrent gc

22:40 ncthom91: i never got that far into ocaml :P

22:41 truebuddi: justin_smith: when i do a (def current-trip (default-trip)) I am actually executing the function only once right?

22:41 and I remember reading somewhere that you can "redef" the same by doing a (def ...) again ...

22:43 justin_smith: truebuddi: true on both counts - you can use defonce if the ns may get reloaded but it is important for correcness that the def not be re-bound

22:43 *correctness (ironic typo)

22:44 truebuddi: but remember that this would make the boot time of your app "magic" - your app doesn't start up fresh for each request unlike some languages

22:45 I have sites that have uptimes of months before being restarted

22:45 truebuddi: I am just trying to now think where i would use a ref here

22:45 justin_smith: why would you use a ref?

22:45 truebuddi: exactly ... am trying to find a use case for ref ..

22:45 justin_smith: haha

22:45 tbaldridge: truebuddi: and now you have reached enlightenment....

22:46 michaniskin: truebuddi: justin_smith conj.io is easier to remember than grimoire

22:46 truebuddi: like i have a (def app-state []) ... technically i can "redef" it anytime i want to add to my app-state right?

22:46 justin_smith: michaniskin: cool, did not know about that URL

22:46 tbaldridge: people come to Clojure for the STM, and stay for everything else

22:46 justin_smith: truebuddi: don't use def at runtime, it has no sane concurrency semantics

22:47 truebuddi: that said, you usually don't need STM, atoms and maybe the occasional lock should suffice

22:47 (inc tbaldridge)

22:47 I am so inc-happy tonight, and no lazybot

22:47 tbaldridge: lol, it's the thought that counts

22:48 truebuddi: let me get this ... [] is immutable .. so any modification doesnt effect other concurrent users .. and in the worst case the def again will give stale values right?

22:48 justin_smith: truebuddi: right, but you can lose updates

22:48 truebuddi: yes .. in case of concurrent updates ... true

22:48 justin_smith: think of what happens if two threads read the current value, calculate a new one, and redef, at nearly the same time

22:48 right

22:49 you can solve this with atoms, refs, locks, or even local state in a core.async go block, depending on what you are attempting to do

22:50 in our experience, usually refs are not needed

22:50 truebuddi: also i have a general Java question about asynchronous IO in java ... in the .NET world, we have async calls where in the thread doesnt get blocked and there is a IO completion port that handles the "waiting" so to speak and calls back when the call is completed ... i cant find such a thing in Java .. usual recommendation is make a call on a diff thread or a thread pool thread ...

22:50 tbaldridge: truebuddi: that's kindof what core.async is for

22:51 not Java, but clojure

22:51 justin_smith: truebuddi: there is also java.nio, but core.async is a much better api

22:51 java.nio is the more async-friendly update to java.io that comes with java 7

22:51 truebuddi: so if i make 1000 async server calls ... it isnt really going to spawn 1000 background threads right?

22:51 justin_smith: truebuddi: not with core.async, no

22:51 tbaldridge: with core.async, no

22:52 lol

22:52 justin_smith: it's the #clojure chorus

22:52 truebuddi: what about jdbc calls? does core.async help here as well>

22:52 tbaldridge: you'd need an async DB interface, but using that with core.async isn't hard

22:52 justin_smith: truebuddi: it can, if you wrap your jdbc usage in channel usage - I can see that working

22:53 * justin_smith tags off to tbaldridge (no need for us to say everything twice)

22:54 tbaldridge: lol, go ahead justin_smith

22:54 truebuddi: what do you mean by async DB interface? I thought the whole JDBC protocol doesnt have anything non-blocking in design?

22:57 sarcher: database access at the jdbc layer is not asynchronous

22:57 justin_smith: to quote tbaldridge https://groups.google.com/d/msg/clojure/Aj2njGQtPN0/PMVOigU2fDAJ

22:57 (regarding what tbaldridge would have meant by async db interface)

22:58 sarcher: you can asynchronously perform db updates though using jdbc and core async i would assume.

22:58 justin_smith: right, as shown in some code in the link above

22:58 truebuddi: thanks for the link . but there you can see (thread ... ) .. so there is indeed a thread being created

22:58 justin_smith: for the db interaction, yes

22:59 but it's not a thread per interaction

22:59 it's a thread that handles the interactions

22:59 you can create as many as you like, and if they read/write the same channels, they scale transperently

22:59 truebuddi: so a thread is spawned ... it receives input through channels .. and for each input does some "db" work

22:59 right?

22:59 justin_smith: so you can decide how many need to exist

23:00 right

23:00 truebuddi: so if channel has a queue then long running db op can block the others in the same channel ...

23:00 justin_smith: and any number of threads can be spawning queries on the db based on grabbing them from the same channel

23:00 no

23:00 channels don't work like that

23:01 if you have two threads reading from the channel, you can have two requests at a given time. Given that your bottleneck isn't CPU, it's network bandwidth (and some latency on the db end that scales with the nubmer of requests) a fixed size thread pool works nicely

23:02 you can experiment to find the number of threads that performs optimally - beyond a certain count, you should see throughput drop when you increase the concurrency (due to the i/o bottlenecks)

23:03 truebuddi: hmm

23:03 so when you do a (chan 4) ... channel with buffer of size 4 is created right?

23:03 justin_smith: right

23:06 truebuddi: so in tbaldridge example, he spawns 4 threads all reading from the same channel ... so 4 db operations could be done in parallel on 4 threads

23:06 justin_smith: right

23:08 but unlike most thread pools, you wouldn't tune the pool size based on CPUs available, but based on the performance of the db (and factors like whether it is remote, network latency, db engine latency, etc.).

23:09 truebuddi: in a web app where you own/manage the deployment and constantly monitor .. may be tuning it by yourself is sufficient but imagine you are making servers that gets "sold" and the customer does his/her deployments ... tuning is going to be tricky

23:11 justin_smith: right, but you should be able to get a very good picture of the performance characteristics with load testing

23:11 and with a well designed app, you can access the back end and configure things like the thread count without a redeploy

23:11 (of course telling them "never ever touch this config" and finally telling them how to do it if it is needed)

23:12 truebuddi: but things like these only comes with experience (or getting burnt before) so when you build something you dont really worry about these until late (atleast where I work)

23:12 justin_smith: right, but you can design such that these things can be flexible in the future

23:12 and clojure has some nice features that ease that

23:13 clojure is very good at helping you prevent brittleness in apps, if you let it help you

23:13 truebuddi: anyway point is .. with all the cool innovations that happens on JVM .. it's a little surprising of not having a non-blocking db access ...

23:13 justin_smith: truebuddi: it would just end up being some defaults on top of threads anyway. It's not like the jvm implementors have access to something you as a dev don't functionality wise.

23:14 on this count at least

23:14 though, a good easy to use async db lib would be awesome. I bet you could write it if you put your mind to it :)

23:15 (in clojure, of course)

23:15 truebuddi: haha..honestly i dont see how adding any layer ontop of jdbc can smooth it out ...

23:15 justin_smith: I say in Clojure because the bottlenecks are emphatically not in the CPU or heap usage of the app, so switching to java would be unlikely to gain you much

23:16 the layer just makes it easier - the bottleneck isn't in the jvm, so a layer of abstraction will be a small constant factor, not a complexity increasing performance drain

23:17 truebuddi: layer cannot make something blocking at heart, non-blocking ... whether you see it blocking or not depends on the layer i guess

23:17 anyway you use a lot of "promise"/"future" in clojure? or does core.async replace all those

23:17 justin_smith: on the contrary, if it uses threads it can - and that is how your hypothetical java async db api would have to work

23:18 I use future a lot

23:18 I consider promise an implementation detail that creates futures

23:18 future is good sometimes, core.async others - I don't consider future out of date at all

23:18 agents are great too

23:19 in fact agents for an async db api would likely be a pretty good match

23:19 truebuddi: i always get confused between future ånd a promise

23:19 justin_smith: agents use a thread pool, you can deref a specific agent to get its result, or query as to whether it is ready...

23:19 a promise is just a thing you can deliver to

23:20 futures use the promises as an implementation detail, and deliver to the promise from another thread

23:20 or that's how I think of it, it might not be precisely and literally like that in clojure

23:21 yeah, future doesn't literally use promises

23:21 but that's the relationship - future is explicitly about threads, promises are more general

23:22 truebuddi: future { result = somework; result} .. somework is done only once .. and promise is just a placeholder that someone else delivers the value .. right?

23:22 justin_smith: or you could deliver to it yourself

23:22 it's just a thing that goes from not yet having a derefable value, to later having one

23:23 for example you could have one promise, and spawn N futures that could each fill the promise, first one to find an answer wins

23:23 truebuddi: any simple example of future with a thread?

23:23 justin_smith: future uses a thread, always

23:23 truebuddi: so i dont have to create a thread myself?

23:24 justin_smith: (dotimes [_ 10] (future (mapv println (range 10))))

23:24 I can't make clojurebot do that, he hates threads

23:25 truebuddi: and future uses threadpool?

23:26 justin_smith: it creates a java.util.concurrent.Future

23:26 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

23:27 xeqi: it uses the agent send-off pool

23:27 justin_smith: $source future

23:28 xeqi: yeah, I am seeing that now

23:28 (.submit clojure.lang.Agent/soloExecutor ^Callable f)

23:28 truebuddi: whats that?

23:28 justin_smith: that is a quote from the source of future

23:29 and here is the definition of soloeExecutor https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Agent.java#L53

23:29 it is a pool

23:30 a static field on Agent

23:30 truebuddi: and do we have things like .. when-all .. when-any ?

23:30 justin_smith: we have realized?

23:30 (every? realized? futures)

23:30 (filter realized? futures)

23:30 etc.

23:31 if futures is a list of futures that have been spawned

23:31 err. sequential, I mean sequential of course :)

23:31 hell, maybe even group-by would be useful here

23:32 truebuddi: that only allows u to check if they are ready to read from or not ... my intent with when-any was like (when-any future-list #(str %1 " retuns answer : " %2))

23:33 where i "assumed" it returns a future and its answer in the result ... jus as an example

23:34 justin_smith: ok, use (filter realized?) and act on the first, or map on all results

23:35 or group-by realized, so you can act on all the ones that are done, and set aside all that are not done to check later

23:35 (by which I mean call recur with the list under the false key)

23:37 truebuddi: say i have 5 futures each of which talks to a http mirror ... we r really interested in only one answer and the first one to answer is what we are interested about .. if i do a filter .. none of them may be realized yet .. so i try again .. and again ... and again ... but this is basically spinning and spinning ...

23:38 justin_smith: truebuddi: you can poll, or as I mentioned above, ask them all to attempt to fulfill the same promise, and then block on the promise

23:38 then, cancel all futures once the promise comes through (cancel on a finished future is fine, it's a no-op)

23:39 truebuddi: i m going to try it out .. anyway cancellation is not guaranteed right

23:39 justin_smith: (doc future-cancel)

23:39 clojurebot: "([f]); Cancels the future, if possible."

23:39 justin_smith: that doc string is pure poetry, I swear

23:40 truebuddi: lol

23:40 justin_smith: it's been a favorite of mine, before I ever needed to use future-cancel

23:45 xeqi: future-cancel => if the future hasn't started, it won't be, but if the future has been started then the code would have to cooperate with shutting down

23:46 by checking Thread/interrupted and handling it gracefully

23:46 irrc

23:51 justin_smith: xeqi: cool, good to know

23:52 as I think about that task more - I wonder how often the latency at the other end of the http request is the main bottleneck (such that starting multiple requests and cancelling all but the one that finished makes sense)

23:52 also, if I was running the service you were hitting with that kind of usage pattern, I would probably be annoyed

23:54 at a certain point, fewer parallel requests will perform better, as your interface or network saturate. The interesting question is whether that point is > 2 or not

23:58 catern: the (or foo bar default) trick is so useful and I can even use it in Python

23:58 justin_smith: heh, indeed

23:58 catern: are there any other such cross-language tricks that I could learn about from Clojure?

23:59 justin_smith: the value of immutible data (the trick is how well the language can fake immutibility of course)

Logging service provided by n01se.net