#clojure log - Sep 05 2009

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

1:50 hiredman: ~sandbox

1:50 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

3:45 mathias: I am trying to start swank separately to be able to connect to it from a separate emacs instance. I am able to start the swank server and even connect to it from emacs but I never get a lime buffer up. I can send things for evaluation from a normal emacs buffer but how do I get the REPL?

3:45 I start clojure like this: java -cp clojure/clojure.jar:swank-clojure clojure.lang.Repl

3:46 I then do: (require 'swank.swank)...

3:46 and lastly: (swank.swank/start-server "/tmp/slime02" :port 4005 :encoding "utf-8")

3:50 hiredman: clojurebot: how can you start swank seperately and connect to it from emacs?

3:50 clojurebot: with style and grace

3:51 hiredman: (sorry)

3:53 mathias: hiredman: ?

3:54 hiredman: not an emacser, so I don't know anything about swank

3:55 mathias: hiredman: ah

4:48 tomoj: aw he left

5:38 octe: can i refresh a package loaded with the use-method?

5:54 LauJensen: (use :reload-all ns)

5:56 @ octe

7:12 octe: LauJensen: thanks

7:14 LauJensen: np

10:34 slyrus_: rhickey: who was the author of the database book you mentioned near the end of the blip.tv talk? Andres Rieter? I think I'm spelling that wrong.

11:41 winterstream: I've been poking around clojure-contrib to see how test-is should be used. One thing I can't figure out is how to define a variable that can be used by all tests in a given namespace - that is, I only want to do the work of setting up the variable once.

11:41 Does anyone know how to do this?

11:46 Chousuke: hmm

11:47 there's the custom test hook, and fixtures.

11:51 winterstream: Chousuke: Thanks for the tip. I think I'm just going to take a shortcut now. I want to load a fairly large XML file for my tests, but I think I'll trim it down and include it as a string in my file.

11:51 kiras: i've been reading through "Programming Clojure" and i have a question about one of the examples. i'm sure it's really simple, but i'm new to clojure/lisp and somewhat confused. is it ok to show code here or is there a pastebin site that people generally use?

11:52 LauJensen: ~paste

11:52 clojurebot: lisppaste8, url

11:52 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

11:52 LauJensen: Go go go :)

11:52 kiras: ty :)

11:53 Chousuke: winterstream: you could also just use a function that loads it once and caches the result

11:54 winterstream: Chousuke: That would actually be the best way; I should learn how to memoize in Clojure anyway :).

11:54 Chousuke: hm

11:55 (doc memoize)

11:55 clojurebot: "([f]); Returns a memoized version of a referentially transparent function. The memoized version of the function keeps a cache of the mapping from arguments to results and, when calls with the same arguments are repeated often, has higher performance at the expense of higher memory use."

11:55 winterstream: So now I can be even lazier :). Thanks.

11:55 Chousuke: dunno if that works for functions with no arguments though :/

11:56 winterstream: If not, I'll just hack it by adding an unused parameter :)

11:56 kiras: http://paste.lisp.org/display/86614

11:57 my question has to do with line 3. in the book, it says "On line 3, the zero-argument body returns the concatenation of the basis values [0 1] and then calls the two-argument body to calculate the rest of the values."

11:58 LauJensen: So whats the question?

11:59 Chousuke: hm, the wording of the book is a bit weird.

11:59 kiras: so... does concat return values multiple times? or does it calculate the value once and then return it?

11:59 did i phrase that ok?

11:59 Chousuke: concat just concatenates two sequences

12:00 (lazy-seq-fibo 0 1) call produces a lazy sequence, so concat concatenates [0 1] with that sequence

12:00 LauJensen: ,(concat [1 2] [3 4])

12:00 clojurebot: (1 2 3 4)

12:00 LauJensen: clojurebot: compute!

12:00 clojurebot: Pardon?

