#clojure log - Dec 25 2012

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

0:19 callen: muhoo: I wasn't aware he had kids.

0:19 muhoo: somebody that tall must have a hell of a time bending underneath a Christmas tree.

0:20 Raynes: it amuses me that all the companies that build on Amazon don't bother build in cross-region failover

0:20 bother to build in*

0:24 muhoo: yikes, now googlecode is giving me 40s

0:24 404s

0:25 heh, if googlecode was giving me 40s, i'd be spilling them on the ground in honor of all the fallen servers, yo

0:25 Raynes: Hahaha

0:26 muhoo: does googlecode use.... amazon?

0:26 Raynes: Whenever refheap goes down, netflix goes down, so I'm like "Yo, netflix is down too, yo."

0:26 They have a team. I have a me.

0:26 muhoo: OK, WHO BROKE THE INTERNET?

0:27 seriously, there are some pissed off ops guys all over the world right now getting SMS's at a time they definitely don't want them

0:28 Raynes: Funfact: mics work better if you remember to plug them into the pramp.

0:28 preamp*

0:28 muhoo: Raynes: setting up for a gig?

0:28 Raynes: Sure

0:28 I've got a crowd of one person. Me in the mirror.

0:29 muhoo: check 1, 2, check 1, 2. 2. 2. 2

0:32 http://online.wsj.com/article/SB10001424127887324660404578200383908151240.html yep, netflix out too

0:41 Raynes: That awkward moment when you finish a massive vocal performance and realize you weren't recording it.

0:46 bbloom: Raynes: took a shower?

0:46 Raynes: ?

0:47 Sgeo: bbloom was thinking you were singing in the shower.

0:47 Raynes: I don't think I'd take a preamp into the shower.

0:59 muhoo: Want some Raynesong for Christmas?

1:00 muhoo: sure!

1:00 didn't know you were a musician

1:00 Raynes: I'm not, really.

1:00 I just like to sing.

1:01 And some people tell me I'm pretty good at it.

1:01 So yey

1:59 ibdknox: Raynes: I got annoyed with entitlement http://www.reddit.com/r/Clojure/comments/15cspw/luminus_my_attempt_at_a_clojure_web_framework/c7ltq2b

2:01 yedi: you tell em

2:01 asina12: i am using emacs+nrepl....how do people use it to navigate clojure source code?

2:02 yedi: ibdknox: on a somewhat related note: did you get to check out luminus at all?

2:03 ibdknox: yedi: Raynes and yogthos were talking about it earlier. The template is something he was intending to do anyways and it sounds like the few things that are in luminus right now will get merged into lib-noir

2:14 muhoo: yep, with free software "if it breaks you keep both peices"

2:20 the person to fix it can be found by looking in the nearest mirror

2:22 * muhoo speaks as someone at this moment spelunking through the source code to libvorbis and vlc to find/fix a bug causing certain ogg files not to play on android

2:48 Raynes: ibdknox: Excellent.

2:50 ibdknox: Loved every second of it.

2:51 Would read again

2:51 ibdknox: lol

2:51 I've been getting this crap a lot lately, and it makes me sad.

2:51 I really, really try to help

2:51 but there's just only so much I can do

2:51 clojurebot: Pardon?

2:51 yedi: even clojurebot is givin you shit

2:52 ibdknox: lol

2:52 Raynes: ibdknox: Don't worry about it. I'll fight the good fight.

2:54 ibdknox: I don't blame you for anything. By time you stopped maintaining Noir, I had already switched to Compojure for unrelated reasons.

2:55 I maintained Noir (as much as I could) entirely as a service to the community.

2:55 ibdknox: I know, and thanks for that :)

2:55 Raynes: But it just got to be silly.

2:55 The batteries included thing doesn't mean much when there are only three batteries.

2:56 ibdknox: and like I said, that whole thing is just a matter of a template

2:56 Raynes: I'm honestly surprised that having to add three deps instead of one is really upsetting people.

2:56 ibdknox: at that point they really are basically equivalent

2:56 bbloom: stop worrying about it guys

2:56 Raynes: Exactly.

2:56 bbloom: there will always be people who love frameworks

2:56 they are wrong

2:56 but they will always be wrong

2:56 and once they learn better, there will be lines of framework lovers right behind them

2:56 you'll never win

2:57 so just bite your tongues and turn the other cheek and some other cheese sayings... then you'll be happier

2:58 Raynes: I think this template is going to go a long way.

2:58 ibdknox: yeah

2:58 Raynes: I'm going to try to help him with it and get info out there about it.

2:58 bbloom: basically just a lein newnew plugin? :-P

2:58 a new newnew?

2:58 Raynes: I'm going to merge his lib with lib-noir in a few days after I look it over.

2:59 Gonna be legendary.

2:59 bbloom: Just a template for lein-newnew.

2:59 lein-newnew is extensible.

2:59 bbloom: right, a new newnew template

2:59 Raynes: Yes.

2:59 * Raynes brainfart

2:59 bbloom: heh

2:59 ibdknox: the new newnew's new template for the new lib-noir style of writing new websites

3:02 Raynes: ibdknox: You know, both 4clojure and refheap use lib-noir+compojure

3:02 Have for quite a while.

3:02 It's pretty great.

3:02 ibdknox: :)

3:02 Raynes: Noir really had some great libraries.

3:03 ibdknox: eh, they're very simple :)

3:03 Raynes: They're still great though.

3:03 I'm happy to replace sandbar's stateful sessions.

3:04 ibdknox: yeah, he dropped that a *long* time ago

3:04 it hadn't really been touched by the time I even started Noir

3:05 Raynes: bbloom: https://groups.google.com/d/msg/clj-noir/AbAvQuikjGk/mlYuC8ChW44J This sort of thing scares me though, man.

3:05 Look at the planned features. At the end, he even lists "??? What else would you like this to do."

3:06 Should have named it kitchen-sink

3:06 bbloom: Raynes: hey man, i get it. i built a serious app on rails

3:06 it was *fucking awesome*

3:06 until about 6 months later

3:06 then it was *not so fucking awesome*

3:06 all-in-one can be really really attractive if you're in a hurry

3:06 particularly if it's popular

3:06 ibdknox: I don't think you have to sacrifice that ease though

3:07 bbloom: for all the absolutely horrible, evil, black magic fucking terrible unholy things that rails does

3:07 i love rails

3:07 it's absurdly productive....

3:07 .....at first

3:07 and if you're a contract crud web app sort of guy

3:07 Raynes: bbloom: The worst part is the guy replying to the guy I linked said "It's nice to see the Clojure web stack maturing"

3:08 I die a little inside when people correlate the library approach to immaturity.

3:08 bbloom: Raynes: like i said: probably better to ignore those people

3:08 Raynes: I want to educate these people. Violently.

3:08 bbloom: however, one of the nice things about the clj community is the refusal to do the dumb things that other communities do

3:08 Raynes: $dict brainwash

3:08 lazybot: Raynes: verb-transitive: To subject to brainwashing.

3:09 Raynes: $dict brainwashing

3:09 lazybot: Raynes: noun: Intensive, forcible indoctrination, usually political or religious, aimed at destroying a person's basic convictions and attitudes and replacing them with an alternative set of fixed beliefs.

3:09 yedi: what are some of the not so nice things about the clj community

3:09 ibdknox: we don't focus on beginners in any reasonable way

3:09 which is what Noir was originally about

3:10 Sgeo: Does Factor's Furnace count as a "framework"?

3:10 Or as a library?

3:11 ibdknox: yedi: the benefits of Clojure are non-obvious to most and so it ended up drawing a very intellectual and seasoned crowd of people to it

3:11 for most of the guys here, picking up something new is fairly trivial

3:11 muhoo: everyone who doesn't get this topic should watch rhickey's "simple vs. easy" presentation

3:12 "i love rails! it's so easy!" .... simple != easy

3:12 Sgeo: http://re-factor.blogspot.com/2010/08/hello-web.html (might be slightly old)

3:12 Anderkent: https://gist.github.com/4372203 has oneone written this before? Macroexpand that does not crash on not-yet-loaded classes

3:12 Sgeo: Hmm, there's a way to make actions besides subclassing :/

3:13 Anderkent, does it work with macros that use &env?

3:13 Anderkent: it passes anything that's actually a macro on to (macroexpand)

3:13 only handles java interop itself

3:13 Sgeo: Does it do the right thing with '(quote ..... oh

3:13 It's not supposed to recursively macroexpand? Ok.

3:14 Anderkent: no, does the same thing as macroexpand :) Recursive macroexpansion is a bit more difficult, you have to track the lexical scope yourself etc

3:15 muhoo: bbloom: actually i'm writing contract crud web apps in clojure. takes me 50 hours to do stuff i could do in 10 hours in rails or PHP, and i only get to bill for 10.

3:16 but i get to write in a language i actually like, so, win.

3:16 yedi: muhoo: really? it's that bad?

3:16 why..?

3:17 muhoo: not bad, i'm just new to clojure.

3:17 and, there are so many slap-it-together cut-and-paste libraries available for, say yii or rails, but in clj i have to roll stuff on my own.

3:18 yedi: i c

3:18 muhoo: when it comes to boilerplate apps, working in a language that has lots of boilerplate libraries is an advantage.

3:22 amalloy: Anderkent: your implementation of macroexpand-1 seems to delegate to macroexpand, not to macroexpand-1

3:23 Sgeo: Anderkent, I only know one person who got recursive macroexpansion in Clojure right, and for some reason it doesn't seem to be very plug-and-playable into clojail

3:24 Although I guess it could be argued that it is not in fact right.

3:25 PudgePacket: Can anyone explain why this doesn't work ? http://pastebin.com/4d2JmL7D

3:25 seems like it should, returning a list of string from the str function

3:26 amalloy: ,("a" "b" "b")

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

3:26 PudgePacket: oh

3:26 i forgot to quote the list

3:26 amalloy: ,["a" "b" "b"] ;; or, (list "a" "b" "c")

3:26 clojurebot: ["a" "b" "b"]

3:26 PudgePacket: siiiiiiiiiigh

3:26 muhoo: yedi: but i recently had to transform some oddball XML RDP-ish tuples from one service into a completely diffrent JSON format for consumption by a different service, and i was able to do that faster and way more fun in clojure than in anything else i knew.

3:26 amalloy: or, as you say, quote it

3:26 PudgePacket: thanks anyway :P

3:28 muhoo: ok, enjoy your holidaze, all

4:10 dimovich: hello ppl

4:10 is there a better way to do (into (into array1 array2) array3)

4:10 ?

4:10 bbloom: dimovich: by arrayN do you mean a java array? or a clojure sequence?

4:10 dimovich: clojure sequence

4:11 bbloom: (doc into)

4:11 clojurebot: "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

4:11 bbloom: ,(into [] (concat (range 5) (range 10 15) (range 20 25)))

4:11 clojurebot: [0 1 2 3 4 ...]

4:12 bbloom: dimovich: does that help?

4:12 dimovich: yes, thanks :)

4:12 forgot about concat :)

4:12 bbloom: dimovich: you can skip the into, if you don't need a vector

4:12 ie just leave it as a lazy seq

4:12 dimovich: ok

4:13 bbloom: or you can use vec

4:13 (doc vec)

4:13 clojurebot: "([coll]); Creates a new vector containing the contents of coll."

5:11 francis: Hello all, I'm having an issue figuring out how to quote a form - https://gist.github.com/4372506

