#clojure log - Oct 15 2013

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

0:00 Raynes: &(doc some-fn)

0:00 lazybot: ⇒ "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns the first logical true value returned by one of its composing predicates against any of its arguments, else it returns logical false. Note that f is short-circu... https://www.refheap.com/19823

0:03 tsantos: Raynes: that sure looks like what I wanted. Testing it out...

0:07 Raynes: yep, works like a charm, thanks.

0:08 * Raynes high fives tsantos enthusiastically.

0:31 yeoj___: jjkk/quit

1:03 dobry-den: (File. (clojure.java.io/resource "test.jpg")) ; Error, File doesn't know type URL.

1:04 (File. (.toURI (clojure.java.io/resource "test.jpg"))) ; Success

1:04 -__-

1:16 satshaba2: (:key value) vs (value :key) ------- Fight!

1:17 no really which is prefered?

1:22 SegFaultAX: If your keys are keywords, prefer using the keywords in function position.

1:23 Raynes: Whichever one looks best in context.

1:23 satshaba2: hmmmm

1:24 Well I come from python so I'm more inclined for (mapthing :key)

1:24 i.e. mapthing[key]

1:25 but it might make sense to do (:key mapthing) because then I think "key of mapthing"

1:26 SegFaultAX: To me (:kw foo) is pretty unambiguous in most situations. (foo :kw) could be a lookup or a normal function call.

1:27 satshaba2: ahh yes I see

1:27 ok then (:kw foo) it is!

1:28 SegFaultAX: satshaba2: Pick a style and stick with it, that's the most important thing.

1:28 satshaba2: yes agreed. I pick (:kw foo)

1:28 SegFaultAX: I just prefer to use (:kw foo) because it's more visually obvious that I'm doing a lookup.

1:28 Cool.

1:35 bitemyapp: SegFaultAX: I do the same thing.

1:35 (:kw foo)

1:35 SegFaultAX: the other reason to do it is that some map-like data structures will not implement IFn

1:35 such as datomic entities.

1:36 satshaba2: ^^

1:39 SegFaultAX: bitemyapp: Yup

2:30 logic_prog: is there a clojurescript cookbook ?

2:35 ered: i just started running through https://github.com/magomimmo/modern-cljs and i'm already impressed

2:35 jonasen: logic_prog: I don't think so

2:35 ered: speaking of clojurescript anyway

2:35 logic_prog: the pre-requisite for that page aone would take a year to read

2:36 ered: i'm only so far into this as idiomatic-for-javascript-but-just-ported-to-clojurescript (.getElementById js/document "email")

2:37 and even just adding a repl that i can talk to my browser is still really cool

2:37 can't wait to see what this looks like later on when it actually gets to idiomatic clojure

2:46 shoshin: hello, ping.

2:46 i have a question that i've been trying to work through a bit.

2:47 how do i access a value that is present inside a vector.

2:47 sm0ke: ,([1 2 3] 1)

2:47 clojurebot: 2

2:47 shoshin: [{:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}] i want to access the values of key :a

2:48 sm0ke

2:48 ^^

2:48 sm0ke: ,(map [{:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}] :a)

2:48 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword>

2:48 sm0ke: oops wait

2:48 ,(map :a [{:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}])

2:48 clojurebot: (1 4)

2:48 sm0ke: hehe i am still learning too

2:49 shoshin: sm0ke thank you! I need to dig more into map and clojure's data structures.

2:49 any resources/pointers?

2:49 sm0ke: shoshin: the vector which you gave has each element as a map

2:50 shadower: now keyword also act as fucntions on maps like ##(:key {:key :value})

2:50 lazybot: ⇒ :value

2:50 sm0ke: finally the (map) function runs the function passed as first argument on each element of collection and returns the new collection

2:51 oops he left

2:56 hey guys in my project.clj i have defined a :main namespace and also a profile {:package {:aot :all}} ,, but when i gnerate a uberjar using 'lien with-profile uberjar'and try to run with 'java -cp my.jar main.name_space' ,,i get 'could not find or load main class main.name_space'

2:56 also i see that namespace being compiled while generating uberjar

3:01 i workaround this by putting (:gen-class) in my main namespace..but i dont know if this is the correct way

3:01 terom: you will need :gen-class for AOT, so it is not a workaround, but requirement, afaik

3:03 sm0ke: i really dont understand what compilation mean in leinigen

3:03 llasram: You don't need :gen-class for AOT, but you do need :gen-class for AOT to produce an actual *class* for the namespace

3:03 sm0ke: is compiling and generating class different?

3:03 llasram: Yes

3:04 sm0ke: really?

3:04 llasram: So on the JVM you do need an actual class to hold bytecode for any functions as method

3:04 sm0ke: isnt compilation means generating class on jvm?

3:04 llasram: The way Clojure does that is by having a class per function

3:05 So doing AOT will pre-generate the classes for all of your functions

3:05 sm0ke: but not my namespace?

3:05 llasram: Exactly. You only get a class for a namespace with e.g. your static main by specifying that that namespace should :gen-class

3:06 That said, you don't need to AOT and :gen-class to get an entry-point, or really even an uberjar entrypoint, even if you really need that

3:06 My preferred approach is to use the `clojure.main` class included in Clojure

3:06 sm0ke: hmm didnt know about that

3:06 llasram: then you can do: java -cp my-uberjar.jar clojure.main -m my.name.space

3:07 And that will run the `-main` method in my.name.space

3:07 sm0ke: oh i see

3:08 llasram: worked like a charm thanks!

3:08 i guess using that approach we can have multiple main methods too

3:08 in deifferent namespaces though

3:10 llasram: You can also call `clojure.main` with `-e <string>` to `eval` some arbitrary string

3:12 Jarda: if I have a dependency from clojars that is causing me trouble, how can I install it locally to get possibility to fix it

3:13 I mean, is there a way of doing git-dependencies or such with leiningen2

3:13 terom: llasram: Hmm. I usually produce uberjars so that I can java -jar my-uber.jar, but that didn't occur to my mind that I could then also do that. Seems logical though, now that I think more of that.

3:13 ered: Jarda: try lein-localrepo?

3:13 https://github.com/kumarshantanu/lein-localrepo

3:14 there might be something better than that

3:14 llasram: Jarda: If the project is using lein already, you don't need a plugin. Just checkout and `lein install`

3:14 (w/in the project)

3:14 ered: oh that's easier than mine :D

3:15 Jarda: llasram: so if my project is in ~/projects/myproject, where should I checkout the dependency?

3:15 oh, or do you mean it can be wherever and leiningen will just know where to fetch the dependency

3:15 llasram: Oh, well

3:16 So if you `lein install` it'll install the version that project's project.clj declares it to be; i.e., probably some SNAPSHOT release

3:16 If you just want to pull the dep in as source in your project, that's what "checkout" dependencies are for

3:17 Check the second project out wherever you like, then

3:17 in your project create a directory called "checkouts", and w/in that dir make a symlink for the dependency named for the dependency artifact basename

3:18 Just linking to the dependency project top-level directory

3:18 The lein doco has more details

3:19 Jarda: https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies ?

3:19 thanks :)

3:19 ered: llasram: neat, i'll have to remember that one

3:19 llasram: terom: Yeah. I used them when I first started doing Clojure, but at this point I'm actually not entirely certain what uberjar main functions are really for. I *always* need e.g. a wrapper shell script anyway

3:19 Jarda: yep, and np!

3:19 sm0ke: i think the only problem is when the external project installs on ivy

3:19 ered: i have a few things i'm going to be working on soon where i'll be working on a project, but also a couple supporting libraries, in parallel

3:19 sm0ke: lein cant fetch from local ivy repos

3:20 llasram: Yeah, if the external dep doesn't use lein, then you need to e.g. use `mvn` (or maybe lein-localrepo -- haven't used) to make it available locally

3:20 sm0ke: but who uses ivy anyways..

3:21 no one uses scala from clojure is guess

3:21 llasram: At least not directly much thus-far

3:22 terom: llasram: true, I seem to find that also. In some rare cases I just want to run uberjar as-is. I guess if I have some GUI application it makes more sense. (On Windows, I can then just double-click the .jar to launch it)

3:23 sm0ke: i think clojure interop with scala will be nasty..specially with Scala people using case classes almost everywhere

3:23 i dont know how well clojure treats case classes

3:24 llasram: terom: Yeah, that may be true. Although the one time I've needed that so far, I used the `lein-exec` approach of embedding a prefix combo sh/.bat script at the beginning of the file

3:24 sm0ke: also one more with with that clojure.main approach.. i had to replace underscore with hyphen

3:24 dont know what thats all about

3:25 llasram: sm0ke: Does your namespace have an '_' in it?

3:25 sm0ke: yes

3:25 llasram: Interesting

3:25 &(map munge ["some-name" "same_name"])

3:25 lazybot: ⇒ ("some_name" "same_name")

3:26 llasram: Clojure name munging for JVM representation isn't reversible

3:26 And since "-" is munged to "_"

3:26 using "_" kind of humorously can get you into trouble sometimes

3:26 Best to just stick w/ convention and use "-" :-)

3:27 sm0ke: llasram: no no wait i think you misunderstood

3:27 llasram: TOO LATE

3:27 sm0ke: llasram: i have _ in my namespace's parent folder name

3:27 like org_some/namespace

3:28 inside clojure file i write it as org-some.namespace

3:28 i think thats the convention in clojure

3:28 llasram: Oh, ok, yeah. So the actual name of the namespace is "org-some.namespace", which is in fact what you need to pass to clojure.main

3:30 sm0ke: llasram: yes but if you put (:gen-class) in yu ns and invoke it deirectly via java -jar you have to put _ in main ns

3:30 llasram: sm0ke: Right -- because then you're directly feeding the munged JVM name to the `java` command

3:31 sm0ke: hmm ok weird enough.. i am just wondering why didnt i make a folder by name 'org-some' in the first place then

3:33 aha .. http://stackoverflow.com/questions/4420944/why-does-clojure-convert-dashes-in-names-to-underscores-in-the-filesystem/4451693#4451693

3:34 so much for java interop

3:34 llasram: Yeah, that's the ultimate reason. And for directories is just simpler -- otherwise your build tool would need to munge each directory name when adding stuff to the JAR, which has a lot of confusion-potential

3:34 Especially for e.g. resources

3:36 sm0ke: yeah makes sense

3:37 but i really was hoping clojure.main would automatically convert between _ and - by itself for its argument

3:38 anyhoo its trivial to nag for

3:38 llasram: Eh. It explicitly takes the Clojure namespace name. You can't in Clojure (:require 'org_some.namespace)

3:39 sm0ke: got it!

3:54 glosoli: How does one define snippet in Enlive with optional arguments ?

4:02 muhoo: why (-> (foo "bar") baz quuz) not (-> "bar" foo baz quuz) ? i see that pattern and wonder why

4:03 llasram: muhoo: Starting with (foo "bar"), adding the -> and not thinking about it is my guess :-)

4:03 I did see someone once here claim that they found e.g. (-> "some-path" io/file .exists) confusing though

4:09 muhoo: it is kind of rpn-ish i guess

4:09 in datomic it's common to have (->> (d/q '[massive bunch of stuff ]) foo bar baz) though

4:10 llasram: Huh

4:10 Interesting

4:11 muhoo: but if there's just one arg to that first function, i don't see why not just thread it in with everything else

4:11 llasram: Yeah, I'm with you there

5:06 talios: 'lo cemerick

5:08 cemerick: talios: Hi Mark :-)

5:08 * talios commits his first clojure to the main project at work this week, sure its still in gerrit reviews, but still :)

