#clojure log - Dec 08 2012

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

0:00 dOxxx: It was rather hard, probably because I'm not very practiced in Clojure, and the performance sucked *hard*

0:00 Once I changed the clojure implementation to use mutable structures, the performance improved quite dramatically.

0:00 devn: there are lots of tricks. I remember _ato's version of WideFinder2

0:00 dOxxx: Now, I may have implemented the immutable version badly.

0:01 Like I said, not very practiced. I'm Java programmer by day :)

0:01 flying_rhino: dOxxx: performance sucking hard is precisely what I am trying to avoid here

0:01 devn: flying_rhino: but dude... science.

0:01 dOxxx: But it was only through testing and timing that I was able to figure out what was best.

0:01 devn: try it.

0:01 dOxxx: And I actually learned a few tricks from the clojure experiments that I was able to apply to the Scala implementation to make it *fly*

0:01 bbloom: forgive me for repeatedly linking to it… but it's really the best summary:

0:02 flying_rhino: http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

0:02 watch taht

0:02 devn: there are tradeoffs here. if you want to write this in assembly, you can do that. i remember this sort of discussion coming up a lot several years ago.

0:02 bbloom: flying_rhino: and everything here http://www.infoq.com/author/Rich-Hickey

0:02 the idea isn't to eliminate mutability

0:02 it's to limit and control it

0:02 devn: '"should i use haskell or clojure or C or OCaml or whatever" for it to be fast?'

0:03 bbloom: clojure has a very specific notions of state, time, value, and identity

0:03 rich discusses them eloquently through those talks

0:03 they are all worth watching and reflecting on

0:03 devn: (inc bbloom)

0:03 lazybot: ⇒ 2

0:03 devn: seriously, listen to bbloom -- and definitely check out "Are We There Yet?"

0:04 bbloom: flying_rhino: any real clojure application is going to have mutability, but it's carefully planned and minimized

0:04 i often have a single top-level mutable value in my applications

0:04 devn: Exactly

0:04 flying_rhino: maybe my mistake is that I am trying to implement one high order system (entity systems) to another high order system (clojure). Because Entity Systems have their way of handling state and identity.

0:04 bbloom: flying_rhino: i haven't read the things you've linked yet

0:05 devn: the point is: When you work with a clojure application, you can point at the parts of your program without much effort and say: "State changes here."

0:05 bbloom: flying_rhino: but you should also watch the videos about datomic

0:05 * devn blasphemes

0:05 devn: fuck the datomic videos.

0:05 bbloom: flying_rhino: www.datomic.com is rich's new database

0:05 flying_rhino: how free is it?

0:05 bbloom: it's not

0:05 devn: watch the clojure videos about state identity and time

0:06 that's all you need to get it

0:06 bbloom: yes, watch the clojure videos first

0:06 devn: datomic's videos are icing on the cake

0:06 bbloom: watch the datomic videos after you have a firm grasp on clojure's vocabulary

0:07 you're trying to run before you can walk… and people coming from java et al backgrounds often find that they can't even crawl at first!

0:07 devn: flying_rhino: is this your first lisp?

0:07 Apage43: I wrote some Java for the first time in a while the other day

0:08 Screenful of "final"s.

0:08 bbloom: Apage43: heh. it makes me want to weep trying to write java… and that was even before clojure

0:08 flying_rhino: devn: I was doing some stuff with plt scheme/racket but that thing has plenty of mutable state so it is different.

0:08 devn: flying_rhino: i dont mean for that to sound like im judging you or something, but im telling you, clojure was my first-ish lisp after a brief encounter with common lisp

0:08 dOxxx: I'll say this about Java: It's predictable and the syntax is very straightforward.

0:09 devn: flying_rhino: i think what you have exactly wrong is that clojure somehow purely functional. i said it before and ill say it again: stuart halloway nailed it when he said that "Clojure is a consenting adults language"

0:09 you can have mutable state

0:09 except it's *separate* from your program in a way that i think most programmers would appreciate

0:10 when you can point at your program and say: "hello code reviewer. state happens here at line 38 and line 49"

0:10 that is a beautiful thing.

0:11 it's not that state doesn't happen, or that magical monads are employed

0:11 its' that state is accessed like a database

0:11 it's*

0:11 dOxxx: heh magical monads

0:11 the way some people describe monads, you'd think they were responsible for the big bang

0:12 devn: hey man, ask the haskell community

0:12 there used to be an old joke

0:12 "how many monad tutorials have you read?"

0:12 *end of joke*

0:12 dOxxx: hehehehehe

0:14 anyway, lovely chat, gotta get up early in the morning. ciao.

0:14 flying_rhino: good bye

0:14 devn: ciao dOxxx

0:14 dOxxx: flying_rhino: good luck with grokking clojure :)

0:15 flying_rhino: dOxxx: I'll need more than luck

0:15 dOxxx: persistence :)

0:15 devn: (inc dOxxx)

0:15 lazybot: ⇒ 1

0:16 flying_rhino: like in LOTR my sword, and my bow, and my axe :)

0:17 devn: dude, if a rhino can fly

0:18 you can grok clojure

0:18 flying_rhino: lol

0:19 devn: btw, i think just about anyone who has used the word "grok" in a sentence on IRC

0:19 has every bit of capability required to undestand just about anything

0:19 flying_rhino: grok grok grok

0:19 devn: our friend dOxxx is right though...

0:20 persistence!

0:26 tpope: this weekend I'm going to learn clojure!

0:33 alandipert: tpope: booya!

0:38 bordatoue: hello, is there an easy way write a client in clojure that connects to different ports with a same ip address using tcp

0:44 bbloom: tpope: while i'm busy repeating it to everyone: watch rich's talks! :-)

0:45 Raynes: I don't like that bbloom guy.

0:45 bbloom: Raynes: yeah, he's a jerk. what did he do this time?

0:45 Raynes: Just a jerk

0:45 :p

0:46 bbloom: Raynes: yeah, last time he was in here, he was going around demanding people waste their time watching useful videos