5:12 I'd like to accept any arbitrary form, (including quoted) and then use a quoted form in my fn, but I'm not sure how to do that

5:12 thoughts?

5:14 bbloom: (doc symbol?)

5:14 clojurebot: "([x]); Return true if x is a Symbol"

5:14 bbloom: ,'x

5:14 clojurebot: x

5:15 bbloom: ,''x

5:15 clojurebot: (quote x)

5:15 bbloom: ,(map class ''x)

5:15 clojurebot: (clojure.lang.Symbol clojure.lang.Symbol)

5:15 bbloom: ,(map name ''x)

5:15 clojurebot: ("quote" "x")

5:15 bbloom: francis: does that help?

5:16 francis: bbloom: I think so, though I need to try it out first

5:17 thanks

5:17 bbloom: francis: also realize that quoting behaves differently on symbols than it does on other types

5:17 ,'5

5:17 clojurebot: 5

5:17 bbloom: ,''5

5:17 clojurebot: (quote 5)

5:17 bbloom: ,inc ; a function

5:17 clojurebot: #<core$inc clojure.core$inc@166248d>

5:18 bbloom: ,(map class [5 '5 inc 'inc])

5:18 clojurebot: (java.lang.Long java.lang.Long clojure.core$inc clojure.lang.Symbol)

5:18 bbloom: notice how 5 and '5 are the same, but inc and 'inc are not

5:19 ,(map class [5 '5 ''5 inc 'inc ''inc])

5:19 clojurebot: (java.lang.Long java.lang.Long clojure.lang.PersistentList clojure.core$inc clojure.lang.Symbol ...)

5:19 bbloom: ,(map class [5 '5 ''5)

5:19 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

5:19 bbloom: ,(map class [5 '5 ''5])

5:19 clojurebot: (java.lang.Long java.lang.Long clojure.lang.PersistentList)

5:19 bbloom: ,(map class [inc 'inc ''inc])

5:19 clojurebot: (clojure.core$inc clojure.lang.Symbol clojure.lang.PersistentList)

5:19 francis: bbloom: interesting

5:20 bbloom: note that is two apostrophes, not a quotation mark

5:20 francis: noted

5:21 dimovich: hey guys, in enlive, how can I select all nodes with a specific property value of itemprop: (enlive/select html [:div.desc (enlive/attr? :itemprop)]))

5:21 how do I specify the itemprop value?

5:25 francis: (when (and

5:25 (= :itemprop (enlive/attr? your-html))

5:25 (= "myvalue" (enlive/get-value your-html)))

5:25 ;; do stuff

5:25 )

5:25 dimovich: do mean like that?

5:25 bbloom: francis: please use refheap for multiline snippets

5:25 francis: I'm not sure of the exact enlive fn, but is that what you mean in general sense?

5:26 dimovich: no

5:26 <div.desc itemprop="somevalue"> some text </div>

5:26 select all nodes that have itemprop=somevalue

5:27 francis: sorry, so you want to use a select with an `and` clause if I'm not mistaken

5:27 hitting docs for exact source

5:27 dimovich: yes

5:27 francis: one min

5:33 Raynes: bbloom: Hahaha

5:33 bbloom: He can't use refheap.

5:33 :P

5:33 bbloom: down?

5:33 heh.

5:33 heroku?

5:33 *sigh*

5:33 Raynes: bbloom: It's been down for hours because Heroku because AWS.

5:33 It's pretty awful.

5:34 Netflix is down too IIRC.

5:34 bbloom: because Heroku because AWS .... because EBS?

5:34 Raynes: Heroku going down for 12 hours at a time is starting to outweigh the benefits of using heroku.

5:35 bbloom: Raynes: i gave up on heroku after 6mo of using it

5:35 it's nice, but it's not nice enough

5:35 Raynes: I did it because Heroku would handle DDOS attacks which pastebins are prone to.

5:35 bbloom: heh

5:35 Raynes: But it's almost not worth it anymore.

5:35 I pay $20 for SSL that I could have for free on my VPS.

5:35 Anderkent: Well hopefully they'll move to multiple avail. zones eventually

5:35 Raynes: I expect uptime.

5:36 I'm okay with a little downtime every once in a while, but yikes, it has been like 12 hours or more.

5:37 Anderkent: but the point of heroku is not the performance, it's the ease of development. Prototyping/beta on heroku then moving directly onto AWS seems like the best bet for me

5:37 bbloom: hmm seems like ELB this time, not EBS

5:37 it's usually EBS

5:37 since EBS is a terrible idea.

5:38 Anderkent: why do you think so?

5:39 bbloom: Anderkent: the same reasons NFS is a terrible idea

5:39 the posix/unix filesystem system api is not designed to be distributed

5:39 there are system calls that just don't make sense for a distributed file system

5:39 hence the design of plan9's 9p protocol

5:41 http://joyent.com/blog/magical-block-store-when-abstractions-fail-us

5:42 http://en.wikipedia.org/wiki/9P

5:58 francis: dimovich: I would just filter by keys unless you have some other reason to use `attrs?` see: https://gist.github.com/4372608

6:02 dimovich: francis: thanks

6:03 I suppose enlive has some built in stuff for this... but this should work too :)

6:05 francis: dimovich: I would imagine it does, but I didn't see anything just quickly looking it over, I don't use it personally and don't know it well enough

6:56 callen: bbloom: good luck telling HN EBS is a bad idea.

6:56 bbloom: they love their fragile magic.

6:56 they get mad if you mention that AWS hasn't been the most reliable thing on the planet.

6:57 Raynes: Oh no, callen's awake.

6:57 * Raynes goes to bed.

6:57 callen: Raynes: :(

6:58 Anderkent: so what's the thing that's more reliable than AWS? Self-hosting?

6:58 callen: Anderkent: it's almost more of an architectural question than where your physical machines live.

6:58 Anderkent: one thing is to avoid networked filesystems that aren't very application specific (like EBS)

6:59 another is to mistrust magical load balancing, queueing, or database services (ELB, SQS, RDS)

6:59 further, keeping your machines heterogenous in *where* they're deployed, with actual procedures in place for cross-geo failover is important

7:00 Anderkent: well, aws does give you different zones for that

7:00 callen: haha, yeah, that tends not to work.

7:00 nice try though. That's been a joke for a long time.

7:00 Anderkent: do tell>

7:01 callen: whenever EBS has gone down, all the sub-zones or whatever of say, US-EAST go down together.

7:01 Anderkent: I mean I havent used AWS on anything large, so I'm really being curious, not attacking you

7:01 callen: there's no apparent separation/damage control

7:01 other downtimes have been datacenter-scale network related, so again, their separation stuff hasn't helped anything

7:01 when I say cross-geo failover, I mean from one end of the world to the other.

7:02 you'd need to have an architecture that is prepared to failover from Virginia to California

7:02 if you're not prepared to do that, have another East Coast provider that isn't AWS

7:02 and failover between those two.

7:03 but going back to my original point, the customers of the companies using AWS (Netflix, Heroku) haven't started getting punished by their customers, so they haven't been incentivized to fix the downtime.

7:03 Anderkent: well that's what I was thinking about, host stuff on EU + one US region, that hopefully gives you something to fail over to>

7:03 callen: I have to say though, Netflix downtime on Christmas Eve is pretty choice.

7:03 Anderkent: hypothetically yes, in practice, nobody takes advantage of that sort of thing.

7:04 which I thought was the original point of AWS, but w/e

7:04 self-hosting *could* be more reliable. at the very least, Google, Facebook, and Twitter have for the last couple years had considerably less downtime than AWS US-EAST

7:05 it's just that for most companies it wouldn't be because they wouldn't be able to invest in the infrastructure properly.

7:05 Anderkent: most of us aren't google, facebook or twitter though, and building our own datacenters is usually not an option

7:05 callen: that's what I said, yes.

7:05 Anderkent: yeah I type a little slow :P

7:05 Raynes: callen: I think I've already decided to move refheap back to my VPS. It has been down for around 12 hours because of this shit.

7:05 Unacceptable.

7:05 Heroku's benefits aren't worth this. This is the second time this has happened.

7:06 But yeah, going to bed for real now.

7:06 Anderkent: so I don't see any alternatives for middle-size companies, where the app is too large to self-host, but too small to warrant branching into infrastructure

7:06 callen: Raynes: incidentally, I have 3 accounts on Heroku, 2 of the 3 have been HTTP 500'ing on login for the past week.

7:06 Anderkent: I see plenty of alternatives.

7:07 Anderkent: well, there's Rackspace, but i'd rather handle aws occasionally going down...

7:08 callen: Anderkent: Rackspace acquired Cloudkick, so they have a lot of the same tooling now.

7:08 Anderkent: there's a ton of damn decent VPS providers, there's Joyent, etc.

7:08 Anderkent: Joyent is pretty price/performance competitive with AWS and doesn't seem to have the ritualized tri-monthly downtime.

7:09 Anderkent: it may not matter for you to have downtime, but it's a pretty serious matter in my day-to-day to have sustained downtime like this.

7:10 Anderkent: I've gotten intensely unpleasant phone calls in the past over 2-3 minute blips before.

7:10 if I was responsible for a product that'd been down for 12+ hours, I would've started the human sacrifices by now.

7:11 Anderkent: yeah, I haven't seen joyent before, will look into that. I'm rather awerse to rackspace after trying to debug kernel panics with them and finding out their support staff has almost no familarity with red hat, while they enforce the os on anyone using managed hosting

7:12 callen: Anderkent: I use a mixture of Linode, Rackspace, Softlayer, and AWS.

7:12 but nothing "live" to any customers goes on AWS.

7:12 I don't trust them and likely never will.

7:12 only backups, batch work, etc go on AWS.

7:15 Anderkent: heroku are on n. virginia too? That's the region having most issues, isn't it?

7:15 callen: Anderkent: it's almost always NVA that has issues.

7:15 Anderkent: that's also where like 90% of the customers are.

7:15 the secret to using AWS is to never ever use US-EAST :P

7:16 the first time anything is going to break, it'll happen there first

7:16 my AWS stuff is US-WEST

7:17 mostly Oregon

9:16 xeqi: Anderkent, Raynes: you could try openshift

9:26 wkelly: xeqi: have you run anything production on openshift?

9:27 xeqi: nope, I'm weary of a service without prices

9:28 wkelly: ^

9:29 wkelly: understandable

9:29 xeqi: though if jcrossley3 or tcrawley|away get openshift auto-clustering working on it I might be really tempted

9:29 well.. I'm already really tempted

9:29 * immutant auto-clustering

9:30 wkelly: I haven't met anyone who has really kicked the tires on it, but I enjoyed playing with it

9:30 it was nice and easy to deploy clojure to!

9:31 I don't know what kind of guarantees you can get about running on different physical hosts and so on for proper clustering

9:39 xeqi: wkelly: thanks, glad to hear from someone whos tried it out

9:41 theadmin: Hello. I want to learn Clojure, but I can't seem to find any decent starters tutorial anywhere. Any kind of LISP is entirely new for me, my only functional language was Haskell

9:42 gfredericks: theadmin: 4clojure.com

9:43 theadmin: gfredericks: Hm, interesting. Thanks.

9:46 wkelly: theadmin: if you are familiar with java, http://java.ociweb.com/mark/clojure/article.html can be helpful

9:46 probably even if you are not

9:46 theadmin: wkelly: Am not

9:57 gfredericks: Hm, well, I'm messing with http://www.4clojure.com/problem/16 and my solution is: (fn hai [firstName] (str "Hello, " firstName)) but it fails. Can't quite see why.

10:01 terom: theadmin: note rhe "!" at the end

10:01 theadmin: terom: Oh durr

10:06 Ok this started to get very confusing

10:37 Anderkent: remind me, bindings are thread local?

10:37 si14__: is it a bug, guys? (name (keyword "/foobar/:baz/bar")) => "bar"

10:38 Bronsa: ,(namespace (keyword "/foobar/:baz/bar"))

10:38 clojurebot: "/foobar/:baz"

10:39 si14__: looks like a bug to me.

10:39 bawr: What would you expect?

10:39 Bronsa: why so?

10:39 si14__: I would expect that (name (keyword x)) == x

10:39 Bronsa: (name :foo/bar)

10:39 ,(name :foo/bar)

10:39 clojurebot: "bar"

10:40 Bronsa: ,(namespace :foo/bar)

10:40 clojurebot: "foo"

10:40 Bronsa: ,(str :foo/bar)

10:40 clojurebot: ":foo/bar"

10:40 Bronsa: ,(name (keyword "foo/bar"))

10:40 clojurebot: "bar"

10:40 Bronsa: ,(namespace (keyword "foo/bar"))

10:40 clojurebot: "foo"

10:41 si14__: it's an abstraction leak, isn't it?

10:41 Bronsa: actually is a wanted feature

10:41 Anderkent: Looks more like non-conforming keyword to me? You want to be able to refer to keywords from other namespaces, which you do with a /

10:42 si14__: "keyword" that doesn't escape it's argument?

10:42 yeah

10:42 definitely a feature :)

10:43 Anderkent: ,(namespace (keyword "Foo" "bar"))

10:43 clojurebot: "Foo"

10:43 Bronsa: err? think about it / is used to separate the namespace from the name

10:43 if "foo/bar" was a valid name, there would be no way to safely parse :foo/bar/baz

10:43 is the name bar/baz or is it baz?

10:44 is the namespace foo/bar or is it foo?

10:44 Anderkent: uh no :foo/bar/baz is pretty easy to parse, :<whatever><space> parses to keyword with name = whatever ?

10:46 si14__: Bronsa: I think Anderkent is right

10:46 bawr: And what about namespaces?

10:46 Anderkent: bawr: name.space/:keyword ?

10:47 Bronsa: i think you may have misunderstood what i was trying to say

10:47 si14__: you are complaining of the fact that in clojure there is no way for "foo/bar" to be parsed as a name

10:48 and I'm telling you that there is a reason why that CAN'T be done

10:48 Anderkent: Bronsa: and the reason is?

10:48 Bronsa: ok, suppose you want a keyword with namespace "foo" and name "bar/baz"

10:49 that would print out as :foo/bar/baz

10:49 Anderkent: oh okay didn't know it puts the : before the ns

10:49 Bronsa: yeah

10:49 Anderkent: weird

10:49 but ok

10:50 Bronsa: if it was the case that a namespaced keyword prited as ns/:bar then it would be possible

10:50 printed*

10:50 but i don't think that'd be a good idea anyway

10:51 si14__: ok, thanks.

10:52 Bronsa: so, the current behaviour of the reader is to take until the last / and consider that the namespace part, and the rest the name

10:56 Anderkent: Any suggestions for large-ish clojure libraries to try my test coverage library on? For now tried incanter and ring, anything else?

11:05 xeqi: Anderkent: could try it on the leiningen source

11:07 Anderkent: nice idea, thanks

11:08 xeqi: or chesire, clojail, compojure, etc. not sure those would be "large" though

11:13 Anderkent: lein master branch is a dev or release branch? Can't run the tests there it seems..

11:15 Bronsa: lein master branch is dev

11:15 xeqi: Anderkent: there is some minor steps required to bootstrap lein atm, https://github.com/technomancy/leiningen#building

11:16 though it does require lein1

11:16 though I think the tests are failing on master

11:17 Anderkent: i get failures at preview as well ;/

11:17 xeqi: yeah, might bee better to come back to that one :p

11:18 Anderkent: well I should be able to run coverage even with failures, so I'll try and see what happens :P

11:28 xeqi: Anderkent: I wouldn't mind seeing stats on https://github.com/xeqi/peridot or https://github.com/xeqi/kerodon

11:37 Anderkent: think I need to give up on lein as it seems to just call System/exit if I do clojure.test/run-tests instead of running it from via lein test ...

11:37 oh, I suppose I can just not run compilation tests ;p

12:15 How can I add a dependency to a lein project from a lein plugin?

12:16 yedi: postgres and redis seems like a winning duo

12:17 Anderkent: ah, found it, nvm

12:19 Baughn: Does clojure have a different notion of classpath than java?

12:20 I ask because.. well:

12:20 gfredericks: no

12:20 Baughn: $ java -cp . -jar ../../lib/clojure-1.4.0.jar

12:20 user=> (compile 'boom.core)

12:20 FileNotFoundException Could not locate boom/core__init.class or boom/core.clj on classpath: clojure.lang.RT.load (RT.java:432)

12:20 $ ls boom/core.clj

12:20 boom/core.clj

12:20 clojurebot: nstools is a library to reduce repetition in your ns clauses: http://code.google.com/p/clj-nstools/

12:23 Anderkent: Baughn: try printing the classpath, see if the dir is on the list?

12:23 Baughn: Anderkent: Sure.. how?

12:23 Anderkent: ,(println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))

12:23 clojurebot: #<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission getClassLoader)>

12:23 Anderkent: well, it will work for you :P

12:24 Baughn: Hm, that gives just the clojure .jar

12:24 Odd.

12:28 Anderkent: try `java -cp '.:../../lib/clojure-1.4.0.jar' clojure.main`

12:28 i'm not sure how -cp and -jar interact

12:28 Baughn: Yeah, that's the trick. They don't.

12:31 yogthos: oh hey I ran into this yesterday

12:31 -cp doesn't like jars not being in the same folder

12:32 Baughn: I figured it out. I just need to not use -jar.

12:32 Not nice of java to just swallow the -cp, though

12:32 yogthos: no it's not ;)

12:33 the way classpath works is not terribly intuitive

12:45 svedubois: How I can translate this line in java to clojure?

12:45 filter.setSigma( Double.valueOf( sigma ).doubleValue() );

12:46 Is this OK? (.setSigma filter (Double/valueOf (sigma) doubleValue))

12:48 yogthos: looks reasonable

12:49 err

12:50 (.setSigma filter (Double.valueOf (.doubleValue sigma)))

12:52 edlothiol: still not right, (.setSigma filter (.doubleValue (Double/valueOf sigma)))

12:52 although Double.valueOf(sigma).doubleValue() can be simplified to Double.parseDouble(sigma), I think

12:53 i.e. (.setSigma filter (Double/parseDouble sigma))

12:53 yogthos: you could also thread it, eg: (->> sigma .doubleValue Double/valueOf (.setSigma filter))

12:55 I find the threading syntax is a bit easier to follow, since it flattens the expression

12:56 svedubois: It seems that works, but I get an exception:

12:56 Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: doubleValue for class java.lang.String

12:56 I need to import something for doubleValue?

12:57 edlothiol: it should be (->> sigma Double/valueOf .doubleValue (.setSigma filter)), but you should really just use Double/parseDouble

12:58 kovas: anyone doing some xmas coding?

12:59 yogthos: yeah if sigma starts out as a string

12:59 svedubois: Thanks it works!

12:59 yogthos: cool

13:00 Anderkent: kovas: yes :P

13:00 kovas: Anderkent: best present: time to code on fun projects :0

13:01 yogthos: :)

13:02 jonasen: kovas: I'm working on the Java Codeq analyzer.. that's a lot of fun!

13:03 kovas: jonasen: cool! is there a github?

13:03 I'm working on session

13:04 Anderkent: hah, I'm hacking on a code coverage tool : https://github.com/JacekLach/cloverage . Should be ready for a beta test... :P

13:04 jonasen: kovas: It's at https://github.com/jonase/codeq/tree/java

13:05 kovas: nice. i am ready for the next level of tooling

13:06 ibdknox: relatedly, I'm working on LT :)

13:07 jonasen: kovasb: here's a query https://gist.github.com/4374467

13:12 kovas: Session looks awesome! Would love to help out on that project

13:12 kovas: jonasen: thanks!

13:12 jonasen: theres a bunch of stuff to do :) I think I'm gonna spend some time opening tickets and improving the documentation right now..

13:14 svedubois: I have translate this java code to clojure:

13:14 Java:

13:14 ImageFileReader reader = new ImageFileReader();

13:14 reader.setFileName(input);

13:14 Image img = reader.execute();

13:14 Clojure:

13:14 (defn main [input]

13:14 (let [reader ( ImageFileReader.)

13:14 img (Image.)]

13:14 (.setFileName reader input)

13:14 (def img (.execute reader))))

13:14 I have problems to convert "img" from java to clojure.

13:14 I am not sure that:

13:14 Image img = reader.execute();

13:14 Is the same that (or even valid):

13:14 (def img (.execute reader))))