5:09 talios: using pristmatic schema of course, gotta have my types!

5:09 * glosoli is happy that folks at work using Clojure for any new project

5:10 dcunit3d: where do u work lol

5:10 * talios forked clojure.osgi and brought it up to date with 1.5.1 first tho, hopefully that'll be our first open source release, if not - I'll probably release it to maven central under my own GAV

5:10 glosoli: dcunit3d: lol, we find it easier to collect and manager your data with Clojure :D

5:10 at NSA :DD

5:10 dcunit3d: lol

5:10 talios: dcunit3d: http://www.smxemail.com - move to New Zealand and work for us ;)

5:11 glosoli: dcunit3d: Small company in Europe Lithuania :) you wouldn't know ;d

5:11 Still kinda fun though

5:11 talios: tho currently we're desperate for some coffeescript/javascript skilz

5:11 cemerick: talios: good deal. No typed clojure tho?

5:11 dcunit3d: new zealand sounds fun. anywhere with good mountains sounds fun

5:12 i'm currently in boulder, but haven't found much clojure here yet

5:12 talios: cemerick: looking at it :) we have ambrose on the podcast again last week, I see schema plans to maybe also compile out core.typed annotations which could be good

5:12 dcunit3d: colorado

5:12 cemerick: dcunit3d: talios uses osgi *voluntarily*. Serious warning sign, right? ;-P

5:12 talios: yup, I heard, enjoyed it :-)

5:12 talios: lolz, if we could drop it we would. Altho, I'd rather keep OSGi and dump hibernate first :)(

5:13 cemerick: had to do some 'creative' editing with the intro to ambrose as we wern't sure if he was showing up or not, then turned up in the middle of recording ;0

5:14 cemerick: i'm missing your show - record!!!

5:14 glosoli: what kind of show ?

5:15 cemerick: talios: yeah, I know. It's been tough to squeeze it in of late. :-(

5:16 talios: glosoli: cemerick's clojure podcast, and my "generic software development maven build love/hate scala/clojure/frege" podcast

5:16 glosoli: talios: where??

5:16 lazybot: glosoli: Definitely not.

5:16 llasram: Is lazybot a bit spastic???

5:16 lazybot: llasram: Oh, absolutely.

5:17 talios: glosoli: http://www.illegalargument.com/ is mine, latest show has Ambrose on talking about core.typed ( his 2nd appearance )

5:17 cemerick: glosoli: http://mostlylazy.com

5:17 talios: cemerick himself is mostly lazy, so hasn't recording in a LONG time.

5:17 glosoli: Damn guys, thanks! :)

5:18 cemerick: talios: that was an intentional reference :-)

5:18 I didn't want people to think it'd be a regular thing...but I didn't mean for it to be quarterly, either.

5:18 talios: glosoli: I think the two interviews with Ambrose, and the one we did with James Ladd on Redline Smalltalk are our most listened to shows ( and most enjoyable to record )

5:19 glosoli: talios: I never heard of them... (a bit out of date here) will have to catch up today! :)

5:19 talios: cemerick: could you worse, you could have been like arbscht and started "The Weekly REPL" podcast, do 4 episodes and stop :)

5:19 cemerick: hah, yeah

5:21 talios: for awhile, we considered getting arbscht on our show regularly, but then we'd have 3 cohosts all at the same company :)

5:21 and I think theres only so many ways we can mangle the company name

5:23 anyone tried out Cursive here? Been using the EAP all week and it's so much better than La Clojure from Jetbrains

5:24 glosoli: talios: is it truth that cursive will become commercial at some poitn ?

5:24 point"

5:25 talios: glosoli: that's colins aim yes, I believe Jetbrains are also going to seed the clojure space to Cursive so as to not compete

5:26 sm0ke: is anyone working with light table too?

5:26 glosoli: talios: Kinda makes me want to stay way from it, until I learn about the pricing

5:26 talios: La Clojure was never really had anyone full time on it anyway

5:27 glosoli: Yeah :) just because of Clojure I got used to Emacs, and even used tried vim lol

5:28 talios: glosoli: I'll chase up Colin on pricing ( he's supposed to be hotdesking next to me for the next week or so ), I think he wants it to be cheap, comparable in pricing to some of the cheapers JB offerings I think

5:28 sm0ke: vim does pretty good with clojure

5:29 talios: I've dabbled with emacs for the last 20 odd years, and I still can't grapple the archaic key cording

5:30 glosoli: Dunno it kinda felt easy for me (though I hadn't used it more than half year)

5:40 Jarda: is anyone aware of a clojurescript core.async wrapper for making xhr requests?

5:47 sm0ke: that would be cool

5:48 Jarda: http://dimagog.github.io/blog/clojure/clojurescript/2013/07/12/making-http-requests-from-clojurescript-with-core.async/

5:48 sm0ke: i think there are some old libraries which wrap jQuery..like jayq

5:48 Jarda: this is cool, but I'm looking more like a complete library to use

5:48 sm0ke: it wont be hard to put that in a core.async channel goroutive

5:49 Jarda: sm0ke: yeah that blog post shows just that (using goog.net XHR)

5:49 but I don't feel like wrapping callback code by myself

5:51 sm0ke: Jarda: hmm well i dont know what clojure experts have to say about it..but core.async just need the most minimal changes...its pretty un intrusive way of introducing async behaviour

5:52 coming from scala and working with actors i dont mind put a feww go blocks and >! !<

5:53 let me know if you find one

5:53 :P

7:02 glosoli: Enlive question here, I have map consisting of key that stands as element id, and value as error message, any suggestions how could iterate the keys and at the same time be doing selection of these elements, so I could add classes to them ?

7:05 notofi: hi. Why does this code declare 'x' ?

7:06 clgv: glosoli: since you want to do side effects you can use (doseq [[k v] mymap] (do-somthing k, v))

7:06 notofi: (defn testfn [] (def x 1))

7:07 clgv: notofi: do not use `def` in functions - `def` is only intended for definition of symbols in a namespace and not for "local variables" (= local bindings)

7:07 notofi: you want `let`, e.g. (defn testfn [] (let [x 1] (+ x 2)))

7:07 glosoli: clgv: hmm now when I thought, all I need to do set same class on several nodes hmm there should be something inbuilt I am not aware of

7:08 notofi: clgv: I know I shouldn't do this but I am working with some code that uses for example defonce in some init functions. Before that there is a declare, and as I see it this declare is not needed

7:08 clgv: glosoli: oh you actually search for a way to select all nodes with keys in the map at once?

7:09 notofi: this non idiomatic and probably leads you straight to hell sooner or later ;)

7:09 glosoli: clgv: I have a list of keywords (which would correspond to the right ids in html template) and I want to select all them at once and apply some action like add-class

7:10 clgv: notofi: if you really need to set a value to a variable in a namespace from an init function better define the var with defonce and an atom a value and swap the atom in the init function

7:11 notofi: clgv: why you shouldn't do this? it seems shorter than using an atom

7:11 clgv: glosoli: I dont know whether there is a built-in helper for that. since an id should be unique I guess this is not considered basic functionality

7:12 glosoli: clgv: Ids are unique

7:12 I have a list of ids, I wanna do the selection of them and execute add-class on all of them

7:12 clgv: glosoli: yes thats what I said ;)

7:12 glosoli: aa ok

7:13 clgv: glosoli: you could simply use `map`+ the id selection function

7:18 glosoli: clgv thanks

7:20 clgv: notofi: you can read that up on the mailinglist. the discussion is often repeated.

7:21 notofi: my personal reason is that it will be hard to understand and reason about your code if you use `def` within functions regularly

7:22 notofi: there are better more technical reasons to avoid it

7:28 notofi: clgv: you know any? :)

7:29 glosoli: clgv: In case you are curious, that's easily doable by grouping your selectors in set

7:29 clgv: glosoli: you mean you can use enlive's `select` with a set of ids?