12:01 kiras: ok. the way the book put it, it seemed like it was saying that concat returned (0 1) first, then called (lazy-seq-fibo 0 1)

12:02 at least, that's how it seemed to me

12:02 Chousuke: well, the (lazy-seq-fibo 0 1) gets evaluated when it's passed to concat.

12:02 but the result of it is a lazy sequence, so no *items* of the sequence are actually produced

12:03 kiras: well, i think i understand the lazy sequence part

12:03 Chousuke: and since concat is lazy too, no additional items will get computed until you have consumed the first two (the [0 1]) from the resulting sequence.

12:04 kiras: i was mostly confused about how arguments to concat were evaluated

12:04 oh

12:04 lol

12:04 i think i'm confused again...

12:04 Chousuke: arguments to functions are always evaluated.

12:04 kiras: ok

12:05 Chousuke: but the thing is, when evaluated, (lazy-seq-fibo 0 1) produces a lazy sequence, and unless you actually try to access items from the sequence (which concat won't do until it's needed), then no items will be computed

12:06 kiras: ok... so basically, if it wasn't lazy, it would produce the whole set of fibonacci numbers?

12:06 Chousuke: yes.

12:06 kiras: ok

12:07 LauJensen: kiras: I dont know if you already got this, but if not this might help: http://paste.lisp.org/display/86614#1

12:08 kiras: laujensen: ty, i'll look at that

12:12 LauJensen: i understand your example. at the moment, i think i'm ok with the recursion that i've seen, just the lazy sequence part is something i don't remember coming across before.

12:12 LauJensen: Just the simplest for of dispatching on argument count

12:12 Alright

12:12 kiras: ty

12:13 LauJensen: But you understand now?

12:14 kiras: well... sort of... i guess to really understand, i might have to look at how lazy-seq actually works with take and similar functions

12:17 LauJensen: ,(doc lazy-seq)

12:17 You can use that in your emacs repl when new functions come up

12:17 clojurebot: "([& 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."

12:18 Chousuke: hmm

12:18 ,(lazy-seq 5)

12:18 clojurebot: Don't know how to create ISeq from: Integer

12:18 kiras: ty, i was actually reading that just now lol

12:18 Chousuke: ah, right.

12:27 kiras: so a lazy-seq is "a Seqable object that will invoke the body only the first time seq is called..."

12:27 ?

12:28 LauJensen: Yes sir

12:28 kiras: so is it actually a sequence or does it just implement the ISeq interface? if that makes any sense?

12:30 Chousuke: ,(ancestors (lazy-seq [1 2]))

12:30 clojurebot: nil

12:30 Chousuke: huh.

12:30 ,(ancestors (class (lazy-seq [1 2])))

12:30 clojurebot: #{java.lang.Iterable clojure.lang.ISeq java.util.Collection clojure.lang.Seqable java.util.List clojure.lang.IMeta java.lang.Object clojure.lang.IObj clojure.lang.Obj clojure.lang.Sequential :clojure.contrib.generic/any clojure.lang.IPersistentCollection}

12:30 LauJensen: As I understood it in plain english, its a sequence of items where each expression is calculated when you eval it. Ex (take 5 (iterate inc 1)) will return (1 2 3 4 5), the next item is 6, but its not calculated, and 1-5 is cached for future calls.

12:31 Chousuke: take itself produces a lazy seq though

12:31 at least, IIRC :)

12:32 LauJensen: true

12:32 Chousuke: ,(take 2 (take 5 (iterate (fn [x] (do (println x) (inc x))))))

12:32 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$iterate

12:32 Chousuke: oops

12:32 ,(take 2 (take 5 (iterate (fn [x] (do (println x) (inc x))) 1)))

12:32 LauJensen: You forgot the offset

12:32 clojurebot: (1 2)

12:33 Chousuke: weird, nothing printed :P

12:33 LauJensen: its in the inferior lisp buffer :)