13:15 Anderkent: it is (assuming it's a top level declaration, otherwise probably (let [img (.execute reader)] ...) is what you want)

13:15 oh, didn't see your earlier example

13:16 what you want is something like

13:16 yedi: session looks sweet

13:16 is there a demo up somewhere?

13:17 Anderkent: (let [img (-> (ImageFileReader.) (.setFileName input) .execute)] <do something to img or return it>)

13:19 kovas: yedi: will try to get a screencast up in the next few days

13:25 yedi: kovas: let me know when you finish documenting/ticketing

13:27 kovas: yedi: sweet, will do :)

13:32 miloshadzic: is there a recommended test framework for clojure?

13:32 zilti: Anderkent: Wouldn't it be more clear to use .. instead of -> to chain java stuff?

13:33 miloshadzic: There's the official one built in, and there are several others, but the most mature is probably midje.

13:34 Anderkent: zilti: .. has different semantics - .. chains the results, -> chains the first expression through all statements

13:35 zilti: Anderkent: Oh. Yes, right.

13:35 miloshadzic: zilti, I guess the builtin one will do for now

13:36 zilti, (thanks)

13:37 zilti: miloshadzic: no problem. But I'd really recommend at least taking a look at both before deciding.

13:38 Anderkent: midje is pretty cool, though I still wrap midje tests in (deftest) so anything that works with clojure.test will work with my tests

13:38 (for example the mvn plugins)

13:38 miloshadzic: zilti, I'm kinda new to Clojure. I use RSpec most of the time in ruby

14:48 zilti: What would be the better variant to search for a function you added in a list with a bunch of functions - to store additional metadata at the fn when adding it or to store the fn at a second place to compare?

14:50 ...or probably even better, to work with hash values.

14:51 svedubois: Is this java to clojure conversion correct?

14:51 image = new Image ( 256, 128, 64, PixelIDValueEnum.sitkInt16 );

14:51 (def image (Image. (256 128 64 PixelIDValueEnum/sitkInt16)))

14:52 zilti: svedubois: "new" exists in clojure, too.

14:53 svedubois: I get this error: clojure.lang.Compiler$CompilerException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn, compiling:(Image.clj:7:20)

14:53 bbloom: svedubois: you're trying to call (256 128...)

14:53 you have extra parens

14:53 zilti: (new java.awt.Image 256 128 64)

14:53 ,(new java.awt.Image 256 128 64 PixelIDValueEnum.sitkInt16)