0:46 Raynes: What a dick.

0:46 bbloom: big time.

0:48 Raynes: cldwalker_: Dude.

0:48 cldwalker_: Why didn't you tell me about this? https://github.com/cldwalker/datomic-refheap

0:48 It's cool.

0:48 And if I understood datomic *at all* I might even pull it.

0:49 Oh man, https://gist.github.com/samaaron/emacs-live/blob/master/packs/live/power-pack/config/refheap-conf.el Sam Aaron uses refheap.

0:50 I've hit the big time now.

1:12 urthwhyte: Hey, anyone had luck getting #clojure up and running on the RPi?

1:12 not sure why I added that pound sign, too much time on twitter of late I s'pose

1:14 tpope: bbloom: I just made it through simple made easy

1:14 Sgeo|web: If a function on clojuredocs is fundamentally broken, should I add an example to the body showcasing its brokenness?

1:14 (I currently have a comment. That comment seems to have been misunderstood by another commenter)

1:23 clj_newb_234: are there any publicized benchmarks of how fast clojure's "read" is ?

1:32 Apage43: clj_newb_234: ptaoussanis did some to compare it with his "nippy" serializer: https://github.com/ptaoussanis/nippy

1:33 clj_newb_234: also, if you want to benchmark something yourself https://github.com/hugoduncan/criterium may be handy

1:45 mindbender1: I'm trying to rid my projects from being infested with thneed snapshots that can't be found anywhere on planet earth

1:45 please send the paramedics

2:05 clj_newb_234: Apage43: got it; thanks

2:17 karimofthecrop: hi there. I am new to clojure. Trying to run tests from nrepl in emacs. I get error Unable to resolve symbol: run-tests in this context. what am I missing?

3:25 broquaint: karimofthecrop: You need to be in the namespace (or qualify it) that run-tests lives in.

3:26 karimofthecrop: broquaint: how do I do that? when I say new, I mean, I started programming clojure 60 min ago

3:29 :-)

3:29 tomoj: karimofthecrop: https://github.com/kingtim/nrepl.el#keys

3:29 in particular, "C-c M-n: Switch the namespace of the repl buffer to the namespace of the current buffer."

3:29 karimofthecrop: nice

3:29 tomoj: or, to do it manually in the repl, you can just (in-ns 'the.ns)

3:29 karimofthecrop: thx

3:30 tomoj: ..though that only works if the namespace has already been loaded

3:31 karimofthecrop: tomoj: thx again

3:38 so, now I have my buffer loading

3:38 and I have tests written, but (run-all-tests) is not in the ns

3:38 is there some special command to load that from clojure-test-mode?

3:42 tomoj: well, you can jump back and forth between implementation and test with C-c t (if you're lucky)

3:42 then C-c C-k in the impl to load it

3:44 does clojure-test-mode even work with nrepl?

3:44 muhoo: if i wanted to have a monotonically-increasing number (like for a message id), should i use an atom for that?

3:44 tomoj: oh, I have a very old version I think

3:46 muhoo: yep (swap! foo inc), perfect

4:06 karimofthecrop: tomoj: C-c t in clojure-mode 1.11.5 is very broken. I fixed it to go one way, but am a little green to fix it in both directions

4:07 matter of fact, I can't see that it is even intended to be bidi

4:09 tomoj: you're right

4:12 the clojure-test-mode at https://github.com/technomancy/clojure-mode/blob/master/clojure-test-mode.el has C-c C-s called clojure-jump-between-tests-and-code

4:12 but why is it version 1.6.0? O_o

4:12 my clojure-test-mode.el says 1.6.0 as well though it's different

4:12 guess that is dev version of 1.7.0

4:13 karimofthecrop: that fn isn't defined

4:14 the binding is

4:14 tomoj: I see, still wip I guess

4:14 karimofthecrop: :-

4:14 :-)

4:14 maybe I'll feel frisky and write one after I am done with 99 clojure problems :)

4:14 tomoj: looks like they do have a test->impl fn though?

4:14 oh, that's the one that already works, huh

4:15 where'd you get 1.11.5?

4:15 ah, that's your clojure-mode version

4:16 borkdude: goat moaning to y'all

4:17 karimofthecrop: mornin

6:23 fckw: Hi there.

6:24 I have a challenging programming problem:

6:24 I have many numbers, and each number can - but does not have to - be paired with 0..n other numbers.

6:25 All I am interested in is: Are two numbers paired or not?

6:25 How would you implement this, knowing that we are talking about millions of numbers?

6:26 And also knowing that in general, most numbers will not be paired, but few numbers will be paired with many other numbers.

6:26 ucb: fckw: what do you mean by paired?

6:26 AimHere: Here's a thing, if a is paired with b, and b is paired with c, is a paired with c? i.e. are these equivalence classes?

6:26 fckw: Building a tuple without further meaning.

6:26 Raynes: Winner of the vaguest question ever award right here.

6:26 * Raynes claps

6:26 Raynes: ;)

6:26 fckw: :)

6:26 ucb: heh

6:27 fckw: AimHere: No, it's not transitive.

6:27 An example:

6:27 5555 -> 345, 876, 1024

6:27 237 -> 1, 9999, 240

6:28 9999 -> 14, 8927, 1024

6:28 777 -> none

6:28 999 -> none

6:28 35232 -> none

6:28 Like this.

6:28 AimHere: In clojure terms, given that you're saying these are sparse, would a clojure hashmap to a list of vectors of the paired numbers be useful?

6:28 Raynes: How do you determine if a number is paired or not? Is this a list of numbers that you'd like to iterate through?

6:28 I don't even know where to start.

6:29 fckw: It's a sparse matrix, yes - but for a few elements there are many combinations with other numbers.

