#clojure log - Dec 11 2010

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

0:31 harishtella: does anyone here use rlwrap for spicing up their clojure repl?

0:34 jk__: harishtella: i have it that way on my linux box. set it up before i knew about lein/cake and it works very well

0:36 harishtella: jk__: I really like, but I couldn't get paren highlighting to work. Was that working for you?

0:37 jk__: harishtella: doesn't highlight, it jumps the cursor to the matching one when you close

0:39 harishtella: to be honest, i only use that now when i want to try something very quickly. usually i use CCW in eclipse so i can have a nice editor (never learned emacs)

0:53 harishtella: jk__: maybe it just doesn't work in mac osx, thanks anyways

1:28 ossareh: what is "holding onto the head of a seq"? where can I read more about this?

1:37 amalloy: ossareh: ##(let [x (range)] [(nth x 1e6) (first x)])## is no good cause you keep the whole seq in ram all at once; ##(nth (range) 1e6) is fine

1:37 sexpbot: (let [x (range)] [(nth x 1000000.0) (fir... ⟹ [1000000 0]

1:37 (nth (range) 1000000.0) ⟹ 1000000

1:37 amalloy: (for a larger number than 1e6 the first would fail)

1:38 in the second case, since you no longer have any reference to the first element of the seq while you're computing the last, the GC can safely throw it away

1:39 lancepantz_: wow, that's awesome, raynes has been going to town on sexpot

1:39 amalloy: lancepantz_: that was me :P

1:39 lancepantz_: oh shit, i'm sorry!

1:39 amalloy: haha np

1:39 glad you like it

1:39 lancepantz_: love the inline evaluation

1:40 amalloy: $markov

1:40 sexpbot: You need if you have been bitten by writing.

1:40 amalloy: mine too, but not looking so clever

1:42 ossareh: amalloy: am I holding onto the head of a seq ? https://gist.github.com/737179

1:42 line 1 in exceptions.log shows what I'm running to eventually result in the exceptions below.

1:44 amalloy: ossareh: i've never seen that traceback before, but it doesn't look like that's your problem

1:44 usually you just get OutOfMemoryError: Java heap space

1:44 ossareh: nah

1:45 this is my first use of agents - first OOM's in clojure too.

1:45 amalloy: ossareh: tbh i can't make heads nor tails of the trace

1:46 ossareh: wonder if I'm causing some issues within the thread pools

1:47 what is very interesting is that running that code results in the first 60-100 companies being printed out almost immediately - far too quickly for http requests to really be taking place (though without any knowledge of the thread pool size it is hard to be sure)

1:47 that said - same things happens if I don't use pmap.

1:49 amalloy: ossareh: looking over your code, here are a few functions i think you will find very helpful, though probably not to fix your bug

1:49 fnil, assoc-in, update-in, condp

1:50 and imo your (let [b (f a), c (g b)]) forms would be cleaner as (-> a f g) threaded forms, but that's style

1:51 _ato: ossareh: heh.. was just about to type a reply to your mail. I think you might be being bitten by the way java strings share data

1:52 (slurp (stream agnt)) <-- loads whole JSON feed in as a string

1:52 ossareh: amalloy: I'm familiar with the assoc-in update-in, I'll take a look at the other two. TBH this isn't any type of long lived code - I just needed to work out the spread of employees..

1:52 _ato: when you take a substring of a java string, it doesn't copy the data, it just points at the original

1:52 so the "name" field you're hanging onto will probably hang onto the whole JSON file

1:53 ossareh: _ato: srsly?

1:53 _ato: yep, they do it for permformance, but it drives me insane sometimes

1:53 amalloy: ossareh, _ato: java strings are very sticky

1:54 ossareh: so the json itself isn't thrown away when I (read-json) ?

1:55 _ato: yeah. You'll want to explicitly copy any strings you hang onto. I think the copy structor should do it, so (let [name (String. ^String name)] ...)

1:55 ,(let [x "foo"] (identical? (str x) x))

1:55 clojurebot: true

1:55 _ato: so str won't do the trick

1:56 s/copy structor/copy constructor/

1:58 ossareh: I don't get it - where am I likely to be holding onto that json file?

1:58 the (:name co) bit in process-company?

2:00 _ato: yeah, so that gets passed into update-emp-range! and then: (assoc v name emp-cnt) which gets put into emp-ranges

2:00 http://fishbowl.pastiche.org/2005/04/27/the_string_memory_gotcha/

2:00 ossareh: I'm still reeling from the fact that read-json doesn't lose the json file. Or am I mis understanding you there?

2:01 _ato: read-json loses it, but the substring hangs onto its parent string's data, if you get what I mean

2:02 substring doesn't copy, it just holds a reference saying I am chars 37 to 49 of the-big-string

2:04 auser: can you subclass a module? I mean... can I have (ns a) and then (ns b :subclass a)?

2:04 or something like that

2:04 ossareh: auser: (ns) is a namespace - similar to a java package.

2:05 amalloy: auser: you can do some things like that, but not exactly that; since it's unclear what you want i'm not sure what to recommend

2:05 auser: well... I have a few clojure packages that will share a lot of functionality

2:05 ossareh: auser: if you have the directory structure project/src/a/b/c/core.clj - the ns would be (ns a.b.c.core)

2:06 the ns in core.clj that is

2:06 auser: it's event handlers, so I want to fire an event and have each handle their events differently, to be specific

2:06 ossareh: I know that, what should I call them, then?

2:06 in erlang, they would be modules

2:06 ossareh: auser: namespaces in clojure.

2:07 auser: k

2:07 amalloy: auser: i'd be inclined to have one "parent" namespace with the common functionality, and several namespaces that all depend on that one

2:07 auser: so they all (:use parent_ns), you mean?

2:07 amalloy: right

2:07 auser: yeah, that's what I was thinking after I typed the question

2:07 I think that's probably the way to go

2:08 ossareh: _ato: so that link does a great job of explaining the substring thing. Thanks. I'm not sure I get where I'm doing tha.... I get it!

2:08 auser: thanks amalloy

2:08 amalloy: auser: if you like you can pretend :use is :subclass :)

2:09 auser: lol

2:09 ossareh: _ato: so as a result of not copying it I'm holding onto all the references

2:09 lancepantz_: auser: have you looked into protocols?

2:09 that's my kneejerk

2:09 amalloy: haha

2:09 ossareh: even when I throw it into the map

2:09 auser: no, protocols?

2:09 _ato: ossareh: yep, exactly

2:09 ossareh: OMG

2:09 amalloy: auser: they are the magic fairy dust you wave on things to make everything right, except it rarely works that way

2:10 lancepantz_: http://clojure.org/protocols

2:10 auser: uh oh

2:10 am I going to toss some cookies?

2:10 _ato: ossareh: huge JVM gotcha that bites everyone who ever processes large data sets

2:10 lancepantz_: hahaha

2:10 amalloy: haha no, protocols are cool

2:10 auser: oh yeah

2:10 I've seen this in the clojure book

2:10 ossareh: auser: Joy of Clojure made the them far more approachable than /protocols

2:10 auser: looks super neat

2:10 amalloy: i've just found that i always try to use them as a substitute for interfaces, and they're not

2:10 lancepantz_: how are they not?

2:10 auser: do they do "pattern matching?"

2:11 ossareh: auser: from my very rudimentary understanding of clojure I think amalloy is right though.

2:11 auser: hm, guess I'll have to see how they work

2:11 amalloy: hiredman said something about protocols the other day that really helped me though

2:11 lancepantz_: i've only implemented one into production code, so i'm not the expert

2:11 ossareh: auser: they're ways of defining how something should work and you can later supply implementations for how they do work. like gen_server, etc.

2:11 auser: ah

2:11 cool

2:12 lancepantz_: you can extend them

2:12 ossareh: auser: a lot is lost in that description from me - on both sides of the equation.

2:12 auser: yeah

2:12 <~ confused

2:12 but looking in my pdf

2:13 ossareh: _ato: I'd not considered 50k requests a large data set :)

2:13 auser: to no avail though

2:13 lancepantz_: stuart halloway had a good screencast on them

2:13 i should say, presentation that was recorded

2:13 auser: http://vimeo.com/11236603 ?

2:13 _ato: ossareh: eh, true. "medium" then. medium = larger than RAM ;-)

2:13 lancepantz_: thats the one

2:13 auser: swweeeeetttt

2:16 ossareh: _ato: nice, so as a result of that change 4x more data processed before the OOMs start

2:17 _ato: heh, I guess eventually you are going to be legitimately running out of memory

2:18 you know how up the heap size right? java -Xmx500m for 500MB max heap

2:18 ossareh: _ato: yup, cheers. - got a clue on how to do that for lein swank?

2:19 _ato: I think you can put it in project.clj somehow.. just a sec

2:20 ossareh: :jvm-opts

2:20 _ato: ah yep

2:21 ossareh: I love how thorough technomancy is!

2:22 _ato: potentially stupid question here - the fact I'm passing the number through from the slurped json isn't going to be doing the same thing is it? this is limited to just strings.

2:25 amalloy: ossareh: yeah, not sure what you mean by passing the number through, but of the core java data structures only strings do interning afaik

2:32 ossareh: heh - think my wifi router *hates* what I'm doing

2:33 _ato: yep, safe with numbers, just strings that have that problem

2:38 ossareh: _ato: cheers - this has been an interesting arc in my "simple report" :)