14:53 clojurebot: #<CompilerException java.lang.RuntimeException: java.lang.ClassNotFoundException: PixelIDValueEnum.sitkInt16, compiling:(NO_SOURCE_PATH:0)>

14:54 svedubois: Thanks, it works: (def image (Image. 256 128 64 PixelIDValueEnum/sitkInt16))

14:54 bbloom: svedubois: for the record, (Foo. x y z) is just shorthand for (new Foo x y z)

14:59 zilti: How ugly is this?

14:59 (defn remove [arg] (if-not (= (class java.lang.Integer) (class arg)) (remove (hash arg)) (...code...)))

14:59 clojurebot: marg is 1

15:00 zilti: (and what is "marg is 1"?)

15:00 bbloom: zilti: what are you trying to accomplish?

15:02 zilti: bbloom: making a function that removes an entry from a list, and if the argument is not an Integer/hash-value, calc the hash and retry.

15:02 bbloom: (doc remove)

15:02 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns false. pred must be free of side-effects."

15:03 zilti: But since Clojure is dynamically typed.

15:03 bbloom: ,(map (comp class hash) [1 2.0 "3"])

15:03 clojurebot: (java.lang.Integer java.lang.Integer java.lang.Integer)

15:03 zilti: Yes, I know remove.

15:03 bbloom: ok all integers rather than longs

15:03 zilti: (hash remove)

15:03 &(hash remove)

15:03 lazybot: ⇒ 21755981

15:04 bbloom: so you wish there was some sort of hash-value? predicate?

15:04 why are you working with hash values directly?

15:05 zilti: bbloom: I thought it's cheaper to keep only the hash-value of a function instead of the whole function, for when I later want to remove that function from the list.

15:06 bbloom: zilti: have you profiled and found that optimization to be worthwhile? is that even an optimization. with boxing of integers, i wouldn't be so sure

15:08 zilti: bbloom: No, I didn't do that. But I thought it's "ugly" to keep the whole function lying around and all that. But it's probably not worth the effort.

15:09 bbloom: also what are the collision characteristics of clojure's hash function? since it's an integer and not like a 128 secure hash, you need to worry about that

15:09 what would be ugly about it? you're not keeping anything "lying around" that's what garbage collection is for

15:09 zilti: &(= (hash (fn[x](* 2 x))) (hash (fn[x](* 2 x))))

15:09 lazybot: ⇒ false

15:09 bosie: s it possible that midje's provided only works on calls for the very last function?