7:31 glosoli: more like [#{:#some_id :#some_other_id}] (add-class "error")

7:31 I guess it applies select on it, though I don't use select directly

7:34 clgv: ah ok. I only know enlive's `select` from seesaw ;)

8:17 augustl: json sucks.. I want most keys to be keywords in maps after json parsing, but some keys are numbers, and I want those to be numbers, not symbolized numbers, i.e. :0. But in JSON, all keys are strings. Meh!</rant>

8:21 shoshin: ping

8:21 i have a question, give an sequence containing maps how would i try to find if a particular key is present in any of the maps or not?

8:22 for example ({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6} {:a 7 :b 8 :c 9})

8:22 how do i find if the key :a is present in all the maps?

8:22 sm0ke_: augustl: i think if prsing using cheshire you can opt for keywods as keys (parse-string "{\"foo\":\"bar\"}" true)

8:23 rkneufeld: shoshin: probably via some

8:23 sm0ke_: the true flag towards the end

8:23 shoshin: rkneufeld would some work on a sequence?

8:23 rkneufeld: shoshin: I think so, give it a go in a REPL.

8:23 augustl: sm0ke_: teah that's what I do, but then the JSON {"0":"test","5":"bar"} will become {:0 "test" :5 "bar"}, since json sucks :)

8:24 sm0ke_: augustl: so what do you want instead?

8:25 shoshin: rkneufeld i tried the following (some #{:a} ({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6})

8:25 returns nil

8:26 rkneufeld: The list of maps you have isn't quoted

8:26 augustl: sm0ke_: I want to be able to tell the world that the keys are numbers, not strings, which json doesn't support

8:26 Morgawr: `(let [a {:a :b :c :d}] (str (map reverse (into [] a))))

8:26 rkneufeld: shoshin: It's trying to find the first map inside the second (or the other way around…). Add a single quote in front of ({:a 1 ...)

8:27 Morgawr: how do I trigger clojurebot? D:

8:27 sm0ke_: augustl: are you sure?

8:27 var a = {3: 4} on my browser repl works fine

8:27 augustl: sm0ke_: yeah, keys have to be strings. Or, you could of course parse the string and check if it only contains ascii number characters

8:27 sm0ke_: a[3] also returns 4

8:27 augustl: sm0ke_: JS will stringify that automatically actually

8:27 sm0ke_: and JS != JSON anyway :)

8:27 rkneufeld: shoshin: hmm, that doesn't work either. Must be something off about the set. It works with :a alone.

8:27 shoshin: rkneufeld (some #{:a} '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}))

8:28 sm0ke_: isnt json = javascript object notation?

8:28 shoshin: doesn't work, yes.

8:28 Morgawr: &(let [a {:a :b :c :d}] (str (map reverse (into [] a))))

8:28 lazybot: ⇒ "clojure.lang.LazySeq@bc3043e0"

8:28 Morgawr: how do I make it not print LazySeq? ^

8:28 I tried using doall but it doesn't work

8:28 rkneufeld: &(some #a '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6})

8:28 lazybot: java.lang.RuntimeException: No reader function for tag a

8:28 rkneufeld: &(some a '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6})

8:28 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

8:28 sm0ke_: anyways i am not sure if i understand

8:28 rkneufeld: &(some a '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}))

8:28 lazybot: java.lang.RuntimeException: Unable to resolve symbol: a in this context

8:28 rkneufeld: &(some :a '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}))

8:28 lazybot: ⇒ 1

8:28 Morgawr: &(let [a {:a :b :c :d}] (str (doll (map reverse (into [] a)))))

8:28 lazybot: java.lang.RuntimeException: Unable to resolve symbol: doll in this context

8:28 augustl: sm0ke_: not entirely, {foo: "bar"} is invalid JSON

8:28 Morgawr: &(let [a {:a :b :c :d}] (str (doall (map reverse (into [] a)))))

8:28 lazybot: ⇒ "clojure.lang.LazySeq@bc3043e0"

8:28 Morgawr: :|

8:29 augustl: sm0ke_: it has to be {"foo":"bar"} (quote the key)

8:29 rkneufeld: shoshin: the last one (typing is hard)

8:29 sm0ke_: augustl: what the...yes of course...its invalid everywhere

8:30 shoshin: rkneufeld you mean this one? (some :a '({:a 1 :b 2 :c 3} {:a 4 :b 5 :c 6}))

8:30 sm0ke_: without foo being defined

8:30 augustl: sm0ke_: considering adding content type negotiation so I can serve EDN which has sets and arbitrary map keys and what not

8:30 sm0ke_: ,{foo :bar}

8:30 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:30 sm0ke_: ,{'foo :bar}

8:30 clojurebot: {foo :bar}

8:30 shoshin: rkneufeld i think i need to map the some over the collection.

8:30 jonasen_: &(let [a {:a :b :c :d}] (pr-str (map reverse (into [] a))))

8:30 lazybot: ⇒ "((:b :a) (:d :c))"

8:30 shoshin: *sequence

8:31 jonasen_: Morgawr: ^

8:31 Morgawr: jonasen_: okay but that is only if I want to use "str" on it, how do I make sure it realizes anyways?

8:31 I thought doall would realize sequences

8:32 rkneufeld: shoshin: yeah. Check out https://github.com/clojure-cookbook/clojure-cookbook/blob/master/composite-data/determining-if-a-collection-holds-one-of-several-values/determining-if-a-collection-holds-one-of-several-values.asciidoc – some applies the set to each value of the seq. (#{:a} {:a 1}) is nil, but (#{:a} :a) is :a.

8:32 sm0ke_: well json is a subset of clojure maps...so yes that would not work both ways

8:32 js has no concept of sets

8:33 shoshin: rkneufeld that helped me understand this! Thank you so much!

8:33 jonasen_: &(let [a {:a :b :c :d}] (str (seq (map reverse (into [] a)))))

8:33 lazybot: ⇒ "((:b :a) (:d :c))"

8:33 augustl: sm0ke_: indeed, and some times I want to convey that something is a set, not a sorted list

8:33 wakeup: Hi all

8:34 I get a IllegalStateException I/O in transaction

8:34 sm0ke_: augustl: may be you want to cosider serialization instead?

8:34 wakeup: I guess it's because I do a database write during dosync

8:34 jonasen_: Morgawr: Use seq

8:34 wakeup: How do I solve this without using a lock?

8:35 sm0ke_: augustl: something like nippy?

8:36 Morgawr: jonasen_: alright, thanks

8:37 wakeup: AH solved it

8:37 augustl: sm0ke_: or EDN :)

8:38 and content negotiation where the client says which content types it accepts, HTTP style

9:21 clgv: wakeup: if you want to do sequential I/O from transactions agents fit pretty well for that

9:22 tbaldridge: wakeup: a little more context may help as well. What is the lock doing?

9:49 rurumate: woohoo from euroclojure

9:50 they finally got the wlan running

9:51 mdrogalis: :)

9:51 ssideris1: hey! I'm there (here) too

9:51 ambrosebs: hello euroclojure!

9:52 mdrogalis: What city is it in?

9:52 rurumate: berlin

9:53 mdrogalis: Sounds terrific

9:53 rurumate: why is everyone saying haitch-tml today, pronouncing the letter H this way? is this a new fancy way to speak?

9:54 ssideris1: rurumate: I think it's a british thing

9:55 rurumate: apparently not everyone agrees on that: http://www.youtube.com/watch?v=c3y0CD2CoCs

9:57 dobry-den: tbaldridge: That was a good macro vid

10:00 mdrogalis: dobry-den: Yeah I learned a lot from that screencast.

10:00 If it's the one I think you're talking about, heh.

10:08 tbaldridge: dobry-den: great! I'm glad it helped

10:09 silasdavis: I've currently got some code that uses the AmazonS3Client directly and I was considering the merits of using: https://github.com/weavejester/clj-aws-s3/blob/master/src/aws/sdk/s3.clj

10:09 but it looks like that doesn't allow you to create an s3-client with the parameter-less constructor

10:11 Currently I am using the parameter-less constructor and an instance profile on elastic beanstalk which has s3 credentials attached which the S3 client knows how to find if given no creds

10:12 shall I just stick with the java SDK?

10:12 tbaldridge: silasdavis: I find little reasons not to use bare Java APIs for most things

10:12 many wrapper libraries don't add much in the way of clojure integration, and simply restrict your options.

10:13 silasdavis: great, that was the sort of validation I was after, I use the bare api, seems nice enough anyway

10:44 wakeup: (seq (take ....)) is not lazy or is it?

10:44 llasram: wakeup: Why would it not be lazy?

10:44 tbaldridge: wakeup: it's lazy

10:44 wakeup: do I need to use doall?

10:45 llasram: Not if you want it to be lazy :-)

10:45 tbaldridge: wakeup: yep, or do vec on it. I often prefer to make all my non-lazy seqs into vectors.

10:45 wakeup: is pmap lazy?

10:45 tbaldridge: wakeup: yep

10:46 wakeup: ok

10:46 Morgawr: it's semi-lazy :P

10:46 tbaldridge: wakeup: if it deals with seqs, it's lazy. Unless specified otherwise.

10:46 Morgawr: &(doc pmap)

10:46 lazybot: java.lang.SecurityException: You tripped the alarm! pmap is bad!

10:46 Morgawr: :|

10:46 dang lazybot

10:46 tbaldridge: ,(doc pmap)

10:46 clojurebot: "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."

10:46 tbaldridge: :-P

10:46 Morgawr: thanks :P

10:47 wakeup: ,(doc doall)

10:47 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

10:47 tbaldridge: &(let [pmap 42] 42)

10:47 lazybot: java.lang.SecurityException: You tripped the alarm! pmap is bad!

10:47 tbaldridge: lol

10:47 mdrogalis: Bad tbaldridge D:

10:47 Morgawr: time to report to the authorities

10:47 keep calm and don't panic

10:47 mdrogalis: Get this guy outta here, he's using pmap. D:

10:48 tbaldridge: I like to live dangerously

10:52 wakeup: What about ref's, I seem to be unable to predict their value,

10:52 anything I should know about using deref?

10:52 mdrogalis: wakeup: Predict?

10:57 tbaldridge: wakeup: I agree with mdrogalis I don't understand the word "predict" in this context.

10:57 mdrogalis: (crystal-ball IRef)

10:57 Backed by data.generators 'anything' function :)

11:16 sm0ke: is the quick sort example in joy of clojure the worst example ever or what?

11:16 i remember reading a quicksort in lyah

11:16 clojure version is hedious

11:17 benmoss: whats bad about it

11:18 llasram: sm0ke: If the version of quicksort in LYAH is pretty, I'm willing to bet that it isn't really a quicksort

11:19 sm0ke: http://learnyouahaskell.com/recursion ... its pretty neat

11:20 llasram: Actually, now that I'm looking at them, neither one is actually quicksort

11:21 wakeup: NullPointerException clojure.core/fn--5420 (core_print.clj:187)

11:21 I can't see em any more...

11:22 indigo: wakeup: :P

11:22 I like your nick, btw

11:22 Helps me wake up in the morning xP

11:22 wakeup: I am serious though

11:23 how am I supposed to debug my concurrent shit if I get NPE's from

11:23 core_print ?

11:23 tbaldridge: wakeup: code paste?

11:24 dnolen: sm0ke: you can write a very nearly that neat in Clojure

11:24 s/very/version

11:26 wakeup: tbaldridge: having trouble locating where the exception comes from.

11:26 no stack trace either.

11:26 tbaldridge: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_print.clj#L187

11:26 wakeup: might as well segfault.

11:26 tbaldridge: even print-stack-trace on *e gives you nothing?

11:30 llasram: sm0ke: ##((fn qsort [[x & xs]] (if x (let [smaller? (partial >= x)] (concat (->> xs (filter smaller?) qsort) [x] (->> xs (remove smaller?) qsort))))) (repeatedly 20 (partial rand-int 256)))

11:30 lazybot: ⇒ (0 17 27 29 46 64 74 113 119 121 126 145 171 174 184 185 194 197 206 245)

11:30 llasram: sm0ke: The version in /JoC/ is lazy, which takes a bit more work

11:37 zerokarmaleft: sm0ke: the beauty of the lazy JoC version is that if you select into the sorted result (with nth or drop & take, etc.), the algorithm only sorts the partitions necessary to give you the correct result

11:38 sm0ke: i guess..its beyond me..i am still a beginer

11:39 but still the structure of loop is bit confusing .. specially the recur call is hard to understand

11:40 list* with 4 arguments..crazy

11:50 indigo: Quick question

11:50 There is some fizzbuzz code on rosettacode written in Clojure

11:50 https://www.refheap.com/19834 <-- do you really need a lazy-seq considering there's already an iterate there?

11:51 Morgawr: mm. considering map is lazy, I'd say you don't need the lazy-seq but I'm not 100% sure

11:51 mdrogalis: I believe you can forego it.

11:52 indigo: It works if I forego it, but I'm just wondering if there is a reason that it was there

11:52 Morgawr: indigo: overengineering probably :P

11:53 indigo: Morgawr: Heh yeah, maybe I'll go ahead and update it on Rosetta Code

11:53 Concise code ftw

11:54 mdrogalis: Speaking of Fizz Buzz https://gist.github.com/MichaelDrogalis/4684403

11:54 This is still hilarious to me.

11:55 stuartsierra: heh

11:55 glosoli: lol

11:55 zerokarmaleft: mdrogalis: haha

11:56 indigo: Heh

11:56 Too bad he didn't put the numbers in

11:57 mdrogalis: indigo: Yeah I think I got close enough and enjoyed that answer a lot, so I stopped. :P

11:57 si14: is there anyone who use Prismatic's Schema with CLJS?

11:58 got my build suddenly broken, just a ton of "Use of undeclared Var [record-name-here]"

11:58 indigo: If anyone I interview writes FizzBuzz in Clojure, they're getting hired on the spot :P

11:59 mdrogalis: indigo: Even with my non-modulus magic?

12:00 indigo: Yep :P

12:01 Then I can have a buddy to complain about PHP with

12:01 wakeup: Now what could that hint to? java.util.concurrent.ExecutionException: java.lang.NullPointerException

12:01 at java.util.concurrent.FutureTask$Sync.innerGet

12:02 marcopolo2: indigo: I used to work at a php shop, I feel your pain

12:02 indigo: Hehe

12:04 dgrnbrg: Is there a way in compojure or another accepted library for mounting a ring handler at a context path?

12:04 jonasen_: si14: did you update cljs?

12:04 si14: jonasen_: yes. -1934 now

12:05 clojurebot: Huh?

12:05 jonasen_: si14: did you run lein cljsbuild clean?

12:05 si14: jonasen_: yes

12:06 jonasen_: si14: do any of the warnings point to a particular file/line-number?

12:07 si14: jonasen_: yes. it looks like this: https://gist.github.com/si14/d7e5254391cffc2c51f7

12:07 jonasen_: but for all records, actually

12:09 indigo: I think I killed RosettaCode :<

12:09 Oh no, nvm, it's back up again

12:10 noncom: if i have (defn hey [x] (+ 1 x)), how do i pass "hey" to a macro so that it gets passed not as 'hey, but as the form itself? or at least as the generated IFn object?

12:11 llasram: noncom: You don't

12:11 si14: jonasen_: when I run generated stuff in browser I get "Uncaught TypeError: Cannot set property 'schema$utils$schema' of undefined "

12:11 mdrogalis: New talk by Rich up on InfoQ :)

12:12 noncom: llasram: oh sad..

12:12 llasram: noncom: Why? You really don't need that

12:12 noncom: wait i make a simple example, maybe you can give a hint

12:13 llasram: ok

12:14 marcopolo2: mdrogalis: link?

12:17 mdrogalis: marcopolo2: http://www.infoq.com/presentations/datomic-functional-database?utm_source=infoq&utm_medium=videos_homepage&utm_campaign=videos_row3

12:17 marcopolo2: mdrogalis: thanks!

12:17 Creap: I have a plugin system, and a user can put a plugin in a directory and a namespace string in a config file. I then want to require the ns and get a function with a predefined name

12:18 (map (comp require symbol #(str % "/message-handler") :ns) (vals plugins)) is my current attempt, which doesn't work very well..

12:18 wakeup: What the hell. What could go wrong, so that locking doesn't work?

12:19 When I comment out the actual (non-logging) body of locking it works fine

12:19 when I do IO in the body, the lock is just ignored

12:19 mdrogalis: Sure!

12:19 wakeup: except logging

12:19 jonasen_: si14: I can reproduce.. I'll take a look if I can find the cause

12:19 wakeup: weeeiird i hate my job right now

12:19 si14: jonasen_: thank you very much.

12:20 tbaldridge: wakeup: you really have to give some context. ranting doesn't help if we don't even know what your problem is

12:20 wakeup: I don't either

12:21 I am trying to produce a minimal example ;)

12:22 marcopolo2: Creap: are you requiring ns/func, instead of just the namespace?

12:24 Creap: in the example above yes, I've tried a number of variants though

12:25 marcopolo2: Creap: try not including the /func, just the ns, so get rid of the #(str ...)

12:28 Creap: marcopolo2: ok, but just to be clear, will require return the namespace, or just include the file?

12:28 if it does the latter, I think I have it working, but I expected a result as well

12:28 TimMc: wakeup: Laziness.

12:29 marcopolo2: Creap: pretty sure it will return nil

12:30 dobry-den: Question: Does loop/recur only exist because of the JVM's limitation?

12:30 I guess, what's the surrogate for loop/recur if you didn't have it?

12:30 TimMc: Yes, otherwise we'd just tail-call.

12:31 Creap: it did indeed, and they were required.. thanks, just need to get the message-handler for those namespaces now

12:31 noncom: llasram: sorry for the delay https://www.refheap.com/19835

12:31 dobry-den: TimMc: What's an example of how you'd write (loop [x 0] (when (< x 10) (recur (inc x))))

12:31 in other lisps

12:33 mdrogalis: lol Rich in that talk "What happens when you play with machines? You get hurt!"

12:34 llasram: noncom: I'm sorry, but I really don't have any idea what you're trying to do :-/

12:35 arrdem: mdrogalis: which one?

12:37 noncom: llasram: here is something like i do: http://blog.zololabs.com/2009/12/10/frumios-a-silly-object-system-for-clojure/ what if, in terms of that example, i want to use functions defined elsewhere as (method) instead of defining it in place?

12:37 mdrogalis: arrdem: The Functional Database. Find it on InfoQ. Very new.

12:38 marcopolo2: Creap: you could try (kinda hacky): (eval `(var ~(symbol "ns" "fn"))) => returns reference to ns/fn function

12:38 TimMc: dobry-den: (fn foo [x] (when (< x 10) (foo (inc x))))

12:38 marcopolo2: Creap: there has to be a better way to do that

12:38 dobry-den: TimMc: Does loop/recur only exist because it does something different than your example?

12:38 marcopolo2: Creap: don't do what I did

12:39 dobry-den: Clojure is my first lisp and in my ignorance, loop/recur simply feels like a low-level loop where its binding has a nice aesthetic just like `let`

12:40 llasram: noncom: If there's an identifier in scope which refers to a function, you can just pass the identifier to the macro, and the macro can expand to code referring to the function via identifier

12:40 technomancy: dobry-den: it is a low-level loop

12:40 dobry-den: I'm talking to someone that suggests that loop/recur is unpleasant and it only exists to address a jvm limitation

12:40 technomancy: application-level logic should always be expressed in higher-order terms via the seq api

12:41 TimMc: dobry-den: In a language with tail-call optimization, my example's call to foo would replace the current stack frame with the new call.

12:41 noncom: llasram: will it expand to the original form of the function or resolve to the compiled form?

12:41 TimMc: Clojure on extant versions of the JVM can't support that, so we have loop/recur.

12:42 llasram: noncom: It'll expand to exactly the same code using the identifier you'd write by hand

12:42 TimMc: It does basically the same thing, but is much more limited.

12:42 dobry-den: TimMc: Even so, loop/recur is sort of like an "anonymous loop" compared to your named-fn example.

12:42 seangrove: Wish they'd hold EuroClojure in SF, would be a lot more convenient

12:42 noncom: llasram: thanks!

12:42 TimMc: dobry-den: It's an anaphoric named-let.

12:43 Creap: marcopolo2: I thought that (symbol "foo.bar/baz") would work

12:44 but I guess I misunderstood symbol

12:44 dobry-den: TimMc: Right, and that seems like useful construct to have in a language. I'm admittedly ignorant of these things but I was trying to suggest to someone that loop/recur is actually a nice construct for a language to have.

12:45 justin_smith: a better analog to loop/recur in cl would be tagbody (with the special case of one tag at the top) - but that is very low level and only used when you are optimizing performance (and usually want multiple tags rather than a case statement or if or something)

12:45 technomancy: dobry-den: in practice you only use loop/recur for things that can't be framed in terms of seq operations, which is almost never

12:45 justin_smith: or am I thinking labels? it has been a while

12:46 llasram: technomancy, dobry-den: seq operations / the CollReduce protocol

12:46 rasmusto: looping in low places

12:47 justin_smith: yeah, looking at the docs I was right the first time tagbody, one label at the top, and "go" instead of recur

12:47 that still isn't right though - go does not take args

12:47 never mind, none of this is all that relevant anyway

12:49 dobry-den: technomancy: So let's say you were implementing Hy (http://docs.hylang.org/en/latest/language/api.html#builtins) - Would you not implement loop/recur?

12:49 And what would you implement instead as your "lowest level loop"

12:51 technomancy: dobry-den: I'm not saying it's not needed in the language; I'm saying it's more of an escape hatch. lots of higher-level functionality that comes with the language needs to be implemented in terms of loop/recur, but the day-to-day programmer never sees it

12:51 Creap: I would expect (var ((symbol "clojure.string" "join")) "_" [1,2]) or ((symbol "clojure.string" "join") "_" [1,2]) to work, why don't they?

12:52 dobry-den: technomancy: The person pointed out to me that Clojure is the only lisp with loop/recur as evidence that it's a hack

12:53 technomancy: haha

12:53 have you seen CL's LOOP?

12:54 dobry-den: Yeah, he actually directed me there as the pinnacle of looping in lisp

12:54 technomancy: hahahaha

12:55 doesn't sound like someone who will listen to reason

12:55 justin_smith: Creep: in the virst example you just have the parens around the call to var balanced wrong

12:56 dobry-den: The context here is that I'm in #hy trying to defend loop/recur in worlds abroad and #clojure just isn't giving me the amunition I need to subjugate the heathens.

12:57 gfredericks: clojurebot: #clojure is wussy about heathen subjugation

12:57 clojurebot: Ack. Ack.

12:57 technomancy: dobry-den: it's true that you don't need loop/recur in languages with guaranteed TCO, but CL and elisp don't have guaranteed TCO either; they have horrible iterative hacks

12:57 dobry-den: This Hy lang is built on Python fwiw

12:57 arrdem: dobry-den: just use loop/recur to run circles around them. they're unfortunate enough to be atop cython, shouldn't be hard.

12:57 justin_smith: Creap: never mind, there is more wrong there than that, but there is a version of that first that works, working on it

12:58 dobry-den: I know python doesn't have tail call optimization, but I suggestd that it doesnt matter because loop/recur is so elegant that it can be implemented with assignment.

12:58 justin_smith: Creap: ##((resolve (symbol "clojure.string/join")) "_" [1,2])

12:58 lazybot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

12:58 justin_smith: ,((resolve (symbol "clojure.string/join")) "_" [1,2])

12:58 clojurebot: "1_2"

12:58 justin_smith: :P

12:59 ahh, there we go

13:00 igstan: is there any reason clojure has loop/recur instead of normal name-based TCO? other than as a hint for the compiler that it should complain if the functions isn't actually tail-recursive?

13:01 technomancy: igstan: having it refuse to compile in non-tail-positions is the reason, yeah

13:01 justin_smith: Creap: the reason var acts so weird is it is a macro, it only works if the thing it gets is directly a symbol - a form that resolves to a symbol only comes in as the form, not the resulting symbol

13:01 dobry-den: arrdem: haha yes. disappear into a trapdoor of recurs

13:01 igstan: technomancy: thanks

13:01 technomancy: I think scala does what you suggest, but there's no way to have the compiler enforce non-stack-consuming recursion IIRC

13:02 igstan: technomancy: scala has an annotation @tailrec. it will do TCO without it, but only complain about non-TCO code if you add the annotation

13:03 technomancy: gotcha. so this is basically a macro to do the same thing.

13:03 justin_smith: what I like about recur is the explicit error if not in the tail position - you don't get as many mystery overflows from small errors or bad refactorings

13:04 igstan: technomancy: it just occurred to me that clojure could have used metadata for this?

13:04 similar to the scala annotation

13:05 technomancy: igstan: yeah, that could probably be used to do the same thing

13:05 igstan: but you'd still need a way to recur to a loop-point that wasn't the function entry point

13:05 so you couldn't get rid of recur entirely

13:06 igstan: technomancy: it's true, that's what I was thinking right now. in scala I always end up with an inner go helper functions that is tail-recursive and carries the accumulator

13:08 Creap: justin_smith thanks!

13:08 wakeup: What could be the reasons for a function to throw a NullPointerExc. only when used in pmap?

13:09 The function looks like this: (fn [out str] (.write out str))

13:09 it also calls .flush on out

13:09 it also calls pr-str

13:09 justin_smith: wakeup: using with-* macro or binding a *special* var so that the resource you want does not exist by the time a parallel thread looks for it?

13:09 wakeup: and get

13:09 Yes I found the binding issue

13:09 justin_smith: wakeup: are you using with-open to open the out?

13:10 wakeup: justin_smith: No.

13:10 justin_smith: so what was it?

13:10 wakeup: I use Socket.

13:10 no I am past that binding issue

13:10 was clueless for hours

13:11 I still get a NPE

13:12 could it be a variable bound by let outside of pmap?

13:13 tbaldridge: wakeup: very much so, pmap will use multiple threads to execute the function. bindings are sometimes not there, or not what you expect.

13:13 wakeup: but doing IO inside of pmap is just....wrong.

13:13 justin_smith: since pmap is mp, the form that launches pmap can exit before all the parts of pmap are done

13:13 mdrogalis: tbaldridge: Is that necessarily true? That's how you pipeline in Datomic.

13:13 wakeup: hmm no thats not it

13:13 justin_smith: tbaldridge: yeah, good point, I would expect weird overlapping output to the socket

13:14 wakeup: tbaldridge: I am using pmap to test IO operations for thread safety...

13:14 tbaldridge: mdrogalis: let me re-phrase that...doing side-effecting IO inside of pmap is troublesome.

13:14 wakeup: tbaldridge: alternatives?

13:15 tbaldridge: wakeup: future would be a good one.

13:15 mdrogalis: tbaldridge: How is that any different? Haha.

13:15 justin_smith: yeah, a doseq or dotimes launching futures that use the Socket would work nicely

13:15 tbaldridge: mdrogalis: doing reading IO is fine, you're not modifying anything (and based on the datastore may not actually modify any state).

13:15 gfredericks: I wrote a pdoseq the other day

13:16 mdrogalis: Pipelining into Datomic isn't reading IO though

13:16 gfredericks: not as featured as doseq though

13:16 mdrogalis: If I understand what you're saying correctly

13:17 tbaldridge: mdrogalis: I'm not sure what you mean.

13:17 mdrogalis: tbaldridge: Eh, nevermind. It's not really important. I think I get your point.

13:17 noncom: ,('a)

13:17 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: Symbol>

13:17 noncom: ,('a 1)

13:17 clojurebot: nil

13:17 noncom: ,('a 1 4)

13:17 clojurebot: 4

13:17 noncom: ,('a 3 5 1)

13:17 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: Symbol>

13:18 noncom: why is that ^^ ?

13:18 what does mean passing 1 or 2 args to a symbol?

13:18 tbaldridge: noncom: calling a symbol as if it were a function treats the 1st argument as a hashmap. if you give it a 2nd argument it gives a default

13:18 justin_smith: noncom: symbol as a called thing is a lookup in a map

13:18 so it is just like (:key {} :default)

13:18 tbaldridge: noncom: 1 argument "can't find 'a in 1", 2 arguments "can't find 'a in 1, so I'll return default"

13:19 noncom: oh, wow, i see! thanks!

13:21 broquaint: ,('a {'a "Like so"})

13:21 clojurebot: "Like so"

13:21 broquaint: ,('a {'b "Like so"} "Defaulty")

13:21 clojurebot: "Defaulty"

13:21 jonasen_: si14: They really like their macros over at prismatic :)

13:24 dnolen: CLJS users - do people really have strong opinion that the lower level try* is gone - it could be used for catching all errors even non error values - I don't really see the point given how people actually write libraries.

13:24 from what I call tell for all browser errors, Foo instanceof Error will be true

13:27 so only thing you can't catch is stuff like throw "Foo" which honestly is pretty silly and not something I think JS libs generally do

13:31 gfredericks: dnolen: I don't expect to have a strong opinion about this, but FWIW I can't even parse your sentences to figure out what you're asking

13:31 might just be lack of context

13:31 justin_smith: I guess it would mess up someone's plan to do continuations in js via try/catch - which would be a silly plan anyway

13:32 gfredericks: any object can be thrown in js, in practice only errors are thrown

13:33 gfredericks: so there was some try* that could catch anything? and that was removed recently? and dnolen is wondering if anybody thinks it should still be available?

13:33 justin_smith: that's how I read it

13:34 gfredericks: does that mean it's not possible to do the cljs analog of (try (a thing) (catch Throwable t (cleanup mess) (throw t)))

13:34 where (cleanup mess) only applies to errors and so couldn't be stuck in a finally

13:34 dnolen: gfredericks: try* could catch anything, same way as try can catch anything in JS

13:35 gfredericks: most host errors will be instances of Error, so that more or less works

13:35 gfredericks: dnolen: so now it's impossible to catch non-Errors?

13:35 dnolen: gfredericks: but if user code throws a string or a number, you can't catch it

13:35 gfredericks: but I'm not convinced that's something worth caring about

13:35 if a library is throwing strings ... rage face

13:35 gfredericks: that sounds like a problem for a lib that wants to be able to excute user code and cleanup issues if any exception is thrown

13:35 justin_smith: it would prevent porting slingshot - don't know how big a deal that is

13:35 https://github.com/scgilardi/slingshot

13:36 gfredericks: and my point is that it doesn't have to be a library doing the messy thing -- it could be a user where a library wants to not break just because a user was messy

13:37 dnolen: gfredericks: no, any host error will be an instance of Error, the only thing that won't work if library code *explicitly* throws non Errors

13:37 gfredericks: users can throw non errors though

13:37 dnolen: gfredericks: CLJS users?

13:37 gfredericks: ye

13:37 s

13:37 dnolen: gfredericks: won't happen cause you can't catch it

13:37 gfredericks: users won't throw them?

13:38 oh throw will check

13:38 I see

13:38 dnolen: gfredericks: if they do they won't be able to catch it

13:38 gfredericks: the only problem is external libs that might do this

13:38 gfredericks: what will (throw "foo") do?

13:42 dnolen: gfredericks: it will throw something you can't catch

13:42 gfredericks: more or less consider that undefined behavior

13:42 justin_smith: fwiw talking to the js expert here, almost nobody in idiomatic js uses throw, because it totally breaks the page if not caught, so they use things like console.assert instead

13:44 TimMc: "breaks the page"?

13:45 justin_smith: all js stops running

13:45 TimMc: That sounds incorrect.

13:45 * si14 jonasen_: yeah :)

13:45 si14: jonasen_: yeah :)