12:36 kiras: when you say "1-5 is cached for future calls" how long are those values cached?

12:38 Chousuke: kiras: until they're no longer referenced.

12:39 and they're referenced as long as you hold on to the head of a sequence that contains them.

12:39 kiras: Chousuke: so if they aren't stored in a variable or the such, they would be calculated again, right?

12:39 Chousuke: well

12:40 if you do (let [x (iterate inc 1)] [(take 5 x) (take 10 x)]) then on the first take call, the values get calculated, but for the second the cached ones would be used for the first 5 and then again calculated

12:41 kiras: that makes sense

12:41 LauJensen: kiras: but short answer is yes

12:42 Chousuke: the caching is why you don't want to do (def fibos (lazy-fibo))

12:42 kiras: hehe

12:42 Chousuke: because then if you did (take 10000 fibos) then it'd hold on to the 10000 fibos until the program ends (or until fibos is redef'd)

12:43 kiras: right

12:43 Chousuke: accidentally holding on to the head of lazy sequences is the main cause of out of memory errors in programs btw :)

12:43 kiras: lol

12:44 Chousuke: it's sometimes difficult to see if you're holding a reference to something or not.

12:44 kiras: i was wondering if that was a very common mistake or not

12:44 LauJensen: kiras: Chousuke does it all the time

12:44 Chousuke: especially because the clojure compiler currently does not nullify references after last use.

12:44 only at tail calls

12:48 kiras: i never really thought about that. do you mean that, if you were to do (def fibos (lazy-fibo)) and store a lot of numbers in there, used them once and then never used them again, it might be possible for the compiler to know the fibos was never going to be used again and set it to null?

12:48 Chousuke: nah, not that.

12:48 I meant local references

12:49 LauJensen: kiras: As it is now, that reference would be kept until program termination

12:50 Chousuke: eg. (fn [x] (let [foo (do-something (drop 100000 x))] "the reference to x still exists here even though it's not needed")

12:51 if the compiler were smarted it could figure out x is not used after the do-something call and nullify the reference, but currently it doesn't do that.

12:51 kiras: LauJensen: seems like it would. i thought maybe Chousuke meant that someday the compiler might be able to tell and set it to null. would think that would be very difficult to do though.

12:51 Chousuke: smarter*

12:52 kiras: Chousuke: i see...

12:52 interesting

12:55 Chousuke: to get around that you need to do (fn [x] (letfn [(work [y] (let [foo (do-something y)] "no ref to x here"))] (work (drop 100000 x))))

12:56 because the (work ...) call is at the tail position the compiler knows x can't be referenced after the call and nullifies the reference

12:56 of course, the example is rather silly like that, but imagine that the strings returned were something more complex (possibly utilising foo, but not x)

12:57 LauJensen: kiras: With dynamic code (macros) I think its near impossible.

12:59 kiras: so do lazy sequences keep track of references to themselves and the parts of the sequence each reference is holding onto (pointing to?)? then when a variable that is using part of the sequence is deleted, the lazy sequence drops that part of the sequence from its cache? or is that handled outside the lazy sequence somehow?

13:00 Chousuke: kiras: the lazy sequence is like a linked list. it's made of smaller subsequences. :)

13:01 kiras: and each subsequence just caches its own value after it's computed.

13:01 the head of each subsequence that is.

13:02 tomoj: so if you're holding the head, the entire sequence computed so far is not gcable?

13:02 Chousuke: yes.

13:02 because there's a reference from the head to the second item, from the second item to the third, etc. until the last actually computed item

13:03 this might be oversimplified though, because you can have seqs that are just "views" to something that already exists fully in memory, like a vector.

15:01 fps: hello, could someone give me a hint on how to use the clj-record library? http://github.com/duelinmarkers/clj-record/tree/master/

15:03 I already compiled it, but I cannot find a jar to add to the classpath

15:09 Bercilak: for those of you using emacs clojure-mode, have you had any success using the clojure-update command?

15:10 I'm running into an error where it tries to run ant in the wrong directory, and I think it's a bug in clojure-mode.

15:11 cschreiner: I get an error with Git

15:11 but I've had no success using the clojure-update command

15:12 Bercilak: out of curiosity, what's the error?

15:15 cschreiner: just that Git cannot be found

15:16 I just left it, and continued with what I was doing before

15:16 there are a couple of things that don't work right in emacs, but I'll manage

15:18 like; code-completion, java-lookup, some problems with elisp formatting from swank etc

15:19 especially when doing (println "whatever") statements

15:20 Bercilak: hmm. I'm still in the process of switching to emacs from textmate, so I'm useless for those...

15:20 cschreiner: error in process filter: slime-dispatch-event: Elisp destructure-case failed: (:write-string "Whatever")

15:21 yeah, textmate, never seen much of that since going back to emacs

15:22 I tend to spend more time browsing elisp code than actually clojouring

15:23 I still need to understand the big picture though (re. emacs)

15:27 LauJensen: For those of you who are interested I'm launching a blog which pivots on Clojure but from a business relevant angle. You'll find it at http://bestinclass.wordpress.com

15:27 cschreiner: sure :-)