2:41 amalloy: how does with-open work? if i generate a lazy sequence of calls to reading from a with-open resource, and realize the seq outside of with-open, is that a bad thing to do?

2:41 chouser: yes, bad

2:41 amalloy: boo

2:41 _ato: with-open just expands to a (try ... (finally (.close foo)))

2:41 amalloy: well, +1 for realizing the potential for problem before just doing it, this time

2:41 chouser: the file will be closed, so if you then realize an item that requires reading from the file, you'll get an exception

2:42 amalloy: yep. good catch. :-)

2:42 _ato: the lack of some sort "lazy" file handles mechanism is very annoying. One thing refcounting instead of GCing is very nice for

2:43 chouser: & (with-open [r (java.io.StringReader. "hello")] (take 5 (repeatedly #(.read r))))

2:43 sexpbot: java.lang.IllegalStateException: Var clojail.core/tester is unbound.

2:44 chouser: hm

2:44 amalloy: *blink*

2:44 chouser: ,(with-open [r (java.io.StringReader. "hello")] (take 5 (repeatedly #(.read r))))

2:44 clojurebot: java.lang.RuntimeException: java.io.IOException: Stream closed

2:44 chouser: there you go

2:44 ,(with-open [r (java.io.StringReader. "hello")] (vec (take 5 (repeatedly #(.read r)))))

2:44 clojurebot: [104 101 108 108 111]

2:44 amalloy: chouser: (repeatedly 5 #(.read r)), btw

2:44 chouser: d'oh

2:44 thanks

2:45 amalloy: i'll send Raynes the sexpbot/clojail hiccup

2:46 helped a bit with clojail, but not on that part

3:04 auser: here's a dummy question, but is there a way to get the name of the current namespace?

3:09 _ato: auser: (ns-name *ns*)

3:10 auser: ah thanks :)

4:27 bytecolor: woo hoo, I could answer the last question. That's progress.

4:28 cpfr: bytecolor, clojure-quiz?

4:29 bytecolor: cpfr: who wrote that? I've been wanting to try that out. hell of a good idea

4:29 cpfr: no idea

4:30 bytecolor: it's based on (doc foo), no?

4:32 that, to me is the next gen in language learning. Some flavour of game, mixed with hard questions. It can't be easy, else every retard would get it.

4:33 retards don't push the envelope.

4:39 auser: so... I'm interested in writing an event driven system... um... similar to gen_event (in erlang)... anyone here have an experience writing events in clojure?

4:39 just out of curiosity, really

4:40 amalloy: bytecolor: fliebel is responsible for clojure-quiz, i think

4:40 (though i totally take some credit for steering him in that direction)

4:42 auser: you might be interested in...what is it, that i/o library with channels and siphons and whatever? those probably have some similarity to events

4:43 auser: aleph

4:43 or lamina? i guess aleph uses lamina. lamina claims to be an event-driven data structure for clojure

4:43 either way, i'm off to bed. enjoy

4:46 auser: oh good links!

4:46 hm, event-driven data structure

4:46 off to be google-informed

4:46 bobo_: links?

4:50 auser: that's perfect amalloy_ thanks!

4:58 Unlogic: Hello guys! I wonder if you can help me with the following question: how to implement multimethods in pure Clojure withous using Java interop? I need this for research reasons only, so performance is not an issue

5:18 kotarak: Unlogic: atom holding map of dispatch values to method functions. function which invokes the dispatch function on the arguments, finds the appropriate method function from said map and invokes it. another function ("defmethod") which swap! in a new map with the given method function assoc'd to the given dispatch value.

5:23 Unlogic: kotarak: thank you! i first thought just like that, by I still want the multimethod be a macro so you can call it just like normal function

5:27 kotarak: well, this is still possible if i define an atom and a function separately, but i don't want to pollute the namespace

5:53 kotarak: Unlogic: Here is a rough sketch. http://paste.pocoo.org/show/303462 Haven't tested it. But only one function is introduced. The dispatch-map atom is attached to the Var metadata.

5:53 Unlogic: so minimal namespace "pollution"

5:53 Unlogic: Untested, though. But I think you get the idea.

6:29 djino: hi, is there anything particulary wrong with this code? http://ideone.com/dRHz8 , I am getting out of memory etc. If I try to access for example (nth (p) 2000) on this sequence.

6:54 mfex: djino, add a (doall ...) around the (remove ...)

6:59 hmm, that only turns a stackoverflow error into the out of memory error

6:59 djino: mfex: hmm, well since the seq is infinite, doalling it wouldnt work

7:17 mfex: I still think there are eventually to many nested lazy-seqs from remove because each previous item adds another, indeed doall isn't an options so it's best to check one of the existing implementations

8:07 fliebel: Can someone give me a hand with java.io stuff? For fastcgi-ring I need to convert an output stream to an input stream. I googled it, and it seems the 2 most common approaches are using a byte array or PipedInputStreams. The problem is that the piped approach seems superior, but requires 2 threads. I'm not sure how t implement that in here: https://github.com/pepijndevos/fastcgi-ring/blob/master/src/fastcgi_ring/core.clj#L27 ot that currently at l

8:09 I had 2 piped streams defined around line 27, but that got me into a deadlock, even though the rwites logically occur before the read, at least until the buffer is full, which I think is the problem.

8:42 Raynes: chouser: Fun bug you found there.

8:42 kumarshantanu: hi, is it possible to create a lazy function given a regular regular function?

8:42 s/regular regular/regular/

8:42 sexpbot: <kumarshantanu> hi, is it possible to create a lazy function given a regular function?

8:42 fliebel: kumarshantanu: ??? lazy-seq?

8:43 kumarshantanu: fliebel: lazy-seq generates a seq when realized?

8:43 fliebel: kumarshantanu: What ind of lazy, and what is a 'general' function?

8:43 kumarshantanu: (defn foo [] (println "Called foo") 10)

8:44 how can I create a lazy-version of foo?

8:44 fliebel: kumarshantanu: lazy-seq only evaluates the expression when you consume the seq. ##(doc lazy-seq)

8:44 sexpbot: ⟹ "Macro ([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls."

8:45 fliebel: kumarshantanu: foo doesn't really produce a seq, does it?

8:45 But you could have a look at repeatedly and iterate.

8:45 kumarshantanu: fliebel: no

8:46 fliebel: kumarshantanu: What is it that you want, then?

8:46 kumarshantanu: I need to lazily evaluate a function

8:47 pass around the lazy fn until required to be eval'ed

8:47 fliebel: kumarshantanu: Define lazily, if the function is not a seq. Maybe future is what you want then?

8:47 Raynes: chouser, amalloy_: I think the problem here is that I may not be realizing the lazy-sequence created by repeatedly and take before I leave the proper scope. Very nice catch. I'll deal later.

8:48 kumarshantanu: fliebel: perhaps I am being ambiguous

8:49 I want to wrap function name and args

8:49 and pass them around until I need to execute

8:49 fliebel: kumarshantanu: Then partial or an anonymous function is what you want I think.

8:50 kumarshantanu: fliebel: yeah! curried as a no-arg function

8:50 thanks

8:52 fliebel: but is there an equivalent of partial that takes no args for the fn?

8:52 fliebel: kumarshantanu: #(the-fn with some args)

8:53 kumarshantanu: fliebel: Oops! Sorry I am embarrassed -- I think "comp" is serving this purpose

8:54 fliebel: &((comp inc inc) 2)

8:54 sexpbot: ⟹ 4

9:02 G0SUB: kumarshantanu

9:03 kumarshantanu: GOSUB: hey

9:03 G0SUB: or maybe this is the handle

9:03 G0SUB: kumarshantanu: yep :)

9:04 kumarshantanu: trust your editor, err client to do the autocomplete.

9:04 kumarshantanu: G0SUB: I use Pidgin (no joy)

9:05 * G0SUB gives kumarshantanu a better IRC client.

9:07 G0SUB: kumarshantanu: too much Java programming has made you a masochist.

9:07 kumarshantanu: G0SUB: LMAO! what client do you suggest? better if cross-platform (currently have to use Windows 7)

9:08 G0SUB: kumarshantanu: if you are on Emacs, try RCIRC or ERC. XChat works fine on Windows too.

9:08 kumarshantanu: G0SUB: downloading mIRC and X-Chat

9:09 G0SUB: kumarshantanu: XChat please. mIRC is to last century.

9:09 s/to/so

9:09 sexpbot: <G0SUB> kumarshantanu: XChat please. mIRC is so last century.

9:09 G0SUB: wtf!

9:09 ztyu: hey!

9:09 * Raynes always smiles when people notice that.

9:09 ztyu: hi

9:09 .

9:10 G0SUB: Raynes: dude, you are breaking IRC's tradition with that overloaded command.

9:10 Raynes: please don't extend a protocol that you don't own! :)

9:10 ztyu just donated to the Clojure project. Cheers to ztyu!

9:10 Raynes: kumarshantanu: If you already use Firefox, Chatzilla is an okay option as well. However, it isn't worth running on XULRunner if you don't. I use XChat. Very satisfying.

9:11 G0SUB: But... but... :p

9:11 ztyu: i donate to clojure , to just thank to G0SUB

9:14 shantanuk_: hello world (from XChat)

9:14 G0SUB: sexpbot: tell ztyu about clojure

9:14 Raynes: will that work? ^^^

9:14 Raynes: No.

9:15 $learn clojure Clojure is a programming language: http://clojure.org

9:15 sexpbot: My memory is more powerful than M-x butterfly. I wont forget it.

9:15 Raynes: $whatis clojure

9:15 sexpbot: clojure = Clojure is a programming language: http://clojure.org

9:15 Raynes: That's the closest you can get right now.

9:15 I've got plans to improve that system.

9:15 G0SUB: Raynes: hmm. how do I add the tell via PM feature?

9:16 Raynes: Like you tried to above?

9:16 G0SUB: Raynes: yes.

9:16 Raynes: That probably belongs in the whatis plugin. It shouldn't be exceedingly difficult. Just need a tell command that does what you want.

9:17 G0SUB: Raynes: great.

9:17 Raynes: G0SUB: http://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/whatis.clj This is what you're looking for.

9:17 G0SUB: Raynes: btw, we met at the Conj, but rarely got to talk.

9:17 Raynes: G0SUB: Right, we ate together at lunch, didn't we?

9:18 G0SUB: Raynes: I think so.

9:20 Raynes: where is the PM functionality of the bot? "$tell" will PM the recipient with the answer (if it knows about it)

9:21 Raynes: G0SUB: You just want to send a message where the channel is the nickname of the user you want to PM. You would do something like (send-message (assoc com-m :channel (first args)) "some text")

9:22 G0SUB: Raynes: you are right. are you accepting patches?

9:22 Raynes: Always

9:22 G0SUB: Raynes: OK. I will send you a pull request in a while.

9:23 * G0SUB shuts down his Erlang node & starts up Clojure

9:23 Raynes: Nice. If you run into any problems, let me know. Recently added some multiprotocol support and broke+fixed everything. ;)

9:23 G0SUB: Raynes: heh

9:24 Raynes: I use the word 'fixed' loosely, of course.

9:47 G0SUB: Raynes: sent a pull request. please accept if the patch is OK.

9:47 Raynes: I looked at the sexpbot code for the first time today. very nice work!

9:51 Raynes: G0SUB: I'll check that out in a few. :)

9:51 G0SUB: Raynes: sure. take your time.

9:52 Raynes: Looks good.

9:53 I think that brings the number of sexpbot contributors to a explosive 6. :>

9:56 G0SUB: Raynes: cool!

9:56 Raynes: is there a TODO list that I can target for some more serious work?

9:56 Raynes: G0SUB: Did you actually test this?

9:57 G0SUB: Raynes: yes. in my own whacky way. please use your own testbed to be sure.

9:57 Raynes: It's simple enough that I'm pretty sure it works just by looking at it. My testing just consists of running the bot and running the command. :p

9:57 I was just curious as to whether or not you got the bot running.

9:58 Mostly just to confirm that the default configuration isn't borked.

9:59 I'm lazy about testing in a 'clean' setting, like a user would be on their first run.

9:59 Well, I'm just lazy in general. ._.

10:00 There isn't any TODO list right now.

10:00 It's mostly just amalloy and I working on it, so we tend to keep TODO lists in our head. :p

10:00 I'm sure I could think of a few low-hanging things.

10:01 G0SUB: Raynes: please write down all the to do items in a file and put it in the repo for others :)

10:01 Raynes: starting the bot was not hard at all.

10:01 Raynes: Great

10:08 G0SUB: Raynes: do I have to do anything else to get the patch accepted?

10:09 Raynes: G0SUB: Nope. I've already pulled it into master. Just haven't pushed yet.

10:09 G0SUB: Raynes: oh, great. many thanks!

10:14 Raynes: G0SUB: A git shortlog tells me that you're the 7th contributor.

10:14 Pushed to master.

10:14 G0SUB: Raynes: interesting.

10:17 Raynes: G0SUB: There is a todo list in master now. I put a bit of low hanging fruit in there that you might be interested. amalloy and I will compile a more comprehensive list later.

10:18 G0SUB: Raynes: awesome! you rock.

10:18 Raynes: <3

10:25 studybot_: what is the difference between n and (int n)?

10:33 sorry

10:33 anybody here?

10:39 kumarshantanu: studybot_: any example?

10:40 studybot_: http://paste.lisp.org/display/69952

10:40 I find this code through stack-overflow

10:40 it seems to be written by rich hicky

10:41 kumarshantanu: ,(type (long 10))

10:41 clojurebot: java.lang.Long

10:41 kumarshantanu: (type (int 10))

10:42 ,(type (long 10))

10:42 clojurebot: java.lang.Long

10:42 kumarshantanu: ,(type (int 10))

10:42 clojurebot: java.lang.Integer

10:42 kumarshantanu: so, int coerces a number into an int

10:43 studybot_: yeah

10:43 kumarshantanu: ,(type (int (short 10)))

10:43 clojurebot: java.lang.Integer

10:43 studybot_: ,(type 3)

10:43 clojurebot: java.lang.Integer

10:43 studybot_: ahha

10:43 I see

10:43 so there's no difference, right?

10:43 kumarshantanu: ,(type 55325327815637163912639129)

10:43 clojurebot: java.lang.ExceptionInInitializerError

10:44 kumarshantanu: ,(type 553253278156371639)

10:44 clojurebot: java.lang.ExceptionInInitializerError

10:44 kumarshantanu: ,(type (long 553253278156371639))

10:44 clojurebot: java.lang.ExceptionInInitializerError

10:44 kumarshantanu: ,(type (long 5532532781))

10:44 clojurebot: java.lang.ExceptionInInitializerError

10:44 kumarshantanu: ,(type (long 5532532781))

10:44 clojurebot: java.lang.ExceptionInInitializerError

10:44 kumarshantanu: ,(type (long 55325))

10:44 clojurebot: java.lang.Long

10:45 kumarshantanu: ,(type (int (long 553253278)))

10:45 clojurebot: java.lang.Integer

10:45 kumarshantanu: ,(type (int 553253278))

10:45 clojurebot: java.lang.Integer

10:45 kumarshantanu: ,(type 553253278)

10:45 clojurebot: java.lang.Integer

10:45 kumarshantanu: ,(type 55325327875843)

10:45 clojurebot: java.lang.ExceptionInInitializerError

11:21 jk__: technomancy: ?

11:47 $seen technomancy

11:47 sexpbot: technomancy was last seen talking on #clojure 12 hours and 26 minutes ago.

12:48 jk__: is this considered bad form? http://pastebin.com/6B1TWWXP

12:48 the call to setup() returns void, as does the call to setAuthenticationManager.

12:50 the function actually returns a usable repository, not a factory. bad name

12:50 chouser: I would use _ instead of x since you don't care about that value

12:50 or just move the call to setup out to before the let

12:50 jk__: ok

12:51 but having one function call after another if an individual call is just used for side effects is ok?

12:51 i mean, no more idiomatic way to do it?

12:51 chouser: not that I can think of

12:52 jk__: ok thanks. just trying to learn good style as i'm learning the language

12:52 chouser: it's ok to rely on each 'let' value being evaluated in order, and to use locals created in previous pairs

12:52 jk__: yes, i've seen that a lot

12:52 chouser: an also ok to rely on the body of a fn and the body of a let being "implicit do's" that will also happen in order

12:53 jk__: ok. thanks very much for the feedback

12:53 chouser: it's worth trying to isolate code that's stateful and messy like this, imo

12:54 but no better way to do it in general.

12:54 jk__: yes that's what trying to do. isolate it. i think this will come up again and again using java interop

12:55 chouser: yes. some java libs are pretty clean -- immutable value objects, side-effect-free methods, etc. Not much value in isolating usage of those

12:56 but if you can provide a function that does mutable stuff internally (because it has to) but presents a clean functional interface to the rest of your code, that's a real win.

12:56 jk__: that's the idea i'm going for

12:57 kotarak: I think the let* behaviour of let is a feature and guaranteed.

12:57 jk__: kotarak: what does that mean? the let* behavior?

12:58 kotarak: jk__: In Scheme there is let, let* and letrec. The difference between (let [a 1 b a] ..) and (let* [a 1 b a] ...) is that a in the first comes from the environment, while in the second is 1 from the first let pair. In Clojure there is only "let*": the let we know.

12:59 jk__: so you can rely, that (let [a (f1) b (f2)] ..) does first f1, before f2 is called.

13:00 jk__: kotarak: ahh, I see. I'm new to Lisp in general and don't know Scheme . I understand what you're saying though. Thanks for explaining

13:01 so I guess with let* the evaluation is free to occur in any order

13:01 oops, i mean let

13:01 kotarak: jk__: In Scheme, yes.

13:01 jk__: (in scheme that is

13:01 :)

13:02 kotarak: one thing that really helps a lot in clojure for us newbies is the fact that there are a lot of very knowledgeable people here who are quite willing to help

13:03 kotarak: jk__: I remember rhickey stating in the ancient days, that he doesn't see the benefit of two let forms and that you in usually want let* anyway. So it is the default for Clojure's let and - I think - it is save to rely on this fact.

13:04 jk__: Yup. Listen to rhickey, chouser, cgrand, cemerick, lpetit, ... :) Treasure chest here. :D

13:04 jk__: kotarak: i see. without any experience it's hard to say, but it's not inconceivable that somebody would want the other style of let. i guess that's what macros are for :)

13:05 kotarak: jk__: A noticeable exception to the []-binding forms (let, with-open, ...) is binding. binding in fact works like the Scheme let.

13:09 raek: you can do the other let with let and destructuring: (let [[a b] [b a]] ...)

13:10 so in clojure there is little need for having two...

13:12 kotarak: (defmacro let+ [bindings & body] `(let [~(vec (take-nth 2 bindings)) ~(vec (take-nth 2 (next bindings)))] ~@body))

13:12 Raynes: G0SUB: Actually, you're the 8th. I forgot about ninjudd's one (count 'em, one) commit.

13:14 ninjudd: Raynes: one commit to what?

13:14 Raynes: ninjudd: sexpbot

13:15 You have one commit.

13:15 ninjudd: i also wrote the logging code, though you committed it, right?

13:15 Raynes: Of course, you also co-wrote the logger plugin, but we mostly exchanged that over gist and irc.

13:15 Yeah.

13:15 You wrote the logging code and gisted it, I fixed the logging code and committed it. We're a team. <3

13:15 ninjudd: so really it is two

13:16 Raynes: Yup. I just robbed you.

13:16 ninjudd: like I robbed lrenn :(

13:16 Raynes: :(

13:17 ninjudd: so he has 0 cake commits instead of 1

13:26 amalloy: Raynes: mind if i pull in the $tell commit to a side branch, remove some code duplication, and bring it back to master?

13:29 G0SUB: that's your commit, right?

13:41 miltondsilva: Hi, can somebody help me with this? http://pastebin.com/ps2A8Ez9

13:55 kotarak: miltondsilva: This is a gross misuse of the agent system. You shoud use a dedicated thread. (.start (Thread. #(server-requests 8080)))

13:57 miltondsilva: also for serving the request: use a custom thread pool. Not an agent.

13:58 amalloy: G0SUB, Raynes: i see you did that already :P. either way i've tidied up whatis.clj now: http://is.gd/izw2O

14:29 LauJensen: kotarak: That looks like a future to me

14:45 mibnk: hi just new to clojure and i have a fast question how can i execute more than one sentence inside an if form

14:45 something like this

14:46 (defn a [x] (if (> x 0) ((println "Hello") (println "World"))))

14:46 LauJensen: ,(if (odd? 3) (do (println "one") (println "two")) "its not odd")

14:46 clojurebot: one

14:46 bobo_: (do (println "hello") (println "world))

14:46 clojurebot: two

14:46 mibnk: thankyou

14:46 LauJensen: mibnk: But in that case, you might want 'when' instead of 'if'

14:46 ,(when (odd? 3) (println "one") (println "two"))

14:46 clojurebot: one

14:46 two

14:47 LauJensen: If there's not (else) clause, you get the (do) for free

14:48 mibnk: thanks again i was a little bit lost with that

14:55 amalloy: mibnk: incidentally, my experience with learning lisps was like "why do i have to type this dang (do) all the time, can't the language give me some sugar for something as common as doing more than one thing"

14:55 followed eventually by "hey, i realized i never use (do) anymore, because my programs don't have side effects and you don't need them otherwise"

15:02 djino: http://ideone.com/O5i0Q : How would I prevent this from blowing the stack?

15:03 mibnk: amalloy: I try to achieve that but some times is difficult

15:04 pdk: if you run iterate it's going to try to return everything in the sequence defined by the iterate form

15:04 in that case it's not just going to pass back the seq generator but instead the whole contents of the seq

15:04 amalloy: djino: try wrapping the remove with a doall

15:05 djino: amalloy: since iterate is infinite i can't, thats the problem i cant figure out : o

15:05 amalloy: pdk: he knows that; he's calling (nth (p)) and (take p)

15:05 djino: amalloy: if I had doall'd it it would try to realise iterate

15:05 amalloy: yeah, i see that now

15:07 mibnk: djino it works fine on my system

15:07 amalloy: have you looked at the implementation in c.contrib.lazy-seqs?

15:08 djino: mbink: Can you try it with larger indexes for nth?

15:08 mibnk: ok

15:09 djino: amalloy: well its not that i need a prime generator, just been playing and i stumbled upon this problem

15:10 amalloy: djino: sure

15:10 but c.c probably had a similar problem

15:10 their solution might be interesting

15:11 mibnk: djino: it blowed at 3800

15:11 djino: 3500 worked fine

15:11 amalloy: to me it looks like they're chunking it - where you're doing a (remove), they first (take n lst) so that they can doall

15:25 djino: well i guess this doesnt play nice with lazyness, a doall is fine however for a fixed size seq, thanks for the suggestions

15:29 kotarak: LauJensen: even a future feels a bit heavy-weight. it feels like waste powering up all the return value stuff for a thread which will never return....

15:30 LauJensen: kotarak: I'd say its fairly idiomatic and in the context of starting a server, it hardly adds any overhead

15:30 kotarak: LauJensen: it's not about overhead. It just feels like waste. Ugly like (dorun (map ...))

15:31 But that's maybe the premature optimiser in me.

15:37 amalloy: kotarak: you could optimize yourself by disabling the premature optimizer. see if that helps :)

15:37 Lajla: amalloy, you are my one true love.

15:40 amalloy: :)

15:40 jk__: i've been fighting this problem for about 2 hours now! http://pastebin.com/75yvycDQ is there some trick to passing nil as a particular type for the purpose of calling some java api?

15:40 amalloy: Lajla: and i live in san francisco, so regardless of your gender we could live happily every after

15:41 Lajla: amalloy, well, I don't.

15:41 THat's an obstacle.

15:41 fliebel, you live nearbye right?

15:41 YOu are my one true love henceforth then.

15:41 amalloy: jk__: maybe try (.getDir repo dir (long -1) ^Collection nil lst)?

15:42 ouch

15:42 jk__: line 11 should be "nil"

15:42 i mistyped that

15:42 amalloy: let me try that

15:42 amalloy: ^Collection is a type-hint, which comes reasonable close to a cast

15:45 jk__: amalloy: that syntax is wrong but i'm still fooling with it. was trying all sorts of type hinting earlier. the only way i ever made it call the right one is if i passed an actual instance of Collection (which I didn't want to do)

15:46 amalloy: &^{:tag Collection} nil

15:46 sexpbot: java.lang.IllegalArgumentException: Metadata can only be applied to IMetas

15:46 KirinDave: Price is wrong.

15:47 amalloy: &(let [x nil] ^{:tag Collection} x)

15:47 sexpbot: ⟹ nil

15:47 amalloy: &(let [x nil] ^Collection x)

15:47 sexpbot: ⟹ nil

15:47 amalloy: jk__: like that instead?

15:52 jk__: amalloy: no matching method found :\

15:54 amalloy: ok i give! i'm just going to pass an actual instance. i think the only diff is that the api will populate my collection rather than create one internally. in either case, the return value is a collection with the right stuff

15:54 i'm tempted to put that snipped in a groovy class and call that instead. took me like 2 seconds to do that in groovy :\

15:55 amalloy: this is svnkit i'm playing with, btw

16:05 amalloy: jk__: i think you have to type-hint the object you're calling on too, to make the method call be resolved at compile time (before it knows the object is going to be null)

16:06 (let [^Collection c nil] .getDir ^Whatever myobj c)

16:06 er, but with more parens :P

16:07 jk__: amalloy: lol man what in incredible PITA this has been thanks to the closeness of the API calls colliding with the dynamic typing. first time i had such a problem in my very short clojure career :D

16:07 i'll go back to that later. i want to get some code working right now

16:08 amalloy: thanks very much for the suggestions. i'll dig into that further a little later.

16:08 amalloy: that's one of those problems that isn't even satisfying to solve because it's just damn ugly!

16:08 amalloy: yeah

16:13 sivajag: hi everyone

16:14 Pie`: hlo sivajag

16:15 sivajag: does anyone know how to add git submodule to leinengen

16:21 never mind got it

16:21 we should checkout to "checkouts" folder

16:24 fliebel: Someone mentioned my nick way up? I'm not able to figure out what's it about.

16:27 amalloy: fliebel: Lajla was asking where you live, but just for fun

16:28 fliebel: amalloy: I believe them knows… roughly.

16:28 s/knows/knowses/

16:28 sexpbot: <fliebel> amalloy: I believe them knowses… roughly.

16:44 sivajag: so relieved that I can git submodules with Lein

16:44 :)

16:47 MayDaniel: rr

17:19 nickik: where to start with emacs and commen lisp?

17:24 LauJensen: nickik: Perhaps in #commonlisp ?

17:31 raek: I'm doing a macro that has multiple levels of syntax-quote

17:31 is calling gensym myself the best way to make a unique symbol that can span two syntax-quotes?

17:34 bmh: has anyone about used the QuickCheck port in ClojureCheck? If so, can you steer me to documentation?

17:42 kotarak: bmh: docstrings are the documentation

17:42 bmh: what problem do you have in particular?

17:42 raek: I believe it's the only way to span two syntax-quotes.

17:45 raek: yes, browsing thought the mail arhives, I come to the same conclusion

17:45 kotarak: thanks!

17:49 bmh: kotarak: I'll check out the source, thanks.

18:31 kotarak: I'm having a bit of difficulty generating lists of a particular length. My understanding of this is: (list <key generating function> <length generating function)

18:57 krumholt: can someone explain to me the difference between send and send-off? why shouldn't i use send on blocking io? if i make a thread wait with Thread/sleep should i use send-off?

19:08 arrummzen: I feel like being evil. How can I import all classes in a package... the import macro appears to require I enumerate all the classes I will use.

19:09 raek: krumholt: the actions of agents are processed by threads in a thread pool. clojure has two thread pools: one with fixed number of threads and one with a dynamic number of threads.

19:10 krumholt: if you send multiple blocking action to the fixed size thread pool, they will keep all other agents from doing work

19:11 (send = fixed size, send-off = unbounded size)

19:11 so, you should use send-off for an action that includes a call to Thread/sleep

19:13 krumholt: raek: unbounded size?

19:14 raek size of what?

19:14 raek: number of threads

19:15 krumholt: raek: ok thanks

19:16 raek: in the send-off case, no action will wait for a thread to become free. if there is no free thread, a new one will be allocated

19:59 arrummzen: Does Clojure support C++/Java style function overloading?

20:00 It seems to support "multimethods" but those seem to only work for overloading by argument type not argument type and argument count.

20:01 dnolen: arrummzen: multimethod are more general than that. They can overload on lots of things, including argument count.

20:02 arrummzen: with deftype/record and protocols you can do more traditional overloading on the type of the first arg and the arity.

20:06 arrummzen: I have this: (defmulti show-image (fn [& args] (map class args)))

20:07 But I keep getting errors relating to "wrong number of arguments"... I don't see why?

20:07 dnolen: arrummzen: what do your methods look like

20:08 arrummzen: (defmethod show-image '(BufferedImage String) [image display-name] ...) and (defmethod show-image '(String) [image-file-name] ...)

20:09 Clojure seems to believe the wrong number of arguments are being passed to (fn [& args] (map class args)) but shouldn't that function take any number of arguments?

20:11 dnolen: arrummzen: does your call to the method look like?

20:12 arrummzen: should maybe paste your code somewhere.

20:12 arrummzen: (ImageProcessing/show-image "032_0003.jpg") is the initial call.

20:18 dnolen: arrummzen: the problem is your dispatch values.

20:18 ,(= '(String) [String])

20:18 clojurebot: java.lang.RuntimeException: java.lang.Exception: Expecting var, but String is mapped to class java.lang.String

20:18 dnolen: ,(= '(String) [java.lang.String])

20:18 clojurebot: java.lang.RuntimeException: java.lang.Exception: Expecting var, but String is mapped to class java.lang.String

20:18 dnolen: erg

20:19 anyways that on my machine evaluates to false.

20:19 '(String) is a list with the symbol 'String in it.

20:19 arrummzen: replace '(x ...) with [x ...] for your dispatch values.

20:24 arrummzen: Well, that was one problem...

20:26 jtokle: How would you use datatypes for something analogous to: MyClass extends AnAbstractClass implements AnInterface?

20:27 chouser: jtokle: extending abstract classes is about implementation inheritence, which is not supported by deftype, defrecord, or reify. You could use 'proxy' though.

20:28 arrummzen: http://pastebin.com/R6AVc62d . I'm still getting the same error java.lang.IllegalArgumentException: Wrong number of args (1) passed to: ImageProcessing$eval1701$fn

20:29 dnolen: arrummzen: are you 1.2.0? What dev environment are you using?

20:30 arrummzen: 1.2.0, why does it work for you?

20:30 I'm using eclipse with counterclockwise as an environment.

20:31 dnolen: arrummzen: trying restarting your REPL

20:32 arrummzen: I recall that redefining multimethods as you go may have issues in 1.2.0

20:32 jtokle: chouser: Thanks. I guess what I want is different types with the same data fields but with different implementations of some protocol

20:33 I thought there might be a smart way to do this, other than writing a bunch of nearly identical defrecord statements

20:34 dnolen: hmm, is it possible to have a version of interleave that keeps going even if some sequences become exhausted?

20:34 well I mean I know it's possible. but is it possible to combine some standard functions together get that behavior.

20:36 weave might be a cool name for that fn.

20:36 arrummzen: dnolen: that was it.... after restarting the REPL it works. Thank you !

20:36 dnolen: arrummzen: np.

20:37 arrummzen: that issue is fixed in 1.3.0, not sure if it'll get backported tho.

20:50 DeusExPikachu: anyone know how code to obtain the cookies for a secure web session so, for example I could then use htmlparser to parse a page?

21:24 studybot_: ,(reduce #(if (even? %2) (+ %1 %2)) 0 (range 5))

21:24 clojurebot: java.lang.NullPointerException

22:21 rata_: hi

22:21 I need some help

22:21 I'm getting this error: GC overhead limit exceeded

22:21 is there a way to work around that?

22:22 perhaps some java command line option or something like that?

22:40 dnolen: rata_: increase the memory to the JVM ?

23:04 rata_: dnolen: I'm trying with that now :)

23:13 arrummzen: I have an odd Java method which takes a int or an Object. How can I tell clojure to pass it an int and not an Integer?

23:16 dnolen: arrummzen: in 1.2.0 you can cast to a primitive int with (int x)

23:21 arrummzen: dnolen: that didn't fix my problem, but thanks anyway =D

23:30 dnolen: actually, that doesn't even work in 1.2.0. (class (int 5)) shows java.lang.Integer

23:30 dnolen: arrummzen: class is just casting it back to Integer

23:32 arrummzen: are you calling a constructor or something?

23:32 arrummzen: I'm trying to use java.awt.image.ColorModel.getRed

23:32 dnolen: arrummzen: what's your call look like?

23:33 arrummzen: (let [rgb (. image getRGB x y) red (. colorModel getRed (int rgb)) ...

23:33 I want to call getRed(int pixel) but getRed(Object inData) is being called.

23:33 dnolen: arrummzen: try (.getRed colorModel (int rgb))

23:34 arrummzen: Same problem.

23:36 dnolen: you need to fix getRGB as well

23:36 it doesn't look like getRGB takes two arguments either, http://download.oracle.com/javase/1.4.2/docs/api/java/awt/image/ColorModel.html#getRGB(int)

23:37 arrummzen: oh different object

23:37 arrummzen: I'm on Java 6, not 1.4.2

23:37 dnolen: still, (.getRGB image (int x) (int y))

23:37 arrummzen: That call doesn't have the problem. It is the getRed one which causes the error.

23:39 dnolen: arrummzen: what is the exact error?

23:42 arrummzen: #<ClassCastException java.lang.ClassCastException: java.lang.Integer cannot be cast to [B>

23:42 The javadoc for getRed(Object) says : "ClassCastException - if inData is not a primitive array of type transferType " so I assume this is because the Object version is being called.

23:43 dnolen: arrummzen: I think it's trying to convert a primitive int into an array of bytes.

23:44 (.getRed colorModel (byte-array [(byte 1)])) ?

23:45 arrummzen: it can be done, hopefully someone else will chime in, but I gotta jet.

23:46 arrummzen: meh, I'm just going to use bitwise operations to extract the RGB components myself.

23:46 This is a typical example of Java making things to damn complicated.

23:46 dnolen: arrummzen: totally.

Logging service provided by n01se.net