15:09 svedubois: How I can obtain the value of image (instead of #<Vector...)?

15:09 (.getSize image)

15:09 #<VectorUInt32 org.itk.simple.VectorUInt32@3a432ed2>

15:10 bosie: anything i call prior to the last function seems to not get mocked, somehow.

15:10 zilti: svedubois: (. image getSize)

15:10 bbloom: zilti: that's precisely the same as (.getSize image)

15:11 svedubois: the vector you're getting back is a java object

15:11 you can inspect it with interop, if the itk library doesn't provide a decent toString

15:18 svedubois: Using toString, I obtain this:

15:18 (.toString (.getSize image))

15:19 "org.itk.simple.VectorUInt32@52c9f3c7"

15:19 bbloom: svedubois: right, the default printing behavior in clojure is to call toString and wrap it in those #<...> things

15:20 svedubois: in this case, there isn't a good toString for that function, so you need to inspect the object's fields directly with (.getX vector) or whatever the functions are called

15:22 svedubois: When I use this:

15:22 (.toString image)

15:22 It prints a long text:

15:22 "Image (0x7fc51c0047b0)\n RTTI typeinfo: itk::Image<short, 3u>\n ... Size: [256, 128, 64]\n ... Size: 2097152\n ...

15:23 bbloom: If you want, you can define a print behavior for a foreign type by doing (defmethod print-method VectorUInt32 [obj writer] (print-simple (str obj) writer))

15:23 svedubois: what exactly are you trying to accomplish?

15:51 Seba51: Happy Christmas to all of you.

15:52 I am learning clojure and have issues to understand a specific problem with macros.

15:52 bbloom: Seba51: ask away

15:54 Seba51: The book uses the following sample for a macro: (defmacro unless [expr form] (list 'if expr nil form)). I am wondering why they do not use (defmacro unless [e f] if e nil f) which seem to work as well

15:54 What is the motivation to use list?

15:54 gfredericks: yours seems to work?

15:55 Seba51: Sorry brackets were missing around if

15:55 gfredericks: even so

15:55 Seba51: (defmacro unless [expr form] (if expr nil form))

15:56 gfredericks: ah ha

15:56 that's a little more understandable

15:56 * gfredericks tries to work out a counterexample

15:56 Seba51: (unless true (println "x"))

15:57 gfredericks: try (unless (= 1 2) 42)

15:58 Raynes: Bodil: Worst thing ever is hearing "I tried it, but it didn't work." :p

15:58 I'm not currently aware of any bugs in conch, so definitely need reports when people find them.

15:59 Seba51: (unless 1 2) prints nothing

15:59 nil

15:59 gfredericks: which you want

15:59 but (unless (= 1 2) 42) should give you 42

15:59 svedubois: When I try to print the Size of an image:

15:59 (.getSize image)

15:59 I get this:

15:59 #<VectorUInt32 org.itk.simple.VectorUInt32@31ac8cf3>

15:59 And using toString:

16:00 (.toString (.getSize image))

16:00 I get this:

16:00 "org.itk.simple.VectorUInt32@981f674"

16:00 Looking the class getSize is inside VectorUInt:

16:00 public VectorUInt32 getSize()

16:00 {

16:00 return new VectorUInt32(SimpleITKJNI.Image_getSize(swigCPtr, this), true);

16:00 }

16:00 Is there any easy way to print the numbers of getSize?

16:00 gfredericks: svedubois: refheap.com

16:00 bbloom: svedubois: like i tried to say: you need to call accessor functions on that VectorUInt object

16:01 Seba51: * need a moment to understand the answer *

16:01 bbloom: consult the javadocs or something for the library you're using

16:01 Raynes: Oh great, refheap is actually up now?

16:01 I've got moving that thing off of Heroku on my todo list.

16:03 bbloom: i have a bunch of helper functions for working with zippers. i use the main zipper library (require '[clojure.zip :as zip]) but want to move all my helper functions into a separate namespace too

16:03 i kinda wish i could do (require '[bbloom.zip :as zip]) and have the zip alias just be like an extended version of the clojure.zip namespace

16:04 is there anyway to do that other than to loop over ns-publics and call intern on each?

16:04 Seba51: Having (defmacro unless_ [expr form] (list 'if expr nil form)) and (defmacro unless [expr form] (if expr nil form)), both print the same for (unlessl 1 2) 42

16:05 bbloom: Seba51: consider side effects: (unless true (print "omg!"))

16:05 jonasen: kovas: I've got session running and started to read through some of the code.

16:05 kovas: jonasen: nice. let me know if u have any questions

16:05 jonasen: kovas: I updated to latest clojure/clojurescript/datomic/cljsbuild and it seems to work still

16:06 kovas: jonasen: i just created a bunch of tickets, working on cleaning up / commenting the code

16:06 jonasen: great, if u make a pull request I'll just update it

16:08 gfredericks: Seba51: what is your understanding about the difference between a macro and a function?

16:08 jonasen: kovas: I also made some trivial clean-up of session.datomic. I'll send you a pull request

16:09 kovas: jonasen: awesome, thanks!

16:10 Seba51: Functions are evaluated immediately

16:11 gfredericks: Seba51: macros are functions on code. Their input is code, and their output is code.

16:11 the definition in the book uses list because it wants to return an if expression, but if expressions are lists that begin with the 'if symbol

16:12 your definition, instead of returning an if expression, either returns the second argument or nil

16:12 and it decides how to do that based on the truthiness of the first argument (expr)

16:12 but that argument is unevaluated code

16:13 so if it is an expression such as (= 1 2), even though it would evaluate to false, as code it is truthy

16:13 (because it is a list)

16:13 ,(boolean '(= 1 2))

16:13 clojurebot: true

16:13 * gfredericks tends to go on and on about macros

16:16 bawr: gfredericks: it's only appropriate :)

16:17 gfredericks: https://twitter.com/gfredericks_/status/283581072237789185

16:17 Seba51: I found out, that the smiley (caused by ( = was actually code, but give me a moment to understand

16:17 gfredericks: oh dear smileys

16:17 Anderkent: (=

16:17 gfredericks: I bet that means my counterexample from earlier got missed

16:18 Seba51: yep

16:18 ;-)

16:18 gfredericks: it was (unless ( = 1 2) 42)

16:18 Seba51: I assumed that you were in happy mood while typing ;-)

16:18 * gfredericks wonders what the 42) emoticon represents

16:19 bawr: Seba51: but erh, yeah, what you want to take away from this is that macros are really supposed to emit code. ;P

16:19 :>

16:19 Seba51: I got it

16:19 gfredericks: bawr: are you trying to condense my ramblings to a helpfully digestable size?

16:20 bawr: gfredericks: I'm distilling them, I guess.

16:20 Seba51: Thanks a lot

16:20 bawr: But that's some good rambling, 10/10 would distill again.

16:20 gfredericks: lerlz

16:22 Anderkent: style question: how do I do nested map/reduce right? example http://pastebin.com/QQdLiv5Z

16:22 jonasen: kovas: thanks for the merge. I might be able to pull of #20 also. Codeq only checks if some known schema attribute is already in the db and otherwise it transacts the schema. Is this what you had in mind?

16:23 kovas: jonasen: i thought it did something more sophisticated with annotating the transaction.. lemme take a look

16:25 gfredericks: Anderkent: besides breaking something out into a separate function, I can't think of a simpler way to do that

16:26 Raynes: http://dl.dropbox.com/u/23745600/Screenshots/6uOy.png

16:26 Wrong window.

16:30 kovas: jonasen: you're right, it does something very simple for the base codeq schema. I thought I saw something for the analyzer-specific schemas, which also need to be transacted

16:31 bbloom: let me try my question again.... is there any way to turn (:require [clojure.zip :as zip] [bbloom.zip-util :as zipx]) into some similar to this magic fake syntax (:require [(clojure.zip bbloom.zip-util) :as zip])

16:31 or even better, do that on the supply side: inside the zip-util namespace

16:31 somewhat similar to how python provides __ALL__ that you can fill in

16:31 jonasen: kovas: The analyzers supports schema revisions and when you run codeq it figures out which versions has been transacted

16:32 kovas: jonasen: in any case, i think my plan was to just copy exactly what codeq did in terms of those conventions

16:32 yogthos: maybe you could make a macro which makes a new namespace that uses both and then require it as whatever?

16:32 Anderkent: bbloom: I don't think your magic fake syntax would do what it does (can't have both of them required for one name, can you?)

16:33 yogthos: oh nm it won't be exposed that way

16:33 it's too bad you can't cascade dependencies

16:33 Anderkent: I'm not sure what we're trying to do - have one zip namespace with all the functions in it?

16:33 Raynes: bbloom: I'd probably hate you if you did that.

16:34 bbloom: yogthos: yeah, you'd need the macro to expand to a bunch of def forms, which is totally doable

16:34 Anderkent: basically

16:34 Raynes: why? i have a dozen or so zipper functions that i always use

16:34 i keep forgetting which are in zip and which are in zip-utils :-P

16:34 it's driving me nuts

16:34 Anderkent: bbloom: how about doing magic in zip-util that reexposes all zip vars under its own ns?

16:34 Raynes: bbloom: The problem is how does the person reading your code know where things come from?

16:34 Which namespace?

16:35 Anyways, if it is ridiculous namespace magic, it's probably in potemkin somewhere.

16:35 $google clojure potemkin

16:35 lazybot: [ztellman/potemkin · GitHub] https://github.com/ztellman/potemkin

16:35 amalloy: yes, potemkin contains exactly the magic bbloom wants to make his code easy to write and hard to read

16:35 Raynes: amalloy: o/

16:35 * Raynes dons sunglasses.

16:36 bbloom: heh: https://github.com/ztellman/potemkin/blob/master/src/potemkin/namespace.clj

16:36 kovas: jonasen: ok. I guess its not a big functionality improvement to change that then, other than to maybe rename the functions i have

16:36 Anderkent: import-fn seems like the thing bbloom wants to do

16:36 kovas: jonasen: I'm also gonna open some tickets on codeq and lein that might be interesting for you

16:36 :)

16:36 bbloom: Raynes & amalloy: you really thing it would be bad to have at the top of zip-util a big list of things that are copied from clojure.zip ? doesn't seem like it would make reading it that hard

16:36 jonasen: kovas: except that you'll be able to run the free transactor

16:37 Anderkent: bbloom: that's okay, as for the user they all seem to come from zip-util

16:37 bbloom: you are in myapp.core and you navigate to zip-util and see that zipper is defined as clojure.zip/zipper

16:37 Anderkent: the bad case is where you would have the two namespaces somehow merged in the user ns

16:37 bbloom: yeah, Anderkent i agree

16:37 jonasen: kovas: right now it'll try to transact the schema every time

16:38 Raynes: bbloom: In my experience, it a) makes it difficult to find where vars originate for people reading the code b) makes error messages have ridiculous stacktraces because you're trying to change where something is c) is not worth it.

16:38 kovas: jonasen: not optimal

16:39 amalloy: bbloom: i suggest you read through the source of gloss, trying to track down the original definition point of a few functions randomly chosen while reading the source. if you don't have trouble with that, your users won't have trouble with your zip-util thing

16:39 and, you might not. potemkin drives me nuts, but beyond what is rational really

16:40 Raynes: And I think amalloy and I share generally exactly the same opinion on potemkin.

16:41 kovas: jonasen: I've run the free transactor with session, seems to work OK

16:42 jonasen: kovas: sorry, I misread your code. You do check for a schema attribute in connect-database

16:42 kovas: jonasen: ok, I think I had both at one point.. forgetting my own code :)

16:42 mpenet: flatland.useful.ns/alias-ns feels better, it's a good tradeoff between potemkin import-fn and tons of require declarations, as long as you don't abuse that stuff

16:43 bbloom: Raynes & amalloy: i dunno, doesn't seem *too evil* to me.... although it breaks down when you have bbloom.zip-util and amalloy.zip-util

16:43 amalloy: ugh, alias-ns is worse

16:43 mpenet: oh ?

16:43 Raynes: bbloom: Look at what it takes to make this crap happen.

16:43 It might turn you off of it.

16:43 amalloy: it makes it actually-impossible to track down where a function came from

16:44 bbloom: Raynes: i looked at it. it's an ugly copy paste of metadata

16:44 amalloy: i forget the syntax, but: (alias-ns useful.seq) (alias-ns useful.map) (map-vals m f) ;; where does map-vals come from?

16:47 bbloom: i agree with you guys that all of these solutions leave something to be desired, but i think that there is a legitimate use case for composing namespaces....

16:47 do you have a better proposal?

16:48 kovas: jonasen: I'm gonna take off for a while, will be on IRC later

16:48 (hopefully)

16:52 bbloom: there are two use cases: 1) organize the backing code for some public api into multiple files, but preserve one namespace

16:52 and 2) alias names locally in a union/merge fashion

16:53 the former falls down when you want to extend somebody else's namespace

16:53 the latter is slightly more effort

16:53 i guess i'll just deal with zip and zipx for now

16:53 but i don't have to like it :-P

16:54 Raynes: bbloom: I guess we wont change your mind. I'm just expressing my own hatred for potemkin, because I personally have had a lot of trouble with libraries that use it.

16:54 bbloom: Raynes: and i'm going to trust you on that, but i'm saying that the shortcomings are probably implementation failings, not something inherent

16:54 ie the stacktraces suck

16:55 or something similar

16:55 no?

16:55 clojurebot: no is tufflax: there was a question somewhere in there, the answer

16:55 amalloy: Raynes: it sounds like you did just change his mind

16:58 Raynes: bbloom: I really don't like the goal, even with a perfect implementation. I prefer knowing exactly where things come from. It's a similar problem to :use

16:58 Anderkent: Raynes: with a good implementation you'll know where stuff came from anyway, it's one extra find-def press more...

16:59 Raynes: Look

16:59 I'm right. You're wrong. Just let it go.

16:59 :P

16:59 Anderkent: I don't really care if something comes from my.project.internal.maths.discrete most of the time, I just want it under my.project.core

17:00 Raynes: It's easier if you guys stop having conflicting opinions!

17:00 bbloom: Raynes: you're only right because i have bigger fish to fry :-P like making this damn library work at all

17:00 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

17:01 bbloom: Raynes: also, i think that many of the problems with it are due to some rough ugly spots in clojure's var/symbol/etc handling

17:01 Raynes: the biggest issue is: when do top level forms run inside a file? at compile time or at runtime? on the jvm, there isn't a difference really, but it's a big issue for clojurescript

17:02 consider (when false (def x 1))

17:02 obviously a stupid edge case

17:02 but illustrates the issue

17:02 gfredericks: on cljs that happens at code-load-time, right?

17:03 bbloom: gfredericks: in cljs x would be defined unconditionally

17:03 gfredericks: if(false){_.x = 1}

17:03 wat

17:03 bbloom: wat indeed.

17:03 gfredericks: just because that's how def is handled?

17:03 bbloom: yeah

17:03 gfredericks: sweet

17:05 technomancy: I think nstools addresses most of the problems immigrate is designed to handle, but in a much more elegant way

17:06 bbloom: gfredericks: notice how parsing 'def unconfiditionally modifies the current namespace: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj#L324

17:06 technomancy: what's your opinion on the namespace discussion?

17:07 gfredericks: bbloom: I notice!

17:08 bbloom: gfredericks: it makes me sad, but to fix it, you'd need to have a -main function or something

17:08 gfredericks: bbloom: because gclosure doesn't like top-level code?

17:08 bbloom: gfredericks: no, b/c the top level of clojure complects run and compile time

17:09 gfredericks: it's too bad that clojure.core isn't divided up into clojure.core and clojure.compiler or something like that

17:09 gfredericks: so we could do it but we don't want to?

17:09 bbloom: gfredericks: it would be a pretty big breaking change, so not gonna happen

17:10 gfredericks: what would it break? people who rely on (if false (def something))?

17:10 * gfredericks feels like he is missing a detail

17:10 bbloom: gfredericks: it would break any side-effectual code at the top level of a module

17:11 the issue is that the environments are different. consider the *warn-on-reflection* var, which is often set! to true

17:11 that var doesn't exist/matter outside the compiler at runtime

17:12 gfredericks: we're talking about fixing (if false (def something)), right?

17:12 technomancy: bbloom: I don't like immigrate. I agree that it can be awkward sometimes, but I think nstools takes care of the awkwardness in a much more straightforward way.

17:13 bbloom: technomancy: are you referring to http://code.google.com/p/clj-nstools/ ?

17:13 technomancy: yeah

17:13 Raynes: google code

17:13 evil one

17:13 technomancy: maybe it's worse if you use a lot of protocols, but the solution to that is easy: use fewer protocols

17:13 Raynes: well the project dates from the days that Clojure was on Google Code

17:13 so they get a pass

17:14 bbloom: i use damn near zero protocols :-P

17:14 Raynes: technomancy: I fixeded the bug in laser and I've got a decent test suite that passes. Once I get refheap mostly moved to it, I'll be announcing it on a wider scale.

17:14 I'll overthrow the Enlive militia if it kills me.

17:14 technomancy: Raynes: cool. if I find myself needing HTML at some point in the future I'll give it a look.

17:15 Raynes: o/

17:15 technomancy: \o

17:15 Raynes: technomancy: So, after last night I might be moving refheap back to my VPS when I get a bit of time. Don't hate me if I do. :(

17:15 I know it isn't all Heroku's fault, but man, 10+ hour downtime...

17:16 technomancy: yeah, can't blame you

17:16 amalloy: those poor folks who wanted to wrap up a paste for their children...

17:16 technomancy: I don't imagine refheap would be much administrative overhead on a VPS anyway

17:17 Raynes: amalloy: It was truly heartbreaking.

17:17 technomancy: I moved to Heroku just because of how prone pastebins are to DDOS attacks.

17:17 I don't know how to handle that crap.

17:17 I could of pastebins have shut down over it.

17:18 amalloy: Raynes: actually i found a christmas present on refheap: https://www.refheap.com/paste/7851

17:18 Anderkent: that last sentence didn't parse

17:18 clojurebot: the previous sentence is false

17:18 Raynes: amalloy: o/

17:20 silasdavis: how can I require an java module from a local jar file

17:20 I have tried copying it to lib

17:20 gfredericks: lein doesn't like that

17:20 lein really wants that jar to be in a maven repo

17:21 silasdavis: ah

17:21 I'll do that then

17:22 how do wildcard requires? zephyr.android.HxMBT.*

17:23 gfredericks: you can't. (:import [zephyr.android.HxMBT OneClass AnotherClass OneMoarClass ...])

17:23 Tolstoy: Trying to get the lein-cljsbuild working, but keep seeing this in by browser log: TypeError: 'null' is not an object (evaluating 'parentElm.appendChild'). Anyone know what's up with that?

17:24 Otherwise, the clojurescript stuff works.

17:28 Maybe the instructions have left out a critical assumption. I'm assuming you can do this via an index.html page (as per the ClojureScript wiki doc).

17:29 Anderkent: Can I use memoize to speed up a self-recursive function? How do I refer to the memoized version?

17:31 technomancy: Anderkent: memoization would require stack-consuming recursion; `recur` skips it

17:31 Anderkent: technomancy: not tail recursive I'm afraid

17:31 gfredericks: Anderkent: alter-var-root should work

17:31 bbloom: wouldn't (def f (memoize (fn [x] ... (f y))) be fine?

17:32 gfredericks: bbloom: that too

17:32 technomancy: sure

17:32 gfredericks: wait does it?

17:32 I guess so.

17:33 Anderkent: thanks, that does it

17:33 gfredericks: but we need to use alter-var-root more for technomancy's sake

17:33 technomancy: so I can yell at you more?

17:33 gfredericks: it's what I wake up for

17:34 Anderkent: it's how you wake up

17:34 :)

17:34 technomancy: but I'm fine with non-runtime use of it

17:34 * gfredericks writes up a web app that alters-var-root on each request

17:34 technomancy: ~gourds

17:34 clojurebot: SQUEEZE HIM!

17:35 * gfredericks leaks

17:39 zilti: I'll never understand how clojurebot decides when to come up with a random-yet-fitting phrase. There must be a human locked up in that bot's JVM.

18:21 Rich_Morin: In "(fn foo [] ...)", is foo only used to allow recursion?

18:21 danlarkin: sometimes also to allow for easier-to-read stacktraces