15:31 Bercilak: textmate is very approachable and snippets are simple to understand and damn useful

15:31 slime is so worth the switch though, and eventually I'll get the hang of emacs

15:31 clojurebot: slime is icky

15:31 Bercilak: heh

15:31 LauJensen: ~forget slime

15:31 clojurebot: I forgot slime

15:31 Chousuke: in the end emacs is more powerful than any other editor

15:31 it just requires some effort :/

15:32 cschreiner: I messed with the ergoemacs keybindings, but I returned to a blank slate

15:32 Bercilak: I always knew that I was going to switch to emacs or vim someday, so recently I set up a linux dev box and I've been doing all my work on that

15:32 cschreiner: better to build the system bit by bit with functionality I am really going to use

15:33 on another hand, the original keybindings are really hard on my old hands

15:33 Bercilak: ergoemacs looked interesting, it's nice to hear from someone who tried it out

15:33 Chousuke: maybe you just need a better keyboard :/

15:33 cschreiner: maybe

15:34 I need an original symbolics thing

15:34 Bercilak: hehe. I type in dvorak which makes a lot of these layouts kind of infuriating. They make sense in qwerty but not dvorak

15:34 Chousuke: I get by with caps lock as meta and cmd as control but still I think a better keyboard would help a lot :P

15:34 cschreiner: Well, I have three different apple keyboards here, and all of them makes my hand ache

15:35 I need to think more about typing less

15:35 Bercilak: maybe it's blasphemy, but I might switch to using vimpulse/viper for basic text movement and manipulation

15:35 elisp is where it's at for configuration though

15:35 cschreiner: care to share?

15:36 vimpulse, is that a vim thing?

15:36 Chousuke: viper.el is a vi implementation for emacs.

15:36 and vimpulse adds some vim things missing from viper.

15:36 I used viper but it didn't play well with paredit so now I'm trying to get used to emacs controls

15:37 cschreiner: any torough docs/intros?

15:37 I think the incremental search is the most important thing, and sexp navigation of course

15:37 Chousuke: paredit is awesome.

15:38 cschreiner: so few modifiers, so many modes

15:39 Chousuke: I don't even do much besides some barfing and slurping and sexp-killing with paredit but it's still an enlightening experience.

15:39 Bercilak: I just googled it... the paredit koolaid looks delicious.

15:39 * Bercilak will drink

15:40 Chousuke: I suppose if I learned to use the sexp navigation commands properly I would be one step closer to lisper nirvana

15:41 cschreiner: examining the pareditcheatsheet now http://www.emacswiki.org/emacs/PareditCheatsheet

15:43 Chousuke: one of the more common operations I do with paredit is deleting a let, and it's really very easy :/