13:45 TimMc: justin_smith: I'm gonna need a demo of this.

13:46 justin_smith: TimMc: this is a web shop, we see this all the time - if you have js that throws and uncaught exception, all your js on that page stops running

13:46 I could make a minimal example maybe (though I am not on the js side of things here)

13:47 gfredericks: maybe you're miscommunicating? the thing it sounds like you're saying contradicts my ten years or something of working in web browsers

13:47 justin_smith: maybe

13:48 gfredericks: e.g., if you add a click handler to an element that logs to the console and then throws. and then you clicked twice. how many logs would you expect?

13:48 jonasen_: dnolen: I wouldn't be suprised if there were js libs out there that throws strings

13:49 dnolen: jonasen_: I've never seen one that I'd want to use.

13:49 gfredericks: jonasen_: dnolen: it seems super common in clj-jvm libs to want to be able to catch _all_ throwables for some purpose or another. the idea that something could sneak through because a user is ignorant is troubling

13:49 dnolen: jonasen_: or that anyone I know would want to use - exist is one, pervasive is another

13:50 gfredericks: yes, but real the question is whether it actually matters at all for most interop. I'm inclined to say no.

13:50 jonasen_: dnolen: that

13:50 bitemyapp: justin_smith: wat

13:50 jonasen_: 's true