18:22 Rich_Morin: point; tnx

18:22 yogthos: it's also what defn does under the covers

18:22 bbloom: Rich_Morin: to clarify, it's very different from (let [foo (fn [] ...

18:22 yogthos: (macroexpand '(defn foo [])) => (def foo (clojure.core/fn ([])))

18:23 lol not quite I guess :)

18:23 should've read it first lol

18:23 Rich_Morin: tnx all!

18:24 bawr: (macroexpand '(defn foo [x y] x))

18:24 zilti: bbloom: In what is it that different from (let [foo (fn ?

18:24 bawr: &(macroexpand '(defn foo [x y] x))

18:24 lazybot: ⇒ (def foo (clojure.core/fn ([x y] x)))

18:24 yogthos: oh nice

18:24 bbloom: zilti: the let establishes a binding available to all future bindings and to the body of the let. where as (fn foo ...) establishes a binding only available inside the fn

18:25 bawr: bbloom: what do you mean "to all future bindings"?

18:25 yogthos: I guess if you rebind it later inside the let?

18:25 bbloom: ,(let [f (fn [x] x) g f] (g 1))

18:25 clojurebot: 1

18:26 bbloom: ,(let [z (fn f [x] x) g f] (g 1))

18:26 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: f in this context, compiling:(NO_SOURCE_PATH:0)>

18:26 bbloom: i mean later bindings in the same let

18:26 bawr: Aah.

18:26 I see.

18:26 bbloom: lets occur in series

18:26 yogthos: &(let [x 1] (let [x (inc x)] (println x)))

18:26 lazybot: ⇒ 2 nil

18:26 yogthos: is that what you meant?

18:28 bbloom: what i mean is that let bindings occur in series, such that each pair is available in the lexical context of the initialization expression, or if the last binding, in the body of the let

18:28 yogthos: ah ok

18:29 like let* in cl

18:29 bbloom: yogthos: right

18:29 if you need parallel let, like in cl, you can use letfn

18:29 which allows for mutually recursive definitions

18:30 yogthos: ah I haven't considered that

18:30 zilti: By parallel let do you mean being able to call functions defined later in the letfn?

18:30 yogthos: I always took clojure style let for granted

18:30 bbloom: zilti: in a letfn, all bindings occur simultaneously and are available in each other's lexical scopes

18:31 zilti: bbloom: Good to know, didn't know that.

18:31 bbloom: yeah, it's very intentional: you only need parallel bindings for mutual recursion. mutual recursion doesn't make sense in data structures, only with delayed evaluation, like in the case of functions: hence letfn

18:32 doesn't make sense in PERSISTENT/IMMUTABLE data structures, i mean

18:32 yogthos: today I learned :P

18:32 I wondered about letfn before, this makes perfect sense though

18:33 bbloom: in CL, where most of the data structures are mutable, it makes some sense to be able to have mutually recursive pointers occuring. the bindings are established in parallel, but the init expressions are evaluated in series

18:33 zilti: I always thought it to be a "convenience function" but never figured why that very slight gain in characters would justify it :)

18:33 yogthos: ditto

18:33 as always it turns out there's a deeper meaning there

18:36 gfredericks: (doc letfn*)

18:36 clojurebot: Excuse me?

18:36 gfredericks: ,(doc letfn*)

18:36 clojurebot: Huh?

18:36 bbloom: no *

18:36 (doc letfn)

18:36 clojurebot: "([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body."

18:36 zilti: ,(doc letfn)

18:36 clojurebot: "([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body."

18:36 gfredericks: bbloom: letfn* is the special form I think

18:37 ,(macroexpand '(letfn [(a [] 2)] 42))

18:37 clojurebot: (letfn* [a (clojure.core/fn a [] 2)] 42)

18:37 zilti: Does that * have a special meaning in Clojure/Lisp? I noticed it being used for the composable variants of functions in sqlkorma and Lamina.

18:37 bbloom: gfredericks: the true underlying special forms are an implementation detail :-)

18:37 gfredericks: zilti: it gets used to mean several different things

18:37 bbloom: zilti: x* just means "like x but slightly different"

18:38 similar to x' which means "a new value of x"

18:38 * zilti buries a theory

18:38 bbloom: and *x* means "x is a dynamic var"

18:38 but these are just conventions, not enforced

18:38 gfredericks: bbloom: I thought doc responded to special forms though

18:38 ,(doc var)

18:38 clojurebot: Huh?

18:38 gfredericks: &(doc var)

18:38 lazybot: ⇒ ------------------------- var (var symbol) Special Form The symbol must resolve to a var, and the Var object itself (not its value) is returned. The reader macro #'x expands to (var x). Please see http://clojure.org/special_forms#var nil

18:39 gfredericks: &(doc letfn*)

18:39 lazybot: ⇒ nil

18:39 gfredericks: hrm

18:40 bbloom: gfredericks: it's a hardcoded hack: https://github.com/clojure/clojure/blob/master/src/clj/clojure/repl.clj#L18

18:43 tpope: bbloom: I have a proof of concept stacktrace parser. I'm struggling with how to reliably get my hands on the stack trace

18:43 zilti: Hell, we have 2012 and copying files does not ensure them being consistent

18:43 bbloom: tpope: do you ever make anything for clients/employers/etc? or do you just only make awesome stuff for those of us who stalk your github profile?

18:44 yogthos: haha

18:44 tpope: bbloom: I make vim plugins till I'm broke, then take the first shitty rails contract I can get my hands on :/

18:44 yogthos: my trick is to make a project first and then use it at work :P

18:45 tpope: with any luck I'll be able to change that to "first shitty clojure contract" soon enough

18:45 bbloom: tpope: enjoying clojure?

18:45 tpope: so far so good

18:45 bbloom: cool

18:45 tpope: sometimes I feel it's like 5 times too smart for me

18:46 bbloom: ok well what's the stack trace issue? my stack trace skills are weak, but i might be able to provide some insight

18:46 Raynes: I'm of the opinion that if you can do vimscript, you're smart enough for Clojure

18:46 bbloom: tpope: nah, you just need to unlearn so many things you take for granted. it's just different

18:46 yogthos: it is for sure

18:46 but it's really self consistent which helps a lot

18:46 tpope: bbloom: I want to make it so that if evaling something gives an error, the stack trace is prepopulated into the location list

18:46 yogthos: you learn one concept and you can just apply it everywhere :)

18:47 tpope: makes sense, right?

18:48 Raynes: I remain optimistic

18:48 bbloom: biggest challenge. how do I get the stack trace out of nrepl?

18:49 I can eval (.getStackTrace *e), but then I've stepped on *1, etc

18:50 Raynes: tpope: (def temp *1) (.getStackTrace *e) (def *1 temp)

18:50 bbloom: Raynes: that would modify *2 and *3 :-P

18:50 tpope: yeah

18:50 Raynes: Fix them all.

18:50 Rawr.

18:50 tpope: plus now I've dumped a temp var in the user's repl

18:50 bbloom: tpope: probably should ask cemerick, since *e etc are repl features

18:50 not evaluator features

18:51 Raynes: tpope: That's what gensyms are for.

18:51 tpope: I could gensym it or something, but this is starting to get hairy

18:51 Raynes: Hacks are hack.

18:51 bbloom: nrepl provides multiple different commands other than "eval" right?

18:51 tpope: yes

18:51 I haven't exhaustively searched them

18:51 bbloom: is there a "get-var" command?

18:52 tpope: I guess I should

18:53 bbloom: https://github.com/clojure/tools.nrepl/blob/master/doc/ops.md

18:53 tpope: yeah just remembered where it was

18:53 I don't see anything

18:54 bbloom: tpope: you could clone the session and then eval whateve ryou want

18:54 tpope: ooh, cloning might work

18:54 bbloom: clone, eval, close

18:54 tpope: convoluted, but cleaner

18:54 bbloom: mmm immutability :-)

18:54 cheap clones

18:54 no idea what *actually* happens when cloning

18:55 but i assume clone works

18:55 yogthos: presumably just a reference ;)

18:55 and then it modifies its own tree from there right

18:55 bbloom: yogthos: right, my concern would be what happens with :stdin and :stdout

18:55 yogthos: mmm good point

18:58 bbloom: hmmm tpope, actually clone may not help

18:58 ,#'*1

18:58 clojurebot: #'clojure.core/*1

18:58 tpope: what are the odds on that may?

18:58 bbloom: they *might* be dynamically rebound, such that each session gets their own

18:59 but otherwise they are global mutable cells, rather than session data

18:59 which seems odd, i'd assume nrepl needs to support multiple different *1

18:59 so i'd say it has like an 85% chance of working :-)

18:59 tpope: I estimate a half hour of bumbling around just to try it :/

18:59 bbloom: ,(:dynamic (meta #'*1))

18:59 clojurebot: true

19:00 bbloom: ok, 92% chance of success

19:00 :-)

19:03 tpope: cool, foreplay shits itself on the nrepl source

19:04 bbloom: mmm metacircular

19:44 tpope: bbloom: doesn't work

19:44 bbloom: sad day :-(

19:44 why not?

19:44 tpope: bbloom: also found https://github.com/clojure/tools.nrepl/blob/9b1fc6807cf87ad487887b1701abd1462028f635/src/test/clojure/clojure/tools/nrepl/sanity_test.clj#L113-134 :(

19:45 *e is nil in the cloned session

19:45 bbloom: tpope: seems like a bug

19:46 tpope: I suppose I could open an issue. A nice little xmas gift for cemerick

19:46 bbloom: tpope: tools.nrepl is tracked w/ jira

19:46 tpope: oh boy!

19:46 bbloom: dev.clojure.org

19:47 i think you need a signed contributor agreement to open an issue there

19:47 might be best to just email him :-P

19:47 tpope: I'll grab him in the channel sometime

19:47 bbloom: k

19:54 hyPiRion: bbloom tpope: No need to sign a CA for issue reporting

19:54 bbloom: ah ok thanks hyPiRion

19:54 tpope: cheers

19:54 hyPiRion: Just create an account there, and describe the issue :)

19:54 bbloom: hyPiRion: but you still do need to deal with jira :-P

19:55 tpope: this is less an issue and more a question anyways

19:55 hyPiRion: Ah

19:57 ravster: hello everyone

19:57 hyPiRion: hey

20:11 zilti: Here's my first "production-ready" micro-library: https://github.com/zilti/cynomys

20:28 mindbender1: library authors, is there a significant perf diff in using sth

20:28 like (foo {:bar ["baz"]}) as opposed to (foo :bar ["baz"])

20:29 yogthos: depends on how you use it I find

20:29 if you want to pass in some parameters I'd use it the second way

20:30 mindbender1: yogthos: so what has been your finding cos I see a pervasice use of (foo :bar ["baz"]) among many clojure authors

20:30 whereas I expect idiomatic usage of (foo {:bar ["baz"])

20:30 yogthos: well for example in my markdown-clj lib I do this for allowing specifying a code style tag (md-to-html "```code```" :code-style #(str "class=\"" % "\"")))

20:31 if it's something that specifies the environment options for example

20:31 I find people tend to use the :flag foo notation

20:31 Raynes: Bahahaha

20:32 yogthos: I forgot that you're the dude who did markdown-clj.

20:32 yogthos: :P

20:33 Raynes: So now I have to explain myself.

20:33 yogthos: hehe

20:33 lol you opened a couple of bugs on it too :)

20:34 Raynes: yogthos: So, I complained about you using markdown-clj in lib-luminus.

20:34 yogthos: yeah you said you use pegdown for refheap right?

20:35 Raynes: yogthos: The primary reason why is because pegdown is just so great. It supports a whole bunch of extensions. It isn't that markdown-clj is bad as much as pegdown does more and is concisely used from Clojure. I'm not even sure it'd be worth writing a wrapper library for it, but it might be because extensions are calculated using bit-or which might confuse Clojure people not coming from Java.

20:36 Is there a big reason for markdown-clj? Some reason pegdown wasn't sufficient?

20:36 yogthos: main motivation was to make something that runs both in clojure and clojurescript :)

20:36 for example in my blog I want to preview posts/comments

20:36 and if you have a different js implementation of markdown it's not guaranteed to look the same when the server renders it

20:37 but yeah it's not nearly as featureful as pegdown

20:37 Raynes: That makes sense.

20:37 yogthos: thanks :)

20:37 lol originally I did it for lulz

20:38 mindbender1: yogthos: what would have been the difficulty if you have chosen the other implementation because that is stillgoing against Rich Hickey's I don't know I don't want to know

20:38 yogthos: I read a post from Brian Carper about how he used a rhyno to run js interpreter for his blog to make sure md rendered the same

20:38 Raynes: yogthos: Anyways, I just wanted to explain my reasoning, since I was pretty mean about it yesterday.

20:38 yogthos: so I was like can't be that bad to parse md, turns out it's not trivial to do it right :P

20:39 no prob dude, I'm actually surprised it got as popular as it did

20:39 all of a sudden people started starring it on ghub and I was like ok I guess I should fix it up so it's not completely lame :P

20:39 mindbender1: Same question goes to others

20:40 all these is still not heloing with the order problem

20:40 helping

20:40 Raynes: yogthos: I think I'll throw together a little wrapper library for pegdown.

20:40 yogthos: yeah that'd be cool

20:40 Raynes: And perhaps use that in lib-noir, adding an optional extensions arg to md->html

20:40 yogthos: pegdown is pretty slick for sure

20:41 that'd be nice, I moved the function to the template for now btw

20:41 Raynes: Well that'd be fine too.

20:41 yogthos: but yeah I was thinking about it

20:41 I think it'd be best to keep libs in lib-noir and config in the template

20:42 this way it makes updating libraries easier

20:42 Raynes: A pegdown wrapper would still be useful though. I had an issue with it and numbers a while back that I had to fix by explicitly wrapping something in (int ..) but most people would just give up and not use pegdown, thinking it broken.

20:42 yogthos: if too much stuff gets into template, then people are gonna have a hell of a time upgrading their apps

20:42 Raynes: So I'll still do that either way.

20:42 yogthos: yeah let's get a pegdown wrapper in lib-noir and I'll move md->html back there after :)