6:29 AimHere: as in {555 #{345 876 1024} 237 #{1 9999 240} ....}

6:29 list of sets, even, since you're just searching for some random member in them

6:29 fckw: The numbers represent "pointers" (not in C++ terms)

6:29 The easiest solution:

6:29 Use a HashMap or Dictionary with key = number, value = list of numbers

6:30 But that's very inefficient in terms of memory being used.

6:30 AimHere: Well you're doubling the memory, really

6:30 Which is not really 'very inefficient', I'd say

6:30 fckw: But is there not a better solution on the bit level?

6:31 I don't know exactly, but something like this:

6:31 4 -> 01001 would mean that number 4 is paired with number 2 and 5

6:31 AimHere: Well you could just have a set of one single number, each number representing a pairing, and which can be easily searched for

6:32 fckw: AimHere: And how would I conclude from the single number to the two original ones?

6:32 ucb: if you want some form of bit-based solution then you'd have to have a vector of all paired numbers, then use the index in the vector as bit position and then have a hashmap from number -> seq of bits

6:32 AimHere: So if you have a maximum MAX_VAL, then a set of values of (a*MAX_VAL+b), and use integer division or modulus to fetch the numbers

6:32 ucb: not sure why you'd want to do that though

6:33 AimHere: As one quick suggestion - that one might not be totally trivial to search, though

6:33 fckw: ucb: Yes, I was thinking about such a solution. But I was also wondering, whether this bit string could be compressed further.

6:33 AimHere: What would a and b be? My paired numbers?

6:34 AimHere: Yes

6:34 ucb: fckw: depending on how many numbers are paired, you could replace your bit string (which might be super sparse) with a vector of bit positions

6:34 * Raynes explodes into bits

6:34 * ucb picks the bits up

6:34 ucb: *badum-tish*

6:34 AimHere: You'd likely want to be able to sort by key%MAX_VAL and key/MAX_VAL for that idea

6:35 fckw: ucb: So I had some sort of vector/list, holding (2,5) to indicate that bit 2 and 5 were set, right?

6:35 ucb: fckw: yup

6:35 fckw: ucb: Hm. But in Java an int takes usually 32 bits. It all depends whether I'd save memory that way or not.

6:36 ucb: fckw: that's what I was saying initially; also an int might not be large enough to index your initial vector someimtes

6:37 Raynes: Are by any chance planning to run this on a toaster?

6:37 fckw: AimHere: I'm trying to understand. a*MAX_VAL+b would compute some sort of z or whathever that would represent a and b, right?

6:38 AimHere: Yes, and just store those zs

6:38 Trouble is, you need to have them sorted two different ways performancewise

6:39 fckw: AimHere: The question already arises out of a pairing function: I am using Cantor pairing function to compute z from x and y.

6:39 That's fine, code works. But the trouble is, for some z, there are other zs this z is combined with.

6:40 I was also thinking about using tries (e.g. Patricia trie) or the like.

8:15 squidz: this may be a bit off topic, but does anybody know which software development methodology works for 2-person teams or even single person projects?

8:27 kmicu: it depends x]

8:34 squidz: kmicu: go on..

8:35 you've got my attention ...

8:39 kmicu: it depends on how smart are those persons

8:40 squidz: okay, please lay out the options

8:44 kmicu: if they are smart then any methodology will be good, and if they are not so smart then nothing saves them ;)

8:44 * ucb .oO( knew it was a leading moment to that comment )

8:45 kmicu: and seriously can you be more specific with your goal?

8:47 Are you considering waterfall/scrum/xp... for 1-2 person team? ;]

8:50 squidz: im actually looking for a technique for myself for a personal project, and im hoping to have minimal distraction with said methodology

8:51 I mentioned the two person team because that might come in handy in the future, but for now, it is a single-person project

8:54 i'm not really looking to use scrum for a 1-2 person team, I really just want a way to organize my own work on a project

8:57 ucb: squidz: then use whatever works best for you :)

8:57 squidz: some people use jira/trello/asana + pomodoro for instance

8:59 squidz: im looking at pomodoro right now, and I have only barely used jira and trello. I'm thinking trello + pomodoro looks good to try out. I don't know what works for me, since Ive never really tested these waters, but I guess now is that time. Thanks ucb and kmicu

8:59 Natch: TODO.org file and a generous helping of red bull works for me :)

8:59 ucb: squidz: sure; if you're regimented and virtuous pretty much anything will work for you ;)

9:01 kmicu: RescutTime for procrastination monitoring

9:02 RescueTime*

9:04 squidz: kmicu: thanks

9:08 yedi: links to some alternatives to disclojure?

9:10 kmicu: clojure gazette, planet clojure, prismatic?

9:11 Gonzih: clojure subreddit

9:11 andrewmcveigh: I need a multi-method, but where the dispatch value can be something like a core.match pattern. Does something like that exist?

9:19 yedi: thanks

9:19 dunno why the clojure reddit didnt immediately come to my mind

9:21 Scriptor: it doesn't see a lot of activity, but good to check once a day or so

9:21 AimHere: There's also the google group for clojure (maybe it's actual usenet, even)

9:30 gfredericks: I'm trying to run 4clojure on a fresh box; I installed mongo (which I don't have any experience with), but get odd connection errors when I try to start 4clojure

9:31 on second thought maybe it's a vanilla connection-refused :/

9:33 java.io.IOException: couldn't connect to [li424-81/] bc:java.net.ConnectException: Connection refused

9:33 the syntax there makes me wonder if it's somehow mangling the hostname and the IP address together?

9:34 connections are definitely being accepted at port 27017

9:34 or maybe just that it's trying to connect to the public interface instead of localhost

9:35 the config says host is "localhost" though :/

9:44 kmicu: :db-name "4clojure"

12:11 krtful: Chousuke, do you have a code example for me where empty collections counting as false in boolean logic can lead to bugs or is otherwise inconvenient?

12:14 devn: gfredericks: you could try and see if you get a different result from localhost maybe?

12:15 AimHere: I don't know what Chousuke has been talking about, but consider a map whose values are collections; you can't just (if (get foo :bar) <whatever>) anymore, since the result will be false if you either have empty collections or :bar isn't in the map