13:51 bitemyapp: justin_smith: So Mozilla is telling people to do things that break web browsers? -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Statements#Exception_Handling_Statements

13:51 justin_smith: bitemyapp: gfredericks: sorry, it appears I didn't actually understand the problem on the js side of things

13:51 mea culpa

13:52 bitemyapp: justin_smith: it's okay, i was just hella confused and thought I was in an alternate universe where JavaScript is even worse than usual.

13:53 justin_smith: I've had frontend guys say "this happens because any error just stops all the rest of the scripts" - clearly that was an oversimplifications

13:53 gfredericks: bitemyapp: also if you use the variable "foo" anywhere in your file it causes the browser to interpret the statements in reverse

13:53 justin_smith: or a specific case, or something

13:53 jonasen_: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ "An unfortunately common pattern in Node.JS"

13:53 dnolen: ^ That's all I was able to find on the matter

13:53 TimMc: justin_smith: If they have a big init function and it throws part way, sure, that will break the app.

13:54 bitemyapp: which is also not a good way to write JS code.

13:54 You can have a callback that does nothing but throw an exception in JS, but as long as the binding is still valid, that callback will keep getting called and keep throwing exceptions.

13:54 justin_smith: ahh, ok

13:54 bitemyapp: All that stuff is independent of each other, you have to write your code in big monolithic blocks to short-circuit behavior.

13:55 anything that's part of the event loop is unkillable unless you explicitly: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.removeEventListener

13:55 or unless you capture the event and preventDefault

13:56 I'm sure dnolen could think of other ways. You get my meaning.

13:56 justin_smith: I take it you're mostly backend?

13:56 justin_smith: yeah, all I know about frontend is when things break between the two I guess

13:58 I thought I knew a bit more before this conversation than I think I know now, for sure :)

13:59 bitemyapp: justin_smith: ego is the enemy of learning.

13:59 justin_smith: definitely

14:05 jonasen_: dnolen: I can prepare a patch for CLJS-620. Do you think it's a good idea to defina a (definline ...) macro that expands to (defmacro ^:inline ...) or should I explicitly add ^:inline metadata?

14:05 dnolen: jonasen_: lets just stick with ^:inline for now

14:06 jonasen_: dnolen: ok

14:24 dnolen: uploaded. Note that I made it an error, so this might break some libraries that are immitating cljs.core

14:24 dnolen: I can change it to a warning if you want to

14:28 dnolen: jonasen_: I prefer it be a warning - I think the warning/error behavior should be tunable via cljsbuild

14:31 amacdougall: I'm having an issue with enfocus, and in hopes of debugging it, I decided to fork the repo and experiment. Turns out I was embarking on a whole new adventure! Any advice on how to use a local copy of a library in a project?

14:32 I've tried making a local jar and installing it in a local Maven repo, following http://nakkaya.com/2010/03/16/adding-custom-libraries-into-local-leiningen-repository/ -- but it's failing in a way that hints that I may be on the wrong track.