20:43 ibdknox: a pegdown wrapper should be its own lib

20:43 Raynes: ibdknox: Duh.

20:43 yogthos: right yeah, we include the lib in lib-noir :)

20:43 Raynes: ibdknox: Always planned for a separate library.

20:43 ibdknox: yogthos: in terms of using md in cljs, I just use some the JS markdown things

20:43 righto

20:43 Raynes: ibdknox: Go back to light table and leave the lib-noring to me.

20:44 :P

20:44 ibdknox: (totally kidding)

20:44 ibdknox: lol

20:44 yogthos: hehe

20:44 ibdknox: see.. Raynes is mean.

20:44 Raynes: ibdknox: His reasoning for having a lib that works in both places is so that markdown renders the same.

20:44 The problem is that markdown sucks because it doesn't have a standard that everyone follows.

20:44 ibdknox: ah

20:44 Raynes: Otherwise this wouldn't be a problem.

20:44 ibdknox: indeed

20:44 yogthos: the whole thing stemmed from this http://briancarper.net/blog/415/clojure-and-markdown-and-javascript-and-java-and

20:45 that's the beauty of md it's such a loose "standard" :)

20:45 every implementation does it a bit different

20:45 ibdknox: well maybe Jeff Atwood 's quest will succeed

20:45 yogthos: haha

20:45 Raynes: You see beauty in strange things, sir.

20:45 ibdknox: It would be nice if it did

20:46 yogthos: mindbender1: what was the question btw?

20:46 Raynes: It sure would.

20:46 yogthos: the worst thing about md is that it has redundant syntax for no apparent reason, like stwo eparate heading declarations

20:47 ibdknox: yeah

20:47 yogthos: and list behavior is largely undefined

20:47 what can go inside lists, how the spacing works, etc

20:47 ibdknox: I love doing things with GFM though

20:47 yogthos: btw could also link this in lib-noir :) https://github.com/yogthos/clj-pdf

20:48 I was looking through django features

20:48 and they have a pdf renderer

20:48 can be nice for some stuff like reporting

20:49 ibdknox: I wonder if it just makes sense to point to these sorts of things in some canonical up-to-date place on webnoir

20:49 that's largely the problem

20:49 it's impossible to find this stuff

20:49 yogthos: yeah I know

20:49 actually I heard from clojars guys that they plan to add number of downloads stats for libs

20:49 that would help a lot

20:49 ibdknox: yes it would

20:49 yogthos: cause then you can see which libs people are using and what the health status is

20:50 maybe could also show the frequency of updates

20:50 and then you could sort by that :P

20:50 I really think this has to be some automated feature not people aggregating libs by hand on some site

20:50 that's just not sustainable

20:50 bbloom: yogthos: i wish github would bring back traffic stats too!

20:50 ibdknox: bbloom: me too

20:50 yogthos: yeah I know!

20:51 bbloom: the one down side to the automated approach is that it benefits incumbents

20:51 yogthos: but yeah seing how lein is the pretty much defacto standard it makes sense to track it through clojars

20:52 true, but you could have different filters too, like activity

20:52 new libs will have more activity than mature ones for example

20:52 and it could give a combined weighted score too when sorting

20:53 bbloom: yogthos: i'd want to sort by the first differential of the number of new projects depending on that lib :-)

20:53 ie show me what people are switching to

20:53 yogthos: that's a good idea

20:55 mindbender1: yogthos: I'm just saying work hard to hide implementation details

20:56 yogthos: yeah that I definitely agree with

20:56 what's the context though?

20:57 mindbender1: It's just that when I see that form of order I ask myself why couldn't amap work here

20:59 yogthos: ah

20:59 mindbender1: like they say eventual consistency is hard for programmers

21:00 yogthos: I don't think it's that bad in this particular context though, optional flags come at the end is not a bad convention

21:00 mindbender1: those can work in maps too

21:00 yogthos: and it does make it a bit more readable I find, but admittedly not that much

21:00 mindbender1: they are very open

21:01 it allows your code to work in a threaded program

21:02 yogthos: I think it does mostly come down to aesthetics

21:02 and realistically, you still have to read the docs to know what to pass in

21:02 so it's not that using a map is going to make that any better

21:03 mindbender1: but then you remove the order

21:03 and save users the headache of syntac

21:03 syntax

21:03 yogthos: true, but I think the headache is mostly perceived in this case no?

21:04 mindbender1: when it builds up with other programs

21:05 yogthos: can you give an example of what you mean?

21:05 mindbender1: when I think of your syntax with a gazillion other syntax I have to think about

21:06 yogthos: but there's not much syntax in clojure to being with to be fair

21:06 I keenly feel that point when working with scala for example

21:06 every 5 min or so I end up googling how to do this or that correctly

21:06 mindbender1: actually I was reading pallet before I came here to whine

21:06 yogthos: hehe

21:07 mindbender1: so? clojure authors seem to want to make sure it arrives

21:08 Actully I don't even know why project.clj adopted a similar syntax

21:09 maybe we should stop using maps

21:09 yogthos: well you kind of need actual maps in most cases

21:10 thing that bothers me more is the cons/conj behavior :)

21:10 mindbender1: have you listened to stu's data oriented programming

21:11 yogthos: yup

21:11 mindbender1: I think he shared some luv there

21:24 gfredericks: it disappoints me sometimes that clojure maps aren't Comparable

21:24 is no comparator better than an arbitrary one?

21:25 I always enjoyed erlang's built-in total-ordering-over-all-types

21:25 I guess there could be no efficient ordering

21:26 erlang doesn't have maps :)

21:26 hyPiRion: how would you compare them?

21:26 yogthos: well you could check how many keys match?

21:26 but that's definitely expensive

21:27 gfredericks: ignoring the efficiency question, it could be anything.

21:27 hyPiRion: Well then, what's the value of sorting them?

21:27 yogthos: so the more keys match the closer they are to each other, there's definitely situations where that can be useful

21:27 any sort of fuzzy logic

21:27 gfredericks: hyPiRion: I'm often interested in canonical representatives in sets of maps that aren't in a particular order

21:28 e.g., from a db query

21:28 yogthos: that's actually a good example, say you have users in db and you want to find duplicates

21:28 gfredericks: yogthos: first compare (sort (keys m1)) with (sort (keys m2)), then if those are equal do the same with the values; that depends on both keys and values being comparable though

21:29 yogthos: yeah it's not hard to implement ;)

21:29 bbloom: i think the fact that it's not obvious how to compare them implies that, yes, no comparer is better than an arbitrary one

21:29 gfredericks: but I imagine that a vector's comparability depends on its entries as well

21:29 ,(sort [[] [2] [4]])

21:29 clojurebot: ([] [2] [4])

21:29 gfredericks: ,(sort [[] [{2 2}] [{}]])

21:29 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Comparable>

21:29 gfredericks: yep

21:30 bbloom: well if it were obvious how to compare them then there'd be no reason to suggest an arbitrary one; my point was that an arbitrary ordering can have utility, even if it's an inscrutible black box

21:31 yogthos: I suspect that could lead to some hard to track down errors too though

21:31 hyPiRion: It's more evident to write, say

21:31 ,(sort-by count [{} {:a 4} {:a :b :c :d}])

21:31 clojurebot: ({} {:a 4} {:a :b, :c :d})

21:31 hyPiRion: than just sort.

21:32 I guess that's why, mostly.

21:32 gfredericks: hyPiRion: certainly in situations where you care how it's sorted, yes

21:33 oh wait wouldn't c.c/hash allow a usually-efficient ordering?

21:33 hyPiRion: gfredericks: I was just thinking about that

21:34 It's consistent, as long you don't have mutables within the maps

21:34 gfredericks: which is lame to begin with

21:34 hyPiRion: AND it's totally ordered, sans collisions.

21:34 gfredericks: on collisions you just do some difficult slow thing

21:35 hyPiRion: another hashing

21:35 with different algorithm

21:35 gfredericks: or just compare (sort m1) with (sort m2)

21:36 haha would that be (sort-by sort my-maps)? :D

21:36 ,(sort-by sort [{:a 12} {:b 17 :c 15} {} {:a 12}])

21:36 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to java.lang.Comparable>

21:36 hyPiRion: nope, more like..

21:37 gfredericks: consarnit

21:37 ,(sort-by (comp vec sort) [{:a 12} {:b 17 :c 15} {} {:a 12}])

21:37 clojurebot: ({} {:a 12} {:a 12} {:c 15, :b 17})

21:37 gfredericks: there it goes

21:37 hyPiRion: Gosh darnit, I need two maps with the same hash to test it out

21:38 ,(sort-by (comp vec sort) [{:a 12} {:b 17 :c 15} {} {1 12}])

21:38 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Keyword>