12:17 devn: ,(if (get {:bar [1 2 3]} :bar) true false)

12:17 clojurebot: true

12:18 devn: AimHere: i don't follow

12:19 ucb: ,(if (get {:bar []} :bar) true false)

12:19 clojurebot: true

12:19 ucb: eep

12:19 ,(if (get {:bar #{}} :bar) true false)

12:19 clojurebot: true

12:19 ucb: ,(if (get {:bar {}} :bar) true false)

12:19 clojurebot: true

12:19 ucb: ,(if (seq (get {:bar {}} :bar)) true false)

12:19 clojurebot: false

12:19 ucb: there we go

12:19 devn: ,(if [] true false)

12:19 clojurebot: true

12:19 AimHere: devn, I was answering krtful; he was talking about the hypothetical case where '() would be equal to false. Clojure doesn't do that, unlike other lisps

12:20 devn: oh, gotcha

12:21 ,(if (get {:bar #{}} :bar nil) true false)

12:21 clojurebot: true

12:21 AimHere: ,(if (get {:bar nil} :bar) true false)

12:21 clojurebot: false

12:22 devn: *nod*

12:22 krtful: AimHere, you should never use (if (get foo :bar) though bur thar (if (contains? foo :bar) yeah, but I suppose it's safe if you intend to map on collecitons only.

12:23 AimHere: krtful, When should you ever test collections for boolean truthiness in the first place? I just picked the first one that sprang to mind...

12:25 krtful: AimHere, you "shouldn't", I'm just seeking particular cases. I'm implementing some toy lisp and I've been debating with myself if I should have only nil and false as falsy or that + empty collections + NaN

12:25 Basically, I'm vehemently against 0 as falsy because it leads to a thousand and one bugs.

12:25 AimHere: Make everything falsy, except true

12:26 krtful: But I'm not sure if considering empty strings, empty lists and the loss does cause bugs.

12:26 lol

12:26 THere was this one lagauge which did that right?

12:26 Isn't in visual basic anything falsy except -1 or something.

12:26 gfredericks: maybe there could be a special object called not-nil that is also truthy

12:27 only true and unit are truthy

12:27 krtful: unit as in the unit type or the value in that type?

12:27 gfredericks: the value I suppose

12:27 also any double larger than 1e10 is truthy

12:27 AimHere: Make true true; make false false. Make everything else a coinflip

12:28 You'd better understand your damn code before you try debugging!

12:40 krtful: AimHere, in PHP "0" is false though

12:41 AimHere: PHP probably borrowed that from Perl

12:45 llasram: Or from C?

12:45 AimHere: "0" isn't false in C

12:45 krtful: I'm pretty sure "0" doesn't count as false in C

12:46 llasram: Oh, the string "0"

12:46 AimHere: "0" here is a string with the numeral 0 in it

12:46 seangrove: Is there an equivalent method for (not (empty? '()))

12:46 krtful: No, a string with the character '0'

12:46 llasram: Ignore me, I obviously wasn't following the convorsation

12:46 krtful: 0 shouldn't be false either

12:46 I'm okay with making NaN false though.

12:47 llasram: seangrove: seq ?

12:47 AimHere: seancorfield, "false"

12:47 krtful: NaN tends to signal 'stuff didn't go as expected'

12:47 seangrove: llasram: Oh, interesting

12:48 AimHere: ,(seq? '())

12:48 clojurebot: true

12:48 AimHere: ,(seq? '(3))

12:48 clojurebot: true

12:48 metellus: ,(seq '())

12:48 clojurebot: nil

12:48 llasram: seangrove: The docstring for `empty?` even mentions the idiom, making it enshrined in code :-)

12:49 devn: seangrove: I tend to just create (defn not-empty? [x] (comp not empty?)) because i like the way it reads

12:49 * devn shrugs

12:49 seangrove: devn: That's probably best, yes. It's a bit more obvious than just `seq`

12:51 llasram: It's obvious to people don't know Clojure well, but using `seq` to test for emptiness is pretty well enshrined

12:51 er, non-emptiness rather

12:51 s,obvious,more obvious,

12:51 oskbor: Hi, is this the place for a newbie question?

12:52 llasram: It is the place for all questions

12:52 Answers come and go :-)

12:52 seangrove: ~justask

12:52 clojurebot: Titim gan éirí ort.

12:52 oskbor: ok :) I cant really wrap my head around why this shouldnt work: (+ [1 2 3])

12:53 gfredericks: oskbor: what other languages are you familiar with?

12:53 oskbor: java ruby javascript

12:54 gfredericks: in java you would not expect {1,3,4} + {4,5,6} to work, correct?

12:54 (assuming those are arrays)

12:55 oskbor: hmm true

12:55 gfredericks: + expects its arguments to be numbers

12:55 oskbor: ok, but how do i sort of flatten the vector then?

12:55 gfredericks: you can give any number of arguments

12:55 apply is your friend in this situation

12:56 raek: ,(apply + [1 2 3])

12:56 clojurebot: 6

12:56 oskbor: will look into this apply voodoo

13:18 sshack: So simple clojure question. Say I've got a record, (defrecord account [number balance]), and I want to do some aggregate function over all the balances (mean, histogram, whatever). Can I transpose all those balances into a list easily?

13:18 gfredericks: you have one record or a list of records?

13:19 sshack: Sorry, a list of records.

13:19 gfredericks: you can (map :balance my-records)

13:20 that would give you a list of balances

13:20 sshack: Awesome.

13:20 I'm porting some code from Mathematica here. So it's sort of lost in translation issues.

13:37 crease: hm. anyone know of good libraries to assemble (even janky) call hierarchies on clojure source?

14:42 gfredericks: Raynes: ping

14:44 qerub: I have a Seq that I want to convert to a type that depends on a value. I'm happy with (into (empty myvalue) myseq), apart from that (into (list) '(1 2 3)) reverses the list because of conj. Is there any nice way to do this?

14:44 &(into (list) '(1 2 3))

14:44 lazybot: ⇒ (3 2 1)

14:45 qerub: I could always dispatch on the type myself and use (apply list myseq), but…

14:50 gfredericks: Raynes: unping

14:58 qerub: For the record: I'm settling with (defn ordered-into [to from] (into to (if (seq? to) (reverse from) from))) for now. :/

14:59 hyPiRion: qerub: concat?

15:00 ,(concat (list) '(1 2 3))

15:00 clojurebot: (1 2 3)

15:00 hyPiRion: ,(concat (vec) '(1 2 3))

15:00 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core$vec>

15:00 hyPiRion: ,(concat (vector) '(1 2 3))

15:00 clojurebot: (1 2 3)

15:01 qerub: I currently need to be able to get the result as a vector too.

15:01 &(into [] '(1 2 3))

15:01 lazybot: ⇒ [1 2 3]

15:05 qerub: Sorry, I'm not expressing myself clearly. I have a function that can operate on lists and vectors and I want the return type to match the input type. The function works with seqs internally so I'm looking for a way to convert back.

15:08 &(defn test [] "Are functions OK?")

15:08 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

15:09 tylergillies: Is there something like rubygems for analogous to clojars? Its a cool site, but theres not much sexay there :)

15:10 s/for/for clojure/

15:10 qerub: tylergillies: What are you missing the most from Clojars?

15:11 tylergillies: qerub: all links are internal to clojars, rubygems has links to source, documentation, authors website, etc

15:14 i usually use it to find github page for projects on a general topic

15:14 qerub: tylergillies: Actually, there are website links if the URL is specified via e.g. :url in project.clj.

15:14 tylergillies: qerub: ah, thats just my ignorance :)

15:15 qerub: tylergillies: I don't know about the other link types, but I do agree they should be there too.

15:17 tylergillies: i just did search for "png" on clojars, i found a lib for png manipulation, would like to know what the github url is so i can thumb through the code before i download it

15:17 thats my biggest usecase for visiting a site like that

15:18 qerub: tylergillies: There's http://www.clojuresphere.com/ too.

15:18 tylergillies: qerub: checking it out, thanks :)

15:19 no link to github, but theres a link to clojars lol

15:19 qerub: :>

15:20 tylergillies: http://www.versioneye.com/search?lang=%2Cclojure%2C&q=png

15:20 tylergillies: Same there, hehe.

15:20 clojurebot: I don't understand.

15:21 tylergillies: that might be a bad example, i just found another project on clojuresphere with link to github

15:21 can't find lib on clojars though

15:21 http://www.clojuresphere.com/org.lispnyc.webapp.homebase/org.lispnyc.webapp.homebase

15:24 qerub: tylergillies: Have you managed to track down the source to png-extract?

15:24 tylergillies: qerub: nope heh

15:28 ivaraasen: qerub: what kind of png manipulation do you need to do?

15:28 qerub: *redirects ivaraasen's question to tylergillies*

15:29 ivaraasen: ah sorry, too little coffee this evening

15:29 tylergillies: ivaraasen: something that will break png image data into chunks for easy chunk manipulation

15:29 theres a good ruby lib called chunkypng

15:30 ivaraasen: could perhaps use im4clj

15:30 tylergillies: philosophical question: do you guys think that easy interop with java makes it so people don't feel the need to create clojure specific libraries?

15:31 ivaraasen: googlin it, thanks

15:31 imagemagick wrapper.... gah

15:32 thanks but no thanks ;)

15:32 ivaraasen: I've used it a couple of times, but nothing fancy

15:32 maybe ImageIO from Java?

15:33 tylergillies: ivaraasen: thanks

15:34 found http://code.google.com/p/javapng/

15:34 meh, its not in maven

15:35 devn: tylergillies: depends. sometimes i want a more clojure-ey way of dealing with a java library, so i wrap those parts up

15:35 tylergillies: in some cases the answer is absolutely yes, because i dont want to write a library to do something really difficult that is...done already, and very mature

15:35 tylergillies: devn: valid points :)

15:36 qerub: tylergillies: Re: the philosophical question; yes, I believe so. A factor is that Clojure was created to be a "hosted language" that doesn't hide the underlying platform (even clojure.core leaks some Java-isms), so I guess it isn't looked down upon to drop down to the libraries for the underlying platform.

15:37 devn: tylergillies: that being said, i think that sometimes it might discourage people from building something that exists in java, but actually sucks

15:38 *maybe*

15:38 i dont have data or anything, just guessing

15:38 tylergillies: qerub: ah so yes, but its not a bad thing

15:39 devn: something sucking in java? never. *disclaimer* I'm coming from ruby ;)

15:40 devn: tylergillies: everything sucks. we're all just trying to pick the thing that sucks the least at any point in time.

15:41 qerub: I'm a bit of a purist, so my stomach turns a little bit every time I see Clojure code with lots of Java interop, but I realize my unacceptance is rather irrational.

15:41 devn: qerub: yeah, well, then you call (class "string") => java.lang.String

15:41 there's no need to pretend we're not in java

15:41 just bask in the fact that you live in the sane part of it

15:42 qerub: devn: Well put :)

15:42 devn: or allow other people to fool themselves by wrapping every bit of java in a function

15:43 sshack: Hrm. Any way to define a record from an table in a database?

15:45 amalloy: don't do it, man. maps are the one true data structure

15:47 sshack: In this case, I don't think so.

15:48 My main purpose is to load a bunch of records into memory and doing aggregate functions on their various fields.

15:48 citizenparker: Anyone done much with per-environment configuration in leiningen?

16:00 tylergillies: amalloy: speaking of maps being ultimate datastructure, why do a bunch of functions use vectors to map things instead of actual maps? e.g. (let [foo bar biz baz]) vs (let {:foo bar :biz baz}) or something similar

16:01 gfredericks: well let is order-dependent

16:01 vectors in general are used in clojure for introducing locals

16:02 tylergillies: i understand its idomatic, its just strike me as a bit odd

16:02 maybe i need to drink more koolaid ;)

16:02 llasram: I think the order-dependance gfredericks mentioned is the thing. Clojure in `let` previous locals are visible to subsequent locals

16:03 gfredericks: letfn is the only exception to the order-dependence that I know of

16:03 llasram: Right, and the syntax of that one is a bit different in a way which doesn't lend itself to using a map at all

16:04 tylergillies: order dependance meaning (let [foo bar biz (i can use foo here?)]) ?

16:04 gfredericks: yep

16:04 tylergillies: gotcha

16:04 that makes sense

16:35 popo1234: ,(let [s (iterate inc 0)] (print (take 2 s)) (print (take 2 s))))

16:35 clojurebot: (0 1)(0 1)

16:36 popo1234: How do I get (0 1)(2 3) ?

16:37 amalloy: &(take 2 (partition 2 (iterate inc 0)))

16:37 lazybot: ⇒ ((0 1) (2 3))

16:41 daniel_karlsson: Thought I would get to know Clojure for a bit. Is Emacs the way to go (I have never used Emacs and are on OS X)?

16:43 tpope: if you don't have strong attachments to any other editor, probably

16:43 amalloy: daniel_karlsson: emacs is most popular, but your best bet is to use what you know

16:45 Raynes: There is counterclockwise for eclipse, vimclojure for vim, clojure-mode for Emacs, crappy support in sublime text 2.

16:45 You could also write it down on paper and scan it later.

16:45 Lots of ways to write Clojure.

16:45 daniel_karlsson: I tried it in Sublime Text 2 and it was a bit of a pain

16:46 Foxboron: daniel_karlsson, i have made some stuff for Sublime regardiung Clojure :)

16:46 Ported some snippets and made a clojuredoc search plugin.

16:46 But the SUblimeREPL is still broke with Lein2

16:47 daniel_karlsson: ok, I tried to interact with the REPL but it was not picking up key commands

16:47 Might be since I use the Vim bindings

16:47 Raynes: It's more that the indentation is just pathetic.

16:47 popo1234: amalloy: thanks!

16:48 ivaraasen: tylergillies: did you succeed in chunking up your img?

16:48 daniel_karlsson: Ok, cool. Mostly wondered if Emacs was the way to go. Thanks

16:50 bbloom: daniel_karlsson: if you're a vim guy, just stick with vim. don't try to learn a language and an editor at the same time :-)

16:50 tpope: ^^^

16:54 daniel_karlsson: yes, I guess Clojure will be enough for my brain to handle

16:58 Raynes: I've never really bought that.

16:59 If you want to learn an editor and a language, go for it.

16:59 Turns out the human brain is capable of it.

16:59 What they really should be saying is "Don't learn an editor just because you think you have to in order to use Clojure." because you certainly do not.

17:00 bbloom: Raynes: I tried to learn clojure and emacs at the same time, but it didn't go well. and i already had some basic emacs skills...

17:00 so while this human brain may be capable, it doesn't seem favorable

17:00 tpope: I'm pretty fiddly about my editor, so trying to learn emacs at the same time would mean learning elisp

17:00 amalloy: i had a great time learning emacs and clojure at the same time

17:01 tpope: I don't think anyone is smart enough to learn their first two lisps at the same time :)

17:01 bbloom: tpope: "pretty fiddly" is an understatement….

17:01 Raynes: bbloom: Were you, by chance, learning Emacs because you felt you needed to to use Clojure?

17:01 If so, you fall into the above category I mentioned.

17:02 bbloom: Raynes: to some extent. however it was because i simply didn't have a workable repl available to vim

17:02 that was pre nrepl, early broken nailgun days of vimclojure, etc

17:02 Raynes: tpope: Nice to meet you, btw. I used lots of your Vim stuff in my Vim days.

17:02 <3

17:02 tpope: cheers

17:02 Raynes: But I guess so does everybody.

17:02 tpope: I have a clojure plugin now too

17:02 in case you missed it

17:03 Raynes: I saw. Good stuff.

17:03 I use Emacs with evil-mode these days or I'd be all over it.

17:03 I was actually using vim last night though, because Emacs doesn't highlight viml out of the box.

17:03 tpope: weird, cuz vim highlights elisp out of the box :)

17:04 bbloom: heh.

17:04 Raynes: Also, regarding the other convo.

17:04 I learned Haskell and Emacs at the same time.

17:04 bbloom: Raynes: I tried evil-mode, but learning clojure, emacs, and not-quite-vim at the same time was even less favorable than learning clojure and emacs without the not-quite-vim mode

17:05 Raynes: It's pretty-close-to-vim

17:05 Everything I most commonly used in Vim is there.

17:05 For me, anywyas.

17:05 bbloom: *shrug* pretty-close-to-vim is almost worse than no vim bindings at all

17:05 Raynes: anyways*

17:05 That's pretty silly.

17:06 tpope: I couldn't get the hang of it, but I didn't fight it very long

17:06 bbloom: nah, i'd rather have no vim bindings than ones that break my muscle memory

17:06 but my normal mode fu is pretty strong

17:06 Raynes: I don't know what you just said, but okay

17:07 tpope: I'll up my emacs game if I ever get a chance to pair with someone who's really good at it

17:07 bbloom: normal mode is vim's default mode

18:10 svedubois: I would like to write an android app using clojure. Do you know some tutorial ?

18:11 gfredericks: tpope: http://bjeanes.com/2012/09/pure-evil

18:13 (a coworker of mine who switched vim->evil and was particularly enamored of the internal design)

18:14 svedubois: Do you know some website wrapper to develop android applications using clojure ?

18:16 ghachey_: quit

18:16 * gfredericks quits

18:26 ivaraasen: anyone want to critique my first shot at Java inter-op?

18:28 antoineB: show

18:30 amalloy: anyone who wants to, can't do it till you link it

18:31 ivaraasen: https://www.refheap.com/paste/7424

18:34 amalloy: ivaraasen: you certainly don't need that atom in save!

18:35 you can, for example, (dorun (map-indexed ...)), or you can reduce over (range n), or you can loop/recur

18:37 ivaraasen: agreed

18:38 antoineB: why do you use "(into []" in create-buffer?

18:39 ivaraasen: rough translation from some Java code, so I utilised the fact that vectors given a number return the item at that index

18:40 antoineB: ,(nth [1 2 3] 2)

18:40 clojurebot: 3

18:40 ivaraasen: argh

18:40 this is embarassing

18:40 antoineB: ,(nth '([1 2 3) 2)

18:40 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

18:41 antoineB: ,(nth '(1 2 3) 2)

18:41 clojurebot: 3

18:41 metellus: ,(nth [1 2 3] 0)

18:41 clojurebot: 1

18:41 callen: antoineB: please use a repl or something privately if you're just learning something.

18:41 antoineB: clojurebot is mostly for demonstrating a concept to others, not for personal experimentation.

18:41 Raynes: Because you're just bothering the crap out of us, man.

18:41 callen: antoineB: alternately, /query the bot.

18:41 Raynes: I was about to call the internet police.

18:41 But since callen is obviously the sheriff.

18:41 callen: Raynes: no call the internet FBI

18:42 Raynes: DEMS A FELON!

18:42 Raynes: Oh noes

18:42 callen: felonious repl.

18:43 Raynes: Sounds like a character from Harry Potter.

18:44 callen: Raynes: maybe from HP:MOR

18:44 antoineB: ivaraasen: "for" return a sequence so you can directly use nth, don't need "(into []"

18:45 callen: sorry

18:45 amalloy: well if he actually needs random access nth on a seq is not a very nice solution

18:45 callen: antoineB: never apologize! be unabashed at all times.

18:46 antoineB: ivaraasen: you use bang at end of your function name, this mean the function mutate an object

18:47 amalloy: vector is good for random access isn't?

18:47 amalloy: indeed, and you told him not to use one

18:47 ivaraasen: antoineB: most of these fns change objects. wasn't sure if the convention was for passed objects or changing the world in general

18:47 antoineB: yes right

18:48 ivaraasen: most of this is done sequentially, so it's not that important with random access, yeah

18:48 antoineB: read-image! should read-image

18:48 ivaraasen: agreed

19:04 tomoj: does persistent! have a ! because you shouldn't try to use it more than once on a given transient?

19:06 ah yes

19:19 kensho: Hi. I have a list of key-value pairs like this [[:foo :a] [:foo :b] [:bar :c]]. I want to get this into a map where each key maps to a seq of all values, i.e. for my example this would be {:foo [:a :b] :bar [:c]}. I can do it with (reduce (fn [m x] (update-in m [(first x)] conj (second x))) {} key-value-pairs) but this strikes me as a pretty common use-case so I'm wondering if there is a shortcut for this kind of thing?

19:20 mthvedt: kensho: have you looked at group-by

19:21 tomoj: group-by frustrates me. but if you had r/group-by, which returned an IKVReduce (and if IKVReduce were useful), that could be pretty nice

19:22 (comp ((comp r/map r/map) second) (r/group-by first)) ?

19:23 amalloy: tomoj: that sounds more like rap lyrics than a useful clojure function

19:23 tomoj: kensho: ignore me

19:25 kensho: thanks. group-by looks promising but doesnt work quite the way I need because it should only use the second element of each pair as value, group-by simply takes the whole pair so I get {:foo [[:foo :a] [:foo :b]]} etc.

19:26 tomoj: yes, and then you have to break up the map, do your thing, and then recreate another map :(

19:26 s/recreate/create/

19:27 kensho: yeah, I guess I stick with the reduce version

19:28 amalloy: kensho: well, write a more general version of group-by that solves your current problem as well as future problems like it

19:28 tomoj: (fn group-with [kf vf coll]) ?

19:28 amalloy: (group-with find-key keep-value coll)

19:29 tomoj: is r/group-by even feasible?

19:29 kensho: that's a good idea thanks

19:29 amalloy: (defn group-with [kf vf coll] (reduce (fn [acc x] (update-in acc [(kf x)] (fnil conj []) (vf x))) {} coll))

19:30 that's a function i've wanted a few times

19:30 tomoj: whoa, I think that's the first time I've seen fnil in use, and that is a pretty nifty use

19:31 amalloy: tomoj: it's the most common use :P

19:32 it tends to be pretty hard to think of any other uses for it

19:32 tomoj: (fnil inc 0) similarly

19:32 amalloy: oh, that's true

19:32 also (fnil + 0)

19:32 tomoj: I always write #(inc (or % 0)) or whatever

19:33 bbloom: amalloy: i had no idea that existed. thank you

19:33 amalloy: though on reflection i can't remember why i needed nil to work in an addition

19:34 kensho: oh nice, didn't know about fnil, very handy. thank you.

19:34 bbloom: now i really want to query a codeq db to see who uses fnil

19:34 somebody get on that :-)

19:35 tomoj: &(update-in {} [:foo :bar] (fnil + 0) 2)

19:35 lazybot: ⇒ {:foo {:bar 2}}

19:37 bbloom: (def conjs (fnil conj #{}))

19:38 ((fnil conj #{}) nil 5)

19:38 ,((fnil conj #{}) nil 5)

19:38 clojurebot: #{5}

19:38 bbloom: i need that frequently

19:41 gfredericks: every 2 months somebody mentions fnil and I decide it's something I need to remember

19:41 * gfredericks forgets about fnil

19:47 tomoj: bblöom: I remember you asking about that and me suggesting #(conj (or %1 #{}) %2) :(

19:57 bbloom: tomoj: yeah, but the fnil version works with var args too :-)

19:58 gfredericks: use-only is the same as require-refer, correct?

19:59 bbloom: gfredericks: if there are any differences, they are too subtle for me to have noticed

20:07 seangrove: Any reason I wouldn't have clojure.pprint?

20:07 ~pprint

20:07 clojurebot: Cool story bro.

20:08 seangrove: hrm, getting "CompilerException java.lang.ClassNotFoundException: clojure.pprint"

20:08 gfredericks: seangrove: you've required it successfully?

20:09 seangrove: gfredericks: Nope, that was the problem

20:09 I thought if I referenced the full name, it needn't be required

20:09 Thanks!

20:10 gfredericks: that only works if some other ns already required it

20:10 so best to be explicit

20:14 augustl: trying to use proxy for the first time, seems the objects it generates aren't accepted by Java method signatures.. Getting "no matching method".

20:15 here's my code https://www.refheap.com/paste/7427

20:15 bbloom: tpope: been abusing cpr, even though i generally have been evaluating individual forms. got burned hard by instance? breaking because i redefined a type that i had an instance of in my scratch file :-/

20:16 (class x) returned foo.Bar and (instance? foo.Bar x) returned false :-/

20:16 emacs people: any good way to deal with that?

20:16 amalloy: bbloom: don't redefine types and expect old instances to be any good

20:16 bbloom: other than to avoid reloading files that declare types for which i have instances of them?

20:17 amalloy: yeah that's clearly the problem

20:17 i just wish it wasn't so easy to be fooled by (= (str (class old-x)) (str (class new-x)))

20:18 amalloy: augustl: scheduleAtFixedRate isn't static

20:22 augustl: amalloy: doh, thanks

20:27 gfredericks: (defn siblings? [x y] (= (class x) (class y)))

20:27 seangrove: Have trouble with this macro https://www.refheap.com/paste/7428

20:28 Map is returning a list, so the resulting form isn't right for doto

20:28 gfredericks: try list* instead of list

20:30 seangrove: That looks great, thanks

20:36 amalloy: seangrove: more like https://gist.github.com/69abccfc2793eeaafe45 maybe

20:37 seangrove: ooohhh, interesting

20:38 I was just wondering how to prevent value from being qualified on expansion

20:38 Thank you

21:16 callen: my google-fu is failing me here and I end up in a maze of Google Group mailing lists, all alike. What's the story on futures/promises in ClojureScript?

21:16 benizi: lein bootstrap is equivalent to: lein deps git-deps

21:17 (sorry: apparently responded to a question from days ago)

21:17 tomoj: callen: there isn't much of one that I know of

21:18 callen: tomoj: namely, they don't work?

21:18 tomoj: well, neither cljs.core/promise nor cljs.core/future exist (right now)

21:18 callen: tomoj: disturbing...okay. Thanks!

21:19 tomoj: there's this thread https://groups.google.com/d/msg/clojure-dev/-/XD1hnBvjNt8J

21:19 (with links to wiki design pages. the link to cljque is out of date, the master branch is now the interesting one)

21:19 that thread is about unifying promises and futures under a callback-based interface

21:20 which, eventually, could lead to something in cljs, though cljque is only on the jvm for now

21:23 muhoo: but isn't javascript single-threaded?

21:24 tomoj: hence "callback-based interface"

21:24 oh, it's unclear what clojure.core/future might look like in cljs, yes

21:25 or whether it's even necessary?

21:27 muhoo: i haven't used futures or promises yet. then again, i'm still new.

21:27 tomoj: I think stu's current idea is that @(promise) will throw an exception in cljs

21:38 bbloom: is there a quick/easy way to see all of the interfaces/protocols on a given instance of an object?

21:39 brehaut: supers?

21:39 (without the question)

21:39 bbloom: ,(supers (class {}))

21:39 clojurebot: #{java.lang.Runnable clojure.lang.IObj java.lang.Iterable clojure.lang.IPersistentCollection clojure.lang.Counted ...}

21:39 brehaut: oh probably (comp supers class)

21:39 bbloom: yeah

21:39 hm thanks

21:40 ,(doc supers)

21:40 clojurebot: "([class]); Returns the immediate and indirect superclasses and interfaces of c, if any"

21:40 bbloom: seems to be interfaces tho, not protocols

21:40 amalloy: well, that will show you the interfaces. protocols, you're sorta SOL

21:40 no such mechanism exists

21:40 technomancy: I always use the slime inspector for that

21:40 bbloom: technomancy: and us vim peasants?

21:40 amalloy: technomancy: how? i'd be amazed if the slime inspector worked

21:40 brehaut: amalloy: it'll show you any protocol generated interfaces for types that are lucky enough to use the interface right?

21:40 amalloy: (for that)

21:41 of course

21:41 technomancy: amalloy: not protocols; I never use protocols

21:41 just to explore classes, interfaces, methods, constructors, etc

21:41 brehaut: technomancy believes in the monomorphism restriction

21:45 bbloom: i want an IAssoc that has a dispatch function with a hierarchy, like a multimethod

21:46 unless somebody tells me that exists, i'm going to make a DispatchMap class, which will be basically the immutable/persistent internals of MultiFn

21:47 plus the caching behavior

23:06 seangrove: bbloom: So you can dispatch on subkeys in maps?

23:50 Raynes: Dear #clojure. You can do this now: http://jsfiddle.net/frf8C/3/

23:50 Carry on.

23:53 ivan: Raynes: why not just attach one callback that does both steps? ;)

23:54 Raynes: What?

23:54 clojurebot: what is exceptions

23:55 ivan: I assume this is a goog.async.Deferred or similar

23:55 Raynes: I don't do ClojureScript.

23:56 Oh.

23:57 OH.

23:57 Jesus.

23:57 ivan: :)

23:57 Raynes: The code.

23:57 I thought you were talking about my embedding js, ivan!

23:57 ivan: I knew something was up

23:57 Raynes: Yeah, thats just a random paste I plucked out of recent pastes to demonstrate embedding.

23:59 tomoj: seangrove: I think goog.async.Deferred is, uh, bad

23:59 seangrove: tomoj: How so?

Logging service provided by n01se.net