14:34 First I had to specify a domina dependency in the client project for cljsbuild to work, and after doing so, my JS immediately dies with "Uncaught Error: Namespace "goog.string" already declared." (which doesn't seem like something that should be occurring under any circumstances)

14:35 jonasen_: dnolen: In that case we'll get several warnings so this change might not be much of an enhancement: https://www.refheap.com/19838

14:43 coventry: amacdougall: I generally use lein checkout dependencies for that. https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

14:44 (Lets you modifiy the library you're bringing in without doing the lein install dance each time.)

14:47 amacdougall: That might do the job! I'll try it out now and let you know.

14:48 Do I simply put a path to the folder that has the library's project.clj and let Leiningen figure out the rest?

14:48 Because THAT would be a godsend. And yeah, it sure looks like it...

14:48 coventry: Yep. cd my-project; mkdir checkouts ; cd checkouts; ln -s /path/to/dependency

14:49 Then stick the dependency in project.clj, restart your repl, and play.

14:53 amacdougall: While I'm working, I suppose I should state the issue I'm trying to debug, in case anyone has ideas -- I'm using enfocus's "listen-live" function to handle clicks on <a class="internal"> links, cancel link navigation, and use client-side routing. enfocus/listen worked fine with a (.preventDefault e) side effect... enfocus/listen-live does not! It runs the handler, but the browser navigates anyway.

14:54 Looking at https://github.com/ckirkendall/enfocus/blob/master/project/cljs-src/enfocus/events.cljs, it looks like listen-live builds a goog.Event from the native DOM event, while listen does not. And goog.Event.prototype.preventDefault doesn't seem to actually invoke the native .preventDefault...

15:00 coventry: Oh, also, you have to (require :reload) the dependency to pick up changes since the ns was last loaded.

15:01 bitemyapp: coventry: (require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh)

15:02 amacdougall: coventry: The checkouts version works like a charm, thank you! Unfortunately, I'm still getting the same error as when I used the local jar, and it's a weird one -- it's claiming that "Namespace "goog.string" already declared", but it's the very first time it's executing main.js!

15:02 ...it must be executing something else before that... wait, I just might be stupid. Never rule that out.

15:04 coventry: bitemyapp: Sometimes that's been slow for me.

15:04 amacdougall: Yeah, problem solved. This will be very helpful! Thanks, coventry.

15:04 coventry: No worries.

15:09 dnolen: jonasen_: hrm why are there multiple warnings there?

15:09 jonasen_: dnolen: because analysis continues if we emit a warning

15:10 dnolen: jonasen_: but why two warnings for 1 when?

15:10 bitemyapp: coventry: figured I'd offer the more robust solution :P

15:11 jonasen_: dnolen: no idea ...

15:11 dnolen: jonasen_: I'm pretty sure the second one can be supressed

15:11 jonasen_: is that in the REPL?

15:12 jonasen_: dnolen: yes

15:12 dnolen: jonasen_: ok so the REPL does two analysis passes is why

15:13 achin__: @technomancy: I'm using your Clojure build pack on Cloud Foundry. I got it to work, but had to munge PATH to include java/bin. I thought the Java buildpack installed the JDK to $BUILD_DIR, not $HOME. http://git.io/fmisbg

15:13 dnolen: jonasen_: in general we don't emit warnings w/o first checking that the user wants to see them, :undeclared is what we normally check for in *cljs-warnings* dynamic hash-map

15:14 jonasen_: we might want to check for something else, or just rethink *cljs-warnings* and make it a bit simpler.

15:14 jonasen_: dnolen: yeah, I also realized that resolve-var shouldn't call warning explicitly, It should go via resolve-existing-var or something

15:15 dnolen: as the docstring for resolve-var suggests

15:18 amacdougall: Aha... enfocus's events/listen-live actually throws away the original DOM event, passing a completely new goog.events.Event to the client. preventDefault and stopPropagation become impossible.

15:18 Sternly resisting the temptation to make jokes about .preventDefault and the US government.

15:34 Creap: is there a way to auto-restart my app, run with lein run, when it crashes?

15:38 mtp: use runit

15:39 Creap: ok, I'll look into it

15:40 mtp: :)

15:41 it's a great thing. you also don't have to use the whole thing, if you just need runsvdir.

15:41 most people just need runsvdir

15:43 llasram: (inc mtp)

15:43 lazybot: ⇒ 1

15:44 wakeup: Can anyone give me an example of a simple threadsafe counter?

15:44 llasram: ##(java.util.concurrent.atomic.AtomicLong.)

15:44 lazybot: ⇒ 0

15:45 llasram: mtp: runit is the best. All nice and Unix-y, but without totally rejecting the FHS like djb's originals

15:46 Creap: mtp: excellent, that took me <5 minutes, thanks

15:46 mtp: :)

15:47 wakeup: Why does this not work:

15:47 (dosync (ref-set cnt (inc (deref cnt))))

15:47 (try STUFF-HERE

15:47 (finally (dosync (ref-set cnt (dec (deref cnt))))))

15:47 ?

15:47 mtp: i'd like, at some point, to merge s6-supervise with runit

15:47 later, tho. :)

15:48 mnemnion: I have a hopefully quick if noobish question. I have, basically (do (make a directory) (put stuff in it))

15:48 coventry: wakeup: how does it fail?

15:48 indigo: wakeup: Why not use atoms instead?

15:49 wakeup: coventry: the value of (deref cnt) seems to be unpredictable.

15:49 gtrak: wakeup: works as expected to me

15:49 wakeup: (when used concurrently)

15:49 mnemnion: I think the problem is that clojure is trying to (put stuff in it) before (make a directory) returns

15:49 indigo: (def i (atom 0)) (swap! i inc)

15:49 coventry: wakeup: Well, you don't have it locked during the try block.

15:49 mnemnion: because when I do them one at a time on the REPL, no problme.

15:50 gtrak: seems like you should use alter insted of ref-set? (unrelated)

15:50 indigo: Or, you know, use atoms ;P

15:51 gtrak: this sounds like xy-problem http://www.perlmonks.org/?node_id=542341

15:51 wakeup: coventry: why would I? (honest question)

15:52 llasram: mnemnion: Clojure doesn't have any implicit laziness. Unless you're doing `(make a directory)` as part of realizing a lazy-seq, `do` always evaluates body forms in order

15:53 indigo: wakeup: What are you trying to do

15:53 mnemnion: llasram: okay. what seems to be happening is that the system call isn't actually completing before the next form evaluates.

15:53 coventry: wakeup: The question from my perspective is why you would expect the value to be predictable, given that cnt could be concurrently modified during the try block.

15:53 wakeup: indigo: cound the number of open connections (concurrently)

15:53 count*

15:53 TimMc: wakeup: While your code is executing STUFF-HERE, another thread is molesting your refs.

15:53 mnemnion: even though the (make a directory) form returns successfully.

15:53 indigo: wakeup: Then you should use an atom

15:53 wakeup: I will try an atom

15:54 llasram: mnemnion: Post full reproducing code? Can't say what is going on w/o, but I assure you that there isn't random out-of-order execution happening

15:54 TimMc: wakeup: If you're just counting the number of threads that are executing STUFF-HERE, your code should work (although it is a bit awkward.)

15:55 What is your evidence that the result of teh deref is "unpredictable"?

15:55 wakeup: TimMc: it doesn't though

15:55 mnemnion: llasram: sure, the only dependency is me.raynes/fs. I'll toss up a gist. thanks!

15:55 wakeup: TimMc: I open 10 connections, then I close them, then the value is random

15:55 Raynes: My code is like an infection. Spreads hate and anger to all who depend on it.

15:56 wakeup: TimMc: obviously I am doing something wrong ;)

15:57 tbaldridge: wakeup: use alter instead of ref-set. that should help

15:57 coventry: I would experiment with tracing output in the finally blocks.

15:58 arrdem: Raynes: could be worse, it could not work while doing all the above.

15:58 wakeup: tbaldridge: would you also suggest using atoms instead?

15:58 mnemnion: https://gist.github.com/mnemnion/6997178

15:58 tbaldridge: the problem is that but yeah, use an atom

15:58 typeo there.

15:59 wakeup: Btw, I got rid of my NPE's by using futures instead of pmap. Can you guys explain me thats the difference of spawing a lot of futures and pmap?

15:59 tbaldridge: yes, use an atom

15:59 lynaghk: cemerick: ping

15:59 TimMc: tbaldridge: Actually, I'm not seeing why this wouldn't work.

15:59 You think there needs to be an ensure? :-/

15:59 mnemnion: llasram: the pieces all work. I can call them one at a time at the REPL and it does what I want.

15:59 llasram: mnemnion: Yeah, so `map` explicitly returns a lazy sequence. You need to force it (probably via `dorun`) in this case, or use a non-lazy form like `doseq` instead

15:59 (in `athena-gen-dirs`)

16:00 mnemnion: llasram: thanks again! The consequences of laziness on side-effect producing code still bite me.

16:00 llasram: mnemnion: When you call the functions in the REPL they work because printing forces the full seqs to be realized

16:00 mnemnion: Yeah, it's tricky, especially at first!

16:01 tbaldridge: TimMc: I think alter implies ensure, not sure if ref-set does.

16:01 mnemnion: llasram: I intuited a laziness problem, that's where the 'do' came from, but it's in the wrong place. I see that now. cheers

16:02 tbaldridge: wakeup: the pmap vs futures thing may come down to a matter of bindings, but your new solution is sound. Side effects should be done in futures not in pmap.

16:02 mnemnion: ....and it works! ...and it was the last thing that needed to work! I am in a fine mood now. Kudos llasram.

16:03 llasram: mnemnion: Glad to help :-)

16:04 wakeup: tbaldridge: Imho this behaviour is quite buggy, I literally spent 4 hours trying to figure that one out.

16:04 lynaghk: e

16:04 llasram: Oh man, I wish

16:04 wakeup: and I didn't even use binding

16:05 The NPE doesn't help one bit...

16:05 lynaghk: Ugh, sometimes my desktop goes "beep" and all of the windows and buttons stop working. But the music keeps playing. Linux...

16:05 wakeup: lol

16:05 sounds like windows ;)

16:05 tbaldridge: wakeup: there's certain facts about Clojure semantics that are easy for beginners to miss. For instance, pmap uses multiple threads and bindings may not be passed around. You shouldn't deref a ref inside a dosync, etc.

16:06 These things all come with time

16:06 lynaghk: wakeup: are you kidding? I should just compile xmonad for Windows 2000 and be done with all of my hardware problems.

16:06 wakeup: lynaghk: Windows 2000 does indeed rock. I make my mum use it on a 15 year old thinkpad.

16:07 coventry: Why shouldn't you deref a ref inside a dosync? I haven't used transactions much yet.

16:08 wakeup: I am afraid what will happen when no browser support win2k. Her office suite doesn't support >xp and nobody could possibly ask her to learn to use a modern MS office.

16:08 TimMc: deref is fine inside a dosync, just make sure to use ensure (if it matters.)

16:10 coventry: Oh, I see how wakeup's code could be failing, and why using alter fixes it. Thanks.

16:10 tbaldridge: coventry: yeah, I think that's the problem. From what I can tell (I might be wrong) if you use deref inside a dosync (without a ensure) the transaction will not be restarted if that ref is modified.

16:10 wakeup: Using atoms has the same effect...

16:10 coventry: tbaldridge: Yes, the refs page on clojure.org is pretty explicit about that possibility.

16:11 wakeup: You need to make the changes atomic using swap! for an atom or alter for a ref.

16:12 What is happening is you have multiple threads coming in, reading the value of cnt and trying to inc/dec it at the same time.

16:13 If you use one of the functions which take an altering function instead, there won't be an opportunity for modification between the read and the inc/def.

16:13 TimMc: wakeup: Could not reproduce with: https://www.refheap.com/19843

16:13 I'd be interested in a SSCCE.

16:15 pjstadig: a deref and ref-set inside of a dosync should be fine

16:15 indigo: TIL SSCCEE

16:15 Er E

16:16 coventry: TimMc: Try taking the delays out.

16:16 wakeup: still works

16:16 weird

16:17 TimMc: coventry: Still works.

16:17 coventry: Let me know if you find something.

16:17 coventry: cnt has a value of 7 after running https://www.refheap.com/19844 for me.

16:18 tbaldridge: and if you use alter?

16:18 indigo: Hm, still has a value of 0

16:18 pjstadig: coventry: you probably need to reref the futures

16:18 wakeup: When I use alter the system deadlocks

16:18 pjstadig: er deref

16:18 TimMc: coventry: Are you sure all those threads have finished? :-P

16:18 tbaldridge: wakeup: how are you using alter?

16:18 wakeup: inside a dosync?

16:18 tbaldridge: should be (alter cnt inc)

16:18 wakeup: (alter ref inc)

16:19 TimMc: I do not believe that ref-set is not strictly stronger than ensure.

16:19 wakeup: in a dosync right?

16:19 tbaldridge: yep

16:19 indigo: coventry: It has a value of 145 if I do it with 2000 threads

16:20 pjstadig: indigo: then you are not waiting for the 2000 threads to finish before checking the value

16:21 alter is better style than deref/ref-set, but not different semantics

16:21 indigo: pjstadig: Ah, gotcha

16:22 wakeup: I am now using alter and still getting random values....

16:22 coventry: TimMc, pjstadig, You're right, cnt is zero if I delay a second before checking it.

16:22 TimMc: ~sscce

16:22 clojurebot: An SSCCE is a Short, Self-Contained, Correct Example <http://sscce.org/&gt;

16:22 indigo: ^

16:22 pjstadig: wakeup: you need to paste the exact code

16:23 TimMc: wakeup: ^ Post an SSCCE *demonstrating* how you get those "random" values.

16:23 You are misinterpreting your results.