15:44 or the reverse, wrapping some code in a let.

15:45 cschreiner: working with a non-us keyboard layout, everthing is fucked from the beginning

15:45 the intention of the original layout does not count

15:46 or, is non-existant

15:47 Chousuke: I find it usable on a Finnish layout.

15:47 though I think if I got used to a US one it would be better

15:47 cschreiner: Suomi?

15:47 Chousuke: it's not like I need ä ör ö when coding :/

15:47 yeah. :P

15:48 cschreiner: I would never have guessed it

15:48 Norway here

15:52 barfage and slurpage seems reasonable enough, never touched paredit- before

15:53 guess I've loaded it, but not bound any of the functions

16:21 quidnunc: cgrand: Is it possible to select a node whose child satisfies some predicate in enlive? I'm trying to do (select foo [[:font (has [:a (attr-contains :href "blah")])]]) but it doesn't seem to be working (the selector on the child works on its own.

17:19 cgrand: quidnunc: (select foo [[:font (has [[:a (attr-contains :href "blah")]])]])

17:20 'has takes a whole selector not a single selector-step

17:23 quidnunc: cgrand: Thanks.

17:26 cgrand: There is no way to get a parent of a node once I from the value returned by select right?

17:27 cgrand: not by select itself

17:30 look at zip-select: something like (zip-select (map xml/xml-zip nodes) [your selector here]) -- where xml is net.cgrand.xml

17:30 quidnunc: cgrand: One last question. Is it possible to use zip-filter.xml functions on the nodes returned by select?

17:32 cgrand: I wasn't clear about the difference between zip-select and select. What does zip-select do differently than select?

17:32 cgrand: zip-filter.xml may barf on xml comments (other than whitespace handling it's the main difference between clojure.xml and net.cgrand.xml)

17:34 'select returns nodes, 'zip-select returns locs (zips) to these nodes... and you can get the parent of a loc

17:35 once you have a loc you can freely use clojure.zip or zip-filters

17:37 quidnunc: Thanks cgrand.

17:37 cgrand: welcome

17:41 quidnunc: bedtime for me

18:11 cemerick: holy crap, I just grokked what subseq is all about

18:12 I had never read the docs -- thought it was over Indexed colls!

18:35 it'd be great to see PTM become extensible (so as to support building stuff like interval trees on top of it, etc)

18:44 emacsen: Why doesn't this do what I expect (knowing I clearly misunderstand): (reduce merge [{:a 10} {:b 20} {:c 30}])

18:45 Chousuke: ,(reduce merge [{:a 10} {:b 20} {:c 30}])

18:45 clojurebot: {:c 30, :b 20, :a 10}

18:46 Chousuke: isn't that what you want it to do?

18:46 emacsen: I didn't get that... let me try again

18:46 Chousuke: though you could also do (apply merge ...)

18:46 which probably internally uses reduce :)

18:46 but might not!

18:46 emacsen: lol, okay this was a slime problem with my display

18:46 Chousuke: ~def merge

18:46 emacsen: I was like "I must be going crazy... this should work"

18:47 Chousuke: hm, merge could be changed to use transients I suppose

18:48 emacsen: Chouske, okay here's a harder one... given another vector in mynode's content, this is invalid:

18:48 (map #({(:k (:attrs %)) (:v (:attrs %))}) (:content mynode))

18:48 I've tried that function on a single argument and it works, and (:content mynode) gives me back a persistent vector

18:49 Chousuke: #() is not fn

18:49 #({}) means calling {} with no parameters

18:49 I assume you meant to return the map

18:49 emacsen: isn't #() a macro for (fn ..)

18:49 Chousuke: no

18:49 #(foo) = (fn [] (foo))

18:50 emacsen: oh good point

18:50 right... okay this all makes more sense

18:50 hiredman: > ((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)

18:50 clojurebot: Any = 1

18:50 hiredman: :D

18:50 Chousuke: what.

18:51 Clojurebot does Scala now?

18:51 what blasphemy is this.

18:51 emacsen: oh that's scala?

18:51 hiredman: yep

18:52 via the simplyscala online repl

20:42 AWizzArd: Anyone awake who knows well about snapshots in Clojure? When I made a snapshot of a ref, and then the ref is mutated, will it use copy on write, as in forks?

20:46 hiredman: uh

20:46 what?

20:48 AWizzArd: when we make a snapshot of a map and have another thread changing the map, will then Clojure have to copy everything from the root to that leaf that gets mutated?

20:48 hiredman: mutating a ref is just assigning it a new value, te copy-onwrite or not depends on what the value is

20:48 AWizzArd: imagine a fork.. when the parent or child mutates data then the os will first copy the page, because everything is marked as read-only

20:49 hiredman: that has nothing to do with refs

20:49 AWizzArd: but mutating something in a tree may require to copy data from the root to that mutated leaf

20:50 hiredman: refs do not care, and don't know anything about what they wrap

20:50 and copy on write, etc, is the responsibility of the object wrapped by the ref

20:50 AWizzArd: i snapshot a ref (i call deref on it) and have a long running function that works on the object

20:51 hiredman: sure

20:51 AWizzArd: and now another thread mutates this object..

20:51 hiredman: then you are screwed

20:51 AWizzArd: then COW is happening under the hood?

20:51 hiredman: that is not how refs work

20:51 the value a ref holds should never mutate

20:51 AWizzArd: the ref is already forgotten after a snapshotted/derefd

20:51 hiredman: the ref can mutate and point to different values

20:52 AWizzArd: yes, let's forget the ref

20:52 hiredman: we cannot just forget the ref

20:53 if you wrap a mutable object like stringbuilder in a ref, the ref is useless

20:53 AWizzArd: yes

20:53 but say it is a clojure map

20:53 we call (foo @our-map)

20:53 hiredman: ok, clojure maps are implemented using structural sharing

20:54 AWizzArd: and while foo is running some other function bar mutates our-map

20:54 hiredman: aand Immutable

20:54 AWizzArd: you cannot

20:54 Immutable

20:54 AWizzArd: our-map sits in a ref

20:55 hiredman: doesn't matter

20:55 AWizzArd: and as you said, the structure is shared

20:55 so, it seems to us that we are working on a completely new object, while under the hood the same thing is mutated

20:55 hiredman: no!

20:55 AWizzArd: if our-map is 600 mb in size, then not each time those 600mb need to be copied

20:55 hiredman: no!

20:55 it is a new object

20:56 it just contains a pointer to another object that it shares some structure with

20:56 no mutation

20:56 AWizzArd: I know, they are not identical

20:56 Chouser: only the parts that are identical are shared

20:57 AWizzArd: when we call (foo @our-map) then at those point foo sees an immutable map, and all threads can see the same thing

20:57 similar to a fork

20:57 Chouser: the COW, if you want to think of it that way, happens the moment you do (assoc ...), regardless of whether a ref is involved or not.

20:57 AWizzArd: yes

20:57 hiredman: ,(let [a '(1 2 3) b (cons 4 a)] [a b]) ;shared structure, no mutation

20:57 clojurebot: [(1 2 3) (4 1 2 3)]

20:57 AWizzArd: this is what i want to know

20:57 does a COW happen, and how efficient will it be

20:58 some other thread runs the function bar which is doing transactions and alters our-map

20:58 hiredman: AWizzArd: it happens everytime you cons, conj, assoc, etc

20:59 AWizzArd: you cannot alter the map

20:59 *cannot*

20:59 Chouser: AWizzArd: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

20:59 hiredman: you can create a new map that shares structure with the old map, and place the new map into the ref

20:59 AWizzArd: yes

20:59 hiredman: but that in no way effects our-map

21:00 AWizzArd: Chouser: thanks for the link

21:00 yes hiredman I know, but I want to know how efficient it will be under the hood

21:00 consing is no problem

21:00 but changes in the middle might be

21:01 hiredman: ,(time (reduce conj [] (range 10000)))

21:01 clojurebot: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 13

21:01 "Elapsed time: 10.073 msecs"

21:01 Chouser: AWizzArd: changes on the end and in the middle are handled identically (for both vectors and maps)

21:01 clojurebot: for is not used enough

21:03 hiredman: AWizzArd: I recomend you read http://clojure.org/refs and http://clojure.org/state

21:04 AWizzArd: those pages don't explain much of how structure sharing is done

21:04 hiredman: correct, I am more concerned with you understanding of refs

21:04 AWizzArd: that is no problem at all

21:05 hiredman:

21:05 AWizzArd: only that i was not talking about them, and fortunately Chouser understood this and gave me an interesting link

21:06 mabes: any vimclojure users here? When I try to run ant in the plugin dir the build fails:

21:06 hiredman: are you following the directions in the readme?

21:06 mabes: http://pastie.org/607372

21:07 hiredman: I was following a screen cast.. I'll double check the readme to see if something has been updated

21:08 hiredman: you need to follow the build instructions for contrib

21:08 mabes: it is as if it can't find my clojure-contrib.jar but I defined it in the local.properites

21:08 hiredman: ok.. so I just don't run "ant"?

21:09 hiredman: mabes: run ant and check for a "Warning ..." and follow the instructions

21:09 mabes: hiredman: k, thanks for the help

21:10 AWizzArd: Chouser: when there is a big map and in a snapshot we have the k/v pair [:a 100] and some other thread dissocs it, then the snapshot still sees it. Will that operation require very much work under the hood, or is that still very efficient?

21:18 Chouser: AWizzArd: that has nothing to do with threads or refs. 'dissoc' will do what it does

21:19 hiredman: ,(time (let [v (vec (range 1e6))] (nil? (reduce #(assoc % %2 (* %2 3)) v v))))

21:19 clojurebot: "Elapsed time: 2788.926 msecs"

21:20 hiredman: 1e6 new vectors

21:22 AWizzArd: I will definitly need to look into that. It seems interesting to see how dissoc can remove elements in such a way that no snapshots will see it.

21:22 Oki, thanks you two and good night

21:22 hiredman: No!

21:23 dissoc doesn't effect any "snapshots"

21:23 the snapsots are immutable!

21:23 AWizzArd: exactly

21:23 they won't see the change

21:23 but when the structure is shared then some copying must happen, so that the snapshot is not a full copy but still can see the dissoc'd element

21:24 n8 n8

21:24 Chouser: yes, clojure's persistent structures are amazing.

22:04 emacsen: n8?

22:04 oh, night

22:29 hey technomancy

22:30 technomancy, how mature is your http abtraction library?

22:39 technomancy: emacsen: in terms of age/usage, not very

22:39 I wrote it in three days and haven't touched it yet

22:39 I've got like three patches contributed that I've been sitting on.</shame>

22:40 emacsen: I don't need any http library yet but soon will

22:40 and looking for something other than the java one, because I don't know Java, I find it distracting to go back and forth between documentation and programming styles

22:41 unless Clojure comes with another one that I've missed

22:44 technomancy: the java one certainly requires a lot of ceremony

22:45 emacsen: there's one in contrib too; uses agents

22:45 emacsen: that's a lot of overkill for what I'm doing

22:47 technomancy: if you're working with a restful API then I'd recommend the "resourcefully" namespace in clojure-http-client

23:05 nathanmarz: any monad masters around?

23:38 emacsen: technomancy, I am indeed working with a restul api

23:53 prospero_: how do I reset the state of the repl?

23:58 hiredman: what state?

Logging service provided by n01se.net