21:38 gfredericks: oh the hashing does give you more flexibility about types doesn't it

21:38 hyPiRion: ,(mapv hash [{:a 0} {:a nil}])

21:38 clojurebot: [1013910569 1013910569]

21:38 hyPiRion: right.

21:39 gfredericks: (def other-hash (comp hash pr-str))

21:39 hyPiRion: Blugh, hahah.

21:39 ,(sort-by (comp hash pr-str) [{:a 12} {:b 17 :c 15} {} {1 12}])

21:39 clojurebot: ({:a 12} {1 12} {} {:c 15, :b 17})

21:40 hyPiRion: Actually, god damnit

21:40 ,(sort-by pr-str [{:a 12} {:b 17 :c 15} {} {1 12}])

21:40 clojurebot: ({1 12} {:a 12} {:c 15, :b 17} {})

21:40 gfredericks: lerlz

21:40 hyPiRion: That's totally ordered, too.

21:41 ,(sort-by pr-str [{2 12} {:b 17 :c 15} {1 13} {1 12}])

21:41 clojurebot: ({1 12} {1 13} {2 12} {:c 15, :b 17})

21:41 gfredericks: unless you want it to distinguish between types that print the same

21:41 hyPiRion: Well, if you're that guy, then fuck you.

21:41 gfredericks: yeah fuck him

21:41 hyPiRion: Because this is good enough

21:41 gfredericks: alright go commit it to core so we can make it into 1.5

21:42 we've hammock'd enough

21:42 hyPiRion: Yeah, rhickey would surely add this in

21:42 yogthos: rofl

21:42 hyPiRion: Foolproof.

21:43 gfredericks: it doesn't have the erlang elegance where the ordering of X and Y where X and Y are different types is dependent only on the types

21:43 I think couchdb does that too

21:43 hyPiRion: I'm working on a patch now

21:43 gfredericks: it helps to have a closed set of types

21:44 if we get into class names then we'll conflict with clojure's multiple-classes-per-datastructure approach

21:46 bbloom: there is no mutually exclusive list of protocols, which is on purpose

21:46 you can have a map that is also a vector, if you really wanted to

21:46 in fact, vectors already are maps....

21:46 gfredericks: sorta?

21:46 ,(map? [3 4])

21:46 clojurebot: false

21:46 gfredericks: so not in every sense at least

21:46 hyPiRion: Vectors aren't maps

21:47 bbloom: (doc map)

21:47 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

21:47 bbloom: (doc map?)

21:47 clojurebot: "([x]); Return true if x implements IPersistentMap"

21:47 bbloom: ,(instance? IAssoc [3 4])

21:47 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: IAssoc in this context, compiling:(NO_SOURCE_PATH:0)>

21:47 bbloom: ,(instance? IAssocative [3 4])

21:47 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: IAssocative in this context, compiling:(NO_SOURCE_PATH:0)>

21:47 gfredericks: bbloom: clojure.lang maybe

21:47 bbloom: ,(instance? IAssociative [3 4])

21:47 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: IAssociative in this context, compiling:(NO_SOURCE_PATH:0)>

21:47 bbloom: ,(instance? clojure.lang.IAssociative [3 4])

21:47 clojurebot: #<CompilerException java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.lang.IAssociative, compiling:(NO_SOURCE_PATH:0)>

21:47 hyPiRion: Vectors has an ordering, whereas maps have no ordering

21:48 gfredericks: hyPiRion: that's not a convincing argument

21:48 bbloom: dur, no I

21:48 ,(instance? clojure.lang.Associative [3 4])

21:48 clojurebot: true

21:48 bbloom: ,(instance? clojure.lang.Associative {3 4})

21:48 clojurebot: true

21:48 bbloom: ,(assoc [0 1 2 3] 2 :omg)

21:48 clojurebot: [0 1 :omg 3]

21:48 gfredericks: hyPiRion: vectors behave similarly to maps in some cases, as bbloom is demonstrating

21:49 ,(dissoc '[a b c d] 3)

21:49 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap>

21:49 hyPiRion: Clearly.

21:49 gfredericks: hyPiRion: sorted-maps are also ordered

21:50 bbloom: the point i'm making is that you can't sort by type like you can in erlang b/c erlang has a closed set of mutually exclusive types

21:50 gfredericks: bbloom: yeah, I was sort of realizing the same thing

21:50 bbloom: effectively there is one type: a discriminated union of each of the primitive types

21:50 gfredericks: about fifteen inches up

21:51 bbloom: honesly, if i had my way, it wouldn't be possible to compare two things of different types at all. at least not without first promoting them to some other type that can represent all possible values for the types of both arguments

21:53 which is sorta what happens defacto anyway

21:53 hyPiRion: You got what you wanted then, hurray

21:53 bbloom: ,(compare :foo 'foo)

21:53 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.Keyword>

21:53 bbloom: ,(compare 'foo :foo)

21:53 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.Symbol>

21:54 gfredericks: ,(compare [1 2 3] (subvec [1 2 3] 1))

21:54 clojurebot: 1

21:54 bbloom: gfredericks: logically speaking, you're promoting to sequences

21:55 gfredericks: ,(compare (seq [1 2 3]) (seq (subvec [1 2 3] 1)))

21:55 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to java.lang.Comparable>

21:55 gfredericks: gotcha

21:55 hyPiRion: Huh

21:55 "throw Util.sneakyThrow(e);" <<-- Within Clj source

21:55 That guy, he's sneaky.

21:56 bbloom: gfredericks: heh, i'm actually surprised by that

21:56 bawr: XD

21:56 gfredericks: bbloom: phew. I thought I would get accused of ignoring your word "logically"

21:57 bbloom: gfredericks: ok fine, logically promoted to clojure.lang.Sequential

21:57 which apparently isn't comparable either lol

21:57 gfredericks: well it's an interface

21:57 I guess it could extend comparable, eh?

21:58 bbloom: now i wonder: why aren't seqs comparable?

21:58 gfredericks: maybe the idea was that potentially infinite types shouldn't be comparable

21:58 hyPiRion: bbloom: They may be lazy and infinite.

21:58 Have fun comparing that

21:58 bbloom: hyPiRion: dur. of course that makes perfect sense

21:58 gfredericks: ,(compare (range) (rest (range)))

21:58 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Comparable>

21:58 gfredericks: ,(compare (vec (range)) (vec (rest (range))))

21:59 hyPiRion: hah.

21:59 bbloom: gfredericks: poor little clojurebot

21:59 he works so hard

21:59 gfredericks: what does an eval server do for timeouts? Isn't killing a thread supposed to be unsafe?

21:59 bbloom: gfredericks: java have timeout security context feature thinggies

22:00 gfredericks: slick

22:00 bbloom: &(compare (vec (range)) (vec (rest (range))))

22:00 lazybot: Execution Timed Out!

22:01 gfredericks: ,(println "yo?")

22:01 clojurebot: yo?

22:01 gfredericks: phew

22:01 bbloom: you didn't kill it :-P

22:02 gfredericks: we have had 0 days since the last (println "yo?")

22:07 hyPiRion: gfredericks: https://github.com/hyPiRion/clojure/commit/4ef68dc957efa8fb4ade95260cade47a93880ddf

22:08 Now you have sortable maps

22:08 Too bad it killed sorted-map though, all the sorted-map tests failed it seems.

22:08 gfredericks: if you're not breaking sorted-map you're not doing real work

22:08 that's what my grandma always used to say

22:09 hyPiRion: Good thing I'm doing real work then!

22:09 gfredericks: haha I love that commit message

22:10 hyPiRion: It sounds like that's a feature, not a bug

22:11 "1.5: sorted maps are now not only deprecated, they also have completely undefined behaviour"

22:14 gfredericks: "1.5: the syntactic role of parentheses and square-brackets have been swapped everywhere."

22:14 I wonder how much change in the java code that would require

22:15 hyPiRion: [let ((a b) (2 3)) [+ a b]] => 5

22:15 gfredericks: Probably two lines

22:15 gfredericks: hyPiRion: and then a gsub or something over all the clj files

22:15 hyPiRion: Well, four,

22:15 Oh lordy

22:16 * gfredericks runs off for a bit

22:16 hyPiRion: That's my new goal

22:16 yogthos: fork clojure and swap square brackets and parens? :P

22:17 gfredericks: hyPiRion: name in Dlojure

22:17 bawr: Why are sorted maps deprecated? :<

22:17 yogthos: I think we're on to something here :P

22:17 bbloom: bawr: they aren't. these guys are just joking around

22:18 bawr: Go deeper. ()->{}->[]->||

22:18 ELIMINATE PARENS ALTOGETHER.

22:18 yogthos: or you could just do what scheme does and make them interchangable :P

22:19 hyPiRion: bawr: Sweet idea

22:19 bawr: Oh, the wonderful ambiguities of trying to swap [] with one token. xD

22:19 gfredericks: (defmacro with-silly-delimeters [& forms] `(do ~@(map (partial wk/postwalk #(cond (vector? %) (list %) (seq? %) (vec %) :else %)) forms)))

22:19 yogthos: you could name it dylan :)

22:19 http://en.wikipedia.org/wiki/Dylan_(programming_language)

22:20 hyPiRion: gfredericks: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L91-94

22:20 amalloy: gfredericks: you probly want list*

22:20 bawr: hyPiRion: But once that proves to be impossible, hey. []-><> can work, too.

22:20 yogthos: 4 lines it is

22:20 gfredericks: amalloy: ah that's why it doesn't work

22:20 that did it

22:21 hyPiRion: It's amazing that all these Clojure things I just joke around with makes me so knowledgeable around the internals

22:21 gfredericks: amalloy is the only person who reads my macros

22:22 hyPiRion: ,(list* ())

22:22 clojurebot: nil

22:22 bawr: gfredericks: Oh I read it, I just didn't parse it. ;)

22:22 hyPiRion: it's not as easy as you'd like it to be

22:22 gfredericks: hyPiRion: maybe seq is better

22:22 hyPiRion: ,(seq ())

22:22 clojurebot: nil

22:23 hyPiRion: :p

22:23 gfredericks: whoops

22:23 of course

22:23 (or (seq %) ()) then

22:23 hyPiRion: Surely that's the best way of doing this.

22:23 Wait.

22:24 yeah, that's the best way

22:24 must be.

22:39 gfredericks: man this reader code is so OO

22:39 ibdknox: do it with blind

22:41 gfredericks: okay with the power of google I cannot figure out what that cryptic comment meant

22:42 ibdknox: soon to be tools.reader: https://github.com/Bronsa/blind

22:43 gfredericks: eventually replacing the core reader? or what's the utility of making it a core lib?

22:45 bbloom: gfredericks: will probably become the reader for clojurescript

22:46 and via that channel, will eventually replace the core reader.... at about the same speed pypy is replacing cpython :-P

22:46 gfredericks: clojurescript gets to have all the fun

22:46 ibdknox: it's very useful for tools guys :)

22:47 gfredericks: clojure: a good language for building clojurescripts in

23:24 amalloy: gfredericks, hyPiRion: ##(doc sequence)

23:24 lazybot: ⇒ ------------------------- clojure.core/sequence ([coll]) Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. (sequence nil) yields () nil

23:25 gfredericks: woah it's like the opposite of seq

23:43 hyPiRion: All these core nuggets

23:43 ,(#'clojure.core/>1? 2)

23:43 clojurebot: true

23:59 technomancy: slamhound is back ladies and gents

Logging service provided by n01se.net