16:23 pjstadig: there's probably an unrealized lazy seq, or otherwise un-joined threads that are causing "randomness"

16:26 coventry: wakeup: Are you sure all *your* threads are finished when you check the value of cnt? Tracing the finally blocks could help determine that.

16:37 cemerick: lynaghk: heyo

16:39 dobry-den: Is there a way to throw a Warning to the user?

16:42 indigo: dobry-den: https://github.com/clojure/tools.logging ?

16:43 dnolen: feel free to chime in the try* change if you are likely to be affected by it, http://groups.google.com/forum/#!topic/clojure-dev/1ahsYtzFbJg

16:43 bitemyapp: dobry-den: [com.taoensso/timbre "2.6.2"] (:require [taoensso.timbre :as t]) (t/warn "you have been warned")

16:44 dobry-den: thanks yall

16:46 Jarda: timbre seems cool

16:46 justin_smith: it even optionally does colors for tty output

16:47 I wish you could set *out* to be a specific output stream for timbre though - things still get weird under emacs/nrepl it seems

16:47 lynaghk: cemerick: hey dude

16:47 cemerick: I saw you had some patches submitted to amazonica and I was going to ask you a few questions about what you're using it for

16:48 I'm thinking about using S3 as a store for small (128kB-ish chunks) and basically need to use a gazillion threads to get any kind of throughput with that

16:48 I decided to just use the java bits manually rather than figure out how to out-reflect amazonica, though.

16:50 bitemyapp: lynaghk: are the throughput limitations due to how slow S3 is or something else?

16:50 cemerick: lynaghk: Using it for s3 + dynamo at the moment

16:51 lynaghk: bitemyapp: I think the HTTP negotiation latency dominates the transfer time

16:51 bitemyapp: lynaghk: that's what I would figure. Is there some reason you couldn't use Riak+Bitcask, Dynamo, or something else?

16:51 lynaghk: bitemyapp: there's an (old) analysis of S3 stuff here: http://improve.dk/pushing-the-limits-of-amazon-s3-upload-performance/

16:52 bitemyapp: inexpensive storage is more important that latency---things will be synced to the end machines and cached there

16:52 I just want to make sure there's bandwidth for the syncing

16:53 cemerick: lynaghk: I've not bothered benchmarking my s3 puts. Fast Enough, etc.

16:53 lynaghk: cemerick: yeah. the main issue I was having with amazonica is that everything is magic---I couldn't figure out how to twiddle the Java client options

16:54 cemerick: dropbox was (still is?) built on s3, so I suspect it's not going to get in your way, perf wise, at least until you're up at some serious scale

16:54 lynaghk: gotta use it with the javadocs open

16:54 amacdougall: coventry: I was able to debug, fix, and pull-request that library. Thanks again for the help!

16:54 lynaghk: bitemyapp: bitcask looks interesting, thanks for the pointer

16:56 bitemyapp: lynaghk: Riak+Bitcask and HDFS are good alternatives for when you need a bit more magic than S3 offers.

16:56 I didn't mention HDFS because BC seemed closer to the mark.

16:56 the LevelDB backend for Riak is for more traditional OLTP workloads.

16:57 lynaghk: a common tactic in Hadoop shops is to use HBase as an index for content stored in HDFS.

16:58 so that you have something more sophisticated than just 1-1 URLs if and when needed.

16:58 you don't want the blobs inline in HBase generally.

16:58 justin_smith: speaking of aws and alternatives, does anyone have experience with using clojure on an openstack? my company uses beanstalk but it would be nice to have options and potentially the extra power you could get with the openstack alternative

16:59 lynaghk: bitemyapp: do you know offhand how difficult it would be to package up bitcask and ship it via an uberjar?

16:59 bitemyapp: lynaghk: approximately as difficult as any Erlang application.

16:59 lynaghk: if I wanted to use it instead of the plain filesystem for a simple k/v cache (a subset of the keys avaliable in S3)

16:59 bitemyapp: no idea how difficult that is = )

17:00 bitemyapp: I'd be comfortable filing it under "ideas that are not good"

17:01 lynaghk: if you want an embedded kv store, then you should look at kyoto cabinet, derby, and LevelDB

17:01 there are pure Java ports of LevelDB and a JNI version

17:01 lynaghk: that's much wiser if you just want an embedded KV store that hits the filesystem.

17:01 lynaghk: bitemyapp: awesome, thanks for the info. will do.

17:01 technomancy: berkeleydb is the old-school choice for embedded kv

17:01 old as the hills

17:01 bitemyapp: technomancy: I was trying not to go there.

17:02 technomancy: because Oracle?

17:02 brehaut: those hills rise wild

17:02 lynaghk: ability to uberjar via lein is a big requirement

17:03 bitemyapp: lynaghk: the most robust answer for an uberjar environ is probably H2/Derby/HSQLDB. LevelDB and Kyoto Cabinet are going to mean either JNI or a port.

17:03 llasram: I've never actually used berkeleydb, but there's this great line in the `reprepro` BUGS section: "Reprepro uses berkeley db, which was a big mistake."

17:03 lynaghk: bitemyapp: you know if any of those have an idiomatic clojure API for doing, e.g., keyset intersections and batch lookups/writes?

17:04 the keys are derived from the content, so everything immutable

17:04 bitemyapp: lynaghk: you want Derby/H2/HSQLDB and to just use SQL then.

17:05 lynaghk: bitemyapp: really? I feel like the overhead of writing 10000 keys into a SQL string would dominate the useful work

17:05 technomancy: IIRC sleepycat had a history of making their license look like a BSD-style license when it was actually copyleft, and then approaching users to work out a licensing deal after they'd already written their code around it

17:05 (before they even got acquired by oracle)

17:06 bitemyapp: technomancy: hence why I was trying not to go there.

17:06 left a bad taste in a lot of peoples' mouths.

17:06 lynaghk: bitemyapp: well, it's all k/v so it shouldn't be too hard to benchmark a few different options. thanks again for the tips!

17:06 technomancy: bitemyapp: well, only if you plan on distributing

17:07 bitemyapp: lynaghk: that's not quite how I would do it.

17:07 indigo: Riak is sexy

17:07 bitemyapp: 10000 keys in a query that is.

17:07 lynaghk: bitemyapp: I haven't used those guys before---I'll take a look at the APIs and see if there's a saner way to do batch ops

17:08 it's just the first thing I thought of when you mentioned SQL.

17:08 bitemyapp: lynaghk: leveldb is more designed around batch ops than the SQL options or Kyoto Cabinet.

17:08 lynaghk: it's built on top of log-structured merge trees. I don't know how applicable it'll be to your problem, it's foreign to me.

17:08 I do a lot of database stuff and I am baffled by what you just mentioned.

17:08 I'd need more info than intersecting 10,000 keys.

17:09 lynaghk: bitemyapp: I just mean for a batch operation like, "insert 10000 keys" with SQL I'd have to write a giant query to see which of those keys already exist, subtract, and then write the new ones

17:10 since SQL strings are the only interface to SQL databases---but, like I said, maybe there are some features in the DBs that you mentioned that provide more data-oriented interfaces over just strings.

17:11 bitemyapp: lynaghk: roughly you're talking about "insert where not exists", I don't think the overhead surrounding the SQL string is a big deal when the database is embedded. It's all something that can be measured. Please blogginate if you do.

17:12 lynaghk: bitemyapp: I'd need to spend approx 20x as much work to get a suitable blog post over what I was going to just do in the privacy of my own application

17:12 = )

17:13 bitemyapp: lynaghk: at least toss me an anecdote then :(

17:14 lynaghk: bitemyapp: you have the same handle on github?

17:14 bitemyapp: lynaghk: yes. I was also in Clojure Cup.

17:14 lynaghk: bitemyapp: I'll shoot you an email when I get it all worked out

17:14 bitemyapp: lynaghk: leveldb is generally a couple micros per write and hundreds of nanos per read, with that in mind, doing the "obvious thing" (just iterating) should only take 20-30 millis.

17:14 lynaghk: is 20-30 millis to sync your 10,000 immutable keys acceptable?

17:14 lynaghk: bitemyapp: yeppers.

17:14 bitemyapp: then you could just do the "obvious" thing in leveldb and verify how long it takes.

17:15 lynaghk: yeah, will probably do that

17:17 bitemyapp: lynaghk: I feel like Hacker News has disincentivized sharing knowledge because if you don't write a perfect post criticisms come out of the woodwork.

17:17 I find this very sad :(

17:18 brehaut: you can write the perfect post, but someone will have a different perspective where the contents of that post are not relevant and they'll still complain

17:20 lynaghk: bitemyapp: nah, nothing about HN---it just takes me forever to write anything

17:20 bitemyapp: well I'll still be pleased if you toss an anecdote my way :)

17:20 indigo: Fuck it, learn through criticism!

17:20 bitemyapp: indigo: <3

17:20 indigo: :D

18:26 tyler_web: does JAVA_OPTS environment work when running `lein run`, or do I need to add to a project file?

18:29 TimMc: tyler_web: It's an environment variable, so when running `lein run`.

18:29 justin_smith: tyler_web: you can use :jvm-opts in a project.clj, or _JAVA_OPTIONS on the command line

18:30 TimMc: Oh, has the env var changed?

18:31 I see JAVA_OPTS and JVM_OPTS in the lein bin.

18:31 justin_smith: I always use _JAVA_OPTIONS

18:32 mklappstuhl: using (try () (catch ...)) is there a way to catch any exception no matter which class?

18:33 technomancy: catching Exception will catch subclasses of Exception too

18:33 justin_smith: and Exception is a subclass of Throwable

18:34 though catching Throwable may be a bit overboard

18:34 technomancy: yeah, don't catch Throwable

18:34 you won't be able to stop your program without kill -9

18:36 TimMc: You can safely catch Exception and AssertionError.

18:36 AimHere: But then again, nobody else will be able to stop it too, muHAHAHA!

18:37 mklappstuhl: Ah, that makes sense, thanks!

18:37 gfredericks: catching throwable is often useful if you're rethrowing it

18:37 there was a bug in java.jdbc regarding transaction roleback due to the fact that it _wasn't_ catching throwable

18:37 TimMc: If you get your hands on an OOM error or similar, you want to rethrow it as quickly as possible.

18:38 and with minimal allocation

18:38 mklappstuhl: I don't really know what I'm doing. Running a big job saving things to a database and I dont want it to stop if it doesn't work in one instance...

18:38 TimMc: OOM?

18:38 gfredericks: yeah just catch Exception for that probably

18:39 mklappstuhl: Will do

18:39 TimMc: out of memory

18:51 dnolen: marcopolo2: are you the author of servant? https://github.com/MarcoPolo/servant?

19:27 dobry-den: Is it possible to write an `unroll` macro so that [(unroll [:a :b :c]) bar] -> [:a :b :c :bar]?

19:29 justin_smith: dobry-den: that macro would need to look out at the thing that contains it

19:29 which is weird

19:29 and probably not at all possible

19:32 turbofail: you could get a similar effect by just using syntax-quote: `[~@[:a :b :c] ~bar]

19:33 slightly less convenient, but not too bad

19:33 dobry-den: (conj [:a :b :c] :bar)

19:34 gws: ,(flatten [[:a :b :c] :bar])

19:34 clojurebot: (:a :b :c :bar)

19:58 amalloy: dobry-den: unroll is indeed impossible to write; any non-crazy use cases are easily handled with turbofail's suggestion

20:02 marcopolo2: dnolen: yup!

20:11 eriktjacobsen: Hello

20:13 Got a question regarding dependencies. I have some sub projects that all compile fine and use aws javasdk 1.5.8, but my top level project has the bandalore library that uses like 1.3 aws java sdk, and it causes top project to fail to compile… Do I have to patch bandalore to use 1.5.8, or how can I tell it to use two version of aws-java-sdk for each of the individual projects?

20:13 this is using lein

20:15 marcopolo2: eriktjacobsen: can you post your project.clj file on refheap.com?

20:19 eriktjacobsen: marcopolo2: included the relevant paste:

20:19 https://www.refheap.com/19848

20:19 looking at it, perhaps should add rotary to top level project?

20:19 trying that now

20:20 Also perhaps I should take a step back, trying to fix this compile issue: http://stackoverflow.com/questions/19391375/clojure-leiningen-compile-error-with-multiple-projects-classnotfoundexception

20:21 Posted pointed me to the dependencies possibly linking wrong libs, so since the version showing up in top level project (1.3) doesn't have the calls I'm using in 1.5.8, i'm hoping that is the root of my compile issues

20:21 rasmusto: ,(for [a nil] a)

20:21 clojurebot: ()

20:22 rasmusto: ,(doseq [a nil] (println a))

20:22 clojurebot: nil

20:25 dnolen: marcopolo2: pretty cool, but I'm assuming it's not possible to put a piece of data into a worker w/o copying without first partitioning it first into array buffers?

20:25 marcopolo2: dnolen: thanks! yeah, unfortunately that's a limitation in web workers :(

20:26 dnolen: marcopolo2: still very cool, and seems very useful.

20:26 marcopolo2: I wish there was an immutable type you could create and transfer around

20:27 dnolen: you going to clojure/conj again?

20:28 also servant made the web worker part of the crypt demo the easiest part! as opposed to the js version where it was the trickiest part!

20:28 dnolen: marcopolo2: yess

20:28 marcopolo2: dnolen: Awesome! :D

20:28 dnolen: marcopolo2: yes, using the channels for the worker pool is really cool

20:29 marcopolo2: makes coordination triival

20:29 marcopolo2: dnolen: It really does! I kinda felt like I was cheating

20:39 bja: anyone using tmux to send-keys to their repl encountered issues with send-keys not supporting zoomed panes in tmux 1.8?

21:14 logic_prog: I have written a few macros in the past. I want to better understand how the macro compiletime/runtime works. Is this documented anywhere? [not how to write macros, but a description of when/how macro expansion works in clojure]

21:17 nightfly: Look up documentation for Common Lisp macros

21:17 brehaut: nightfly: thats not especially relevant

21:18 nightfly: How so? They behave practically identical

21:18 Unless you do AOT stuff, then all bets are off

21:19 brehaut: logic_prog: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L7140 is where to begin with specifics

21:19 logic_prog: brehaut: lol

21:19 actually wait, are you serious?

21:19 brehaut: yeah

21:19 maybe im weird in the head, but the clojrue compiler is relatively straightforward

21:20 logic_prog: where the fuck is "the annotated clojure source / rich hickey" ?

21:20 brehaut: you want anotated source? most of use would be happy with non whitesmith source :P

21:20 logic_prog: brehaut: I think the correct word is "genius" not "weird in the head"

21:20 brehaut: logic_prog: im no genius

21:21 Apage43: macroexpand(form) just calls macroexpand1(form) repeatedly until it stops getting a different result

21:21 logic_prog: https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang is the entireity of the clj source?

21:21 this actually doesn't seem so bad

21:21 brehaut: and theres an isMacro method that is used to determine if a symbol / ref refers to a macro

21:21 Apage43: and macroexpand1(form) will return form *unless* form is a seq whose first element is a symbol that corresponds to a var in the current ns that is defined as a macro

21:22 brehaut: logic_prog: its the entireity of the low level stuff; core.clj adds a crap ton of the sophisticated syntax and semantics

21:22 Apage43: in which case it will instead return the result of applying the macro fn to the rest of the form

21:23 logic_prog: (defn macroexpand [form] (let [h (head form)] (if (isMacro? h) (macroexpand-1 form) form))) ?

21:23 brehaut: close enough for government work yeah

21:23 Apage43: yeah but in java

21:23 brehaut: so its 75 lines long

21:24 Apage43: also the isMacro check is inside of macroexpand-1

21:24 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6530-L6535

21:24 logic_prog: man, that code isn't half bad

21:24 Apage43: macroexpand itself is really short

21:24 logic_prog: it looks readable too

21:25 I feel like I can read the entirety of compieler.java if I just had brehaut/Apage43 as guides

21:26 Apage43: and isMacro just checks is the key :macro is set to true on the Var's metadata

21:27 brehaut: logic_prog: compilers get complicated for about 3 reasons imho: a) monsterously recursive with many cases b) tend to have a lot of layers c) they have to generate a lot of code for all the specific features of the language

21:27 Apage43: (the isMacro in Compiler.java can also take a symbol, in which case it looks up the var, then does said check)

21:27 logic_prog: so clojure avoids this mess by "java has a JIT" ?

21:27 brehaut: logic_prog: clojure's compiler isnt especially layered, and it only has to implement the special forms

21:27 logic_prog: it avoids part of the mess due to that yeah

21:28 logic_prog: actually, here's a dumbass question

21:28 Apage43: ,(meta #'when)

21:28 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name when, :arglists ([test & body]), :column 1, ...}

21:28 logic_prog: does clojur'es compiler compile *.clj files to *.java strings and runs them on the fly, or is the clojure compiler an "interpreter for *.clj files" taht gets JITTed ?

21:29 brehaut: it compiles them to inmemory java bytecode in classes

21:29 Apage43: well the first one definitely doesn't happen. It never generates java *source*

21:29 logic_prog: Apage43: clojure is more dynamic than I thought

21:29 Apage43: it does generate jvm bytecode though, yes

21:29 logic_prog: I need one more help from the two of you, then I'll stop wasting your time

21:29 brehaut: logic_prog: thats all abstracted away in the asm package though :)

21:29 logic_prog: can you point me at where in Compiler.java clojure does the bytecode generation?

21:29 Apage43: javac : java :: Compiler.java : clj ;; sort of

21:29 logic_prog: I'm kinda interested in this as an alternative to LLVM

21:30 I want to learn how clojure does *.clj -> java asm

21:30 brehaut: https://github.com/clojure/clojure/tree/master/src/jvm/clojure/asm i think

21:30 Apage43: basically all the emit* methods are calls to the ASM library

21:31 which does the work of providing a sane way of building java bytecode programatically

21:31 logic_prog: this is fucking badass

21:31 clojure source = my new reading project

21:31 brehaut: logic_prog: part of that magic is that clojure has (if i recall correctly) a custom class loader

21:32 logic_prog: oh, all of https://github.com/clojure/clojure/tree/master/src/jvm/clojure/asm is added 6 years ago

21:32 brehaut: if i recall correctly its a third party library that is bundled with clojure?

21:32 Apage43: http://asm.ow2.org/

21:33 "ASM is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or dynamically generate classes, directly in binary form. "

21:33 brehaut: reformated in whitesmith probably :P

21:33 (https://en.wikipedia.org/wiki/Indent_style#Whitesmiths_style)

21:35 logic_prog: need to eat dinner; thanks to everyone for insightful pointers

22:01 RoboClaudio: Raynes: Many people must be bugging you with this, so I apologise if you recently answered the question, but I'm wondering: is Meet Clojure is still on hold?

22:34 amalloy: RoboClaudio: i'm pretty sure he hasn't worked on it at all recently

22:52 RoboClaudio: amalloy: thanks :)

23:20 * gfredericks spends ten minutes fixing something a static compiler would have caught

23:20 technomancy: ten whole minutes

23:21 amalloy: gfredericks: static compiler? i'm not entirely clear on what that means. does clojure have a dynamic compiler?

23:22 brehaut: (def static-compiler (constantly some-binary))

23:23 amalloy: brehaut: that's how ghc works, right? always compiles down to a lazy binary, which loads whatever code it decides you *actually* need at runtime :)

23:24 brehaut: lol :)

23:24 i dont know: ive never had a haskell program compile without a type error

23:24 amalloy: nor with a type error, i should think

23:25 brehaut: well true

23:25 brainproxy: in core.async / its docs, are "channel" and "port" synonyms?

23:26 or they convey a different meaning?

23:26 marcopolo2: brainproxy: yes

23:27 brainproxy: to the first one sorry

23:27 brainproxy: marcopolo2: thanks

23:30 coventry: I have a macro which is erroring out with a really uninformative stack trace. All it says is that something went wrong in macroexpand1, doesn't even give the line number of the form which caused the arity exception. Is this a common problem with developing macros and if so are there any tricks for getting better stack traces from macros?

23:31 marcopolo2: coventry: I usually play around with (macroexpand1 '(your-macro foo))

23:31 the will show you what your macro will expand to without running it

23:33 coventry: This is a recursive macro, though. It macroexpands its contents, then wraps the interesting contents of whatever special form is yielded by that, and will recurse on the eval. I suppose I can just trace the output of the macro at each stage.

23:34 talios: 'lo brehaut

23:34 brehaut: hi talios

23:35 marcopolo2: coventry: I did something similar a while ago, I ended up changing the inner macroexpands to macroexpand1 to see if I could spot the error

23:35 coventry: what's the macro?

23:36 amalloy: coventry: "a really uninformative stack trace" is subjective. it's often the case that if you gisted it someone could help

23:36 coventry: marcopolo2: It's a general code-transformation scheme similar to riddley.walk. In this case, I want it to wrap whatever it's passed in tracing/debugging instrumentation.

23:39 brainproxy: marcopolo2: are you aware of a larger set of examples for core.async (i.e. larger than the set in the github repo) which explores the API in more detail?

23:39 marcopolo2: brainproxy: you doing cljs or clj?

23:39 brainproxy: i must admit that it's not clear to the "why" and "how" / "how to" for many of the API features

23:39 marcopolo2: cljs mainly, at this point

23:39 coventry: amalloy: I don't need help to debug in this case, I'm just anticipating difficulties in more complex situations. But I would welcome any suggestions you have about how to read https://www.refheap.com/19855

23:39 brainproxy: for core.async I mean

23:40 clear to *me

23:40 marcopolo2: brainproxy: google david nolen's core.async tests

23:40 gfredericks: amalloy: you done known I was talkin bout static types

23:40 marcopolo2: he has some examples for some core.async cljs stuff

23:41 gfredericks: amalloy: gotta sacrifice clarity if I'm gonna fit my IRC comments within 140 characters

23:41 marcopolo2: brainproxy: but it's pretty simple, in cljs you can just use the go blocks

23:42 brainproxy: marcopolo2: right, playing around already

23:42 marcopolo2: brainproxy: Anything in particular tripping you up?

23:42 brainproxy: no, just looking over the API, which seems to have grown since last time I tinkered

23:42 stuff like onto-chan, admix, mult

23:43 maybe i just didn't look that closely beforehand, not sure

23:43 amalloy: coventry: line 73 of wrap_macro_test, right? contains a call to wrap3/walk-wrap, with the wrong number of args

23:43 brehaut: talios: hows things?

23:43 marcopolo2: brainproxy: o wow, you are right. never saw those before

23:46 coventry: amalloy: No, that is the initial test form. The call to wrap3/walk-wrap is actually in wrap-macro/wrap-form*, a couple of layers down the stack.

23:47 marcopolo2: brainproxy: the source is pretty helpful

23:47 brainproxy: marcopolo2: that is a true statement

23:47 :)

23:47 i just like examples

Logging service provided by n01se.net