#clojure log - Feb 17 2010

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

0:16 technomancy: who's ready for a leiningen release tonight?

0:16 danlarkin: Choo CHoooooooooo

0:18 Raynes: Aw man!

0:18 More shit to download, excuse my french. ;)

0:18 technomancy: well, this will be the last time

0:18 somebody contributed an upgrade task

0:19 Raynes: technomancy: Has the "lein new project.clj is all a single line" bug been fixed?

0:19 Oh goody!

0:19 technomancy: Raynes: yup

0:19 Raynes: Yay! I'm all excited now.

0:19 Get to releasing, Doctor Phil!

0:19 technomancy: it's done with format now instead of pprint, which is lame but not as lame as a one-line project.clj

0:20 danlarkin: upgrade task? sounds non-friendly to packages

0:20 Raynes: danlarkin: Screw you and your packages. >:|

0:21 technomancy: danlarkin: yeah, you'll want to delete that for homebrew

0:22 but it does check to make sure the bin script is writable before it replaces it.

0:22 tomoj: what's this "packages"/"homebrew" thing

0:22 danlarkin: I'm gonna let that stew for a few days

0:24 technomancy: oh nice; github has a flash-less upload system now

0:24 so I can use that instead of my dreamhost

0:24 Raynes: I think somebody needs to relay the whole "git doesn't store binaries well" discussion to Ola Bini. Ioke's git repo is unbelievably huge.

0:25 technomancy: Raynes: pet peeve!

0:26 I will do it if I see him.

0:26 I got Charlie to agree to rewriting Duby's history in order to remove jars.

0:26 Raynes: I don't contribute to Ioke simply because downloading the repository on this dial up connection is either impossible, or just not worth the time it would take.

0:27 I might tether up my phone and pull it down over a day or two on a different computer over my phone's 4kb (I live in the middle of nowhere) connection.

0:27 technomancy: I tried to submit a patch to remove jars from the Katta project, but the patch was so big that Jira refused it.

0:28 underdev: hi! i'm trying to use clojure-test-mode, but i'm having a problem. If i run code directly in slime-repl, the testing works fine. If i try to C-c C-, from a buffer with the same code, i get an error: Unmatched delimiter: )

0:28 Raynes: I'm not really sure what makes Ioke's repo so big, but I know that some 300mb is too big for a year old language.

0:28 I mean, even Factor's repo is just 50mb.

0:29 underdev: anyone else encounter this problem?

0:29 technomancy: yeah, the problem is that even just removing a jar adds the size of the jar to the repo over again.

0:30 so a series of upgrades is going to be a disaster

0:30 underdev: no, sounds like the file has a typo

0:31 Raynes: I wish github showed repository and file sizes.

0:31 I'd like to know just how large this beast is.

0:31 underdev: backtrace 0: clojure.lang.LispReader.read(LispReader.java:180)

0:31 technomancy: which file?

0:32 Raynes: I know that whatever made the repo so big isn't there anymore, because the actual source without the history is only like 4mb...

0:32 http://github.com/olabini/ioke/tree/master/lib/build/ Or maybe I spoke too soon. Appears he is still keeping jars in there.

0:33 underdev: i had a little trouble installing clojure-test-mode from elpa, maybe its fubared

0:33 technomancy: underdev: no, it's probably the file containing the tests

0:33 scottj: I saw a screencast where clojure-test-mode highlighted the minibuffer (not just lines) in green/red when tests passed/failed and printed in minibuffer what was expected from test instead of just number of failures. anyone know what version of clojure test mode has those features?

0:34 technomancy: scottj: that'd be tcrayford's. it had a few issues I asked him to resolve before I merged

0:34 Raynes: And this: http://github.com/olabini/ioke/tree/master/bin/

0:35 underdev: technomancy: no, its balanced. its tiny

0:35 paredit confirms :)

0:35 technomancy: underdev: maybe it's a namespace that it requires then?

0:35 underdev: (use 'clojure.test)

0:36 that's it

0:36 (deftest testing-tests (is (= 2 2)))

0:36 scottj: technomancy: cool, those features will be nice

0:36 Drakeson: can I use leiningen to build/install/do-something-to a project that still only has a pom.xml?

0:37 technomancy: Drakeson: not currently

0:38 Drakeson: I see

0:39 scottj: does leiningen (or one of it's plugins) have anything for deployment?

0:40 technomancy: you guys are full of great ideas

0:40 but they are not in leiningen yet

0:40 think of it as an opportunity to contribute

0:41 Raynes: And be greatful that technomancy knows how to manage a github repo, and the size is quite small.

0:41 s/github/git/

0:43 scottj: I did spend like two hours trying to figure out why recent (since jochu's) swank-clojure M-. doesn't work correctly on Windows but failed miserably.

0:44 technomancy: windows is ... lightly supported. to put it generously.

0:45 heck, swank-clojure is lightly-supported when it comes down to it.

0:47 scottj: Other than M-. it worked pretty well I think. I think it's just got / hard coded instead of using File/separator maybe

0:48 technomancy: what are the specifics on badditude of single-segment namespaces?

0:49 is it just an AOT-time problem, or is it more general?

0:50 hiredman: I think current;ly it is mostly an aot issue, but because we wnat something like unified semantics, it is everyone's problem

0:50 technomancy: I'll buy that.

0:51 fewer awkward questions down the road

0:51 so lein new will spit out a foo.core ns instead of foo

0:56 hiredman: did you have a use-/bin/sh fix?

0:56 hiredman: the website updates via fork/pull request is a neat idea

0:56 technomancy: no :(

0:56 technomancy: hiredman: I stole that from the Seattle Ruby group

0:56 hiredman: probably a little late in the release cycle to change something like that anyway

0:59 underdev: having backtracked, when i try to install clojure-test-mode from ELPA, it complaims that swank-clojure.el already exists

1:00 anyone see that before?

1:00 technomancy: underdev: yeah... it's a known bug.

1:00 I've fixed it, but the package.el maintainer hasn't applied my patch yet. =\

1:00 underdev: how would i get your copy?

1:00 technomancy: underdev: http://github.com/technomancy/package.el

1:00 lots of other neat features there too. =)

1:01 underdev: technomancy: ty

1:01 !!!

1:01 technomancy: eh?

1:02 underdev: thank you

1:02 technomancy: oh, I thought the !!! was an expression of surprise or alarm.

1:02 underdev: appreciation

1:02 slyphon: "Ooooh!"

1:02 "no, 'Arrrgh!'"

1:03 technomancy: "no, it's more in the back of the throat..."

1:03 slyphon: :D

1:03 * slyphon tries to figure out how :exposes-methods works

1:06 Knekk: hmm, what's the simplest way to convert a char[] to a list of chars?

1:06 technomancy: Knekk: call seq on it

1:06 Knekk: ah, that's simple enough, thanks.

1:06 slyphon: seq and ye shall find

1:07 Knekk: brilliant, thanks

1:09 underdev: technomancy: w00t! thank you!

1:10 rock on

1:11 technomancy: should future versions of leiningen have code names?

1:11 danlarkin: yes!

1:12 underdev: DARN IT!

1:13 installed but still getting that stupid error

1:13 technomancy: look out for Leiningen "Amazing Horse" 1.2.0, coming to a git hub near you.

1:13 danlarkin: Heyooooooooooooooooo

1:14 technomancy: danlarkin: next time I call you I'm going to be thinking about the fact that "hey, pressing this button is going to cause the amazing horse song to be played. neat."

1:14 danlarkin: Hahah

1:15 technomancy: dun dun DUN: http://github.com/technomancy/leiningen/blob/1.1.0/NEWS#L3

1:15 danlarkin: well my phone's on silent most of the time, but it's the thought that counts

1:15 underdev: technomancy: do you think i would be better off using the esk? does that have clojure-test-mode integrated into it?

1:16 technomancy: underdev: it installs clojure-test-mode via elpa too.

1:16 can you try M-x toggle-debug-on-error?

1:16 maybe that could get you a stacktrace you could paste

1:18 slyphon: god *dammit*

1:19 * slyphon can't figure out how to call a protected method on a gen-class

1:19 technomancy: slyphon: you could try wall-hack

1:19 in contrib

1:19 * slyphon looks

1:19 technomancy: but I don't know much about it apart from it's an awesome name that sounds like it could be relevant to the problem at hand

1:19 slyphon: hah

1:20 hiredman: it got renamed

1:20 in master it is called reflection something or other

1:20 * slyphon is using 1.1.0

1:20 hiredman: excellent

1:21 slyphon: it seems like gen-class provides a way to do this, i just can't figure out the correct combination of :exposes-methods and :methods or something

1:23 hiredman: slyphon: what does :methods have to do with it?

1:24 slyphon: so, my superclass has a protected setName method, when i (defn -setName ...) and try to do (.setName inst "blah") i get No matching method found: setName

1:25 basically, i'm throwing stuff at the wall and seeing what sticks at this point

1:26 hiredman: :exposes {setName private-setName}

1:26 or something

1:26 slyphon: yeah :exposes-methods { setName setNameSuper }

1:26 is what i have

1:26 hiredman: actually, hypens are not a good idea

1:26 * slyphon pastes his code

1:27 hiredman: is this for pircbot?

1:27 slyphon: yeah

1:27 https://gist.github.com/8e989bdceba5fb2b5778

1:27 * hiredman recognizes that method name

1:27 slyphon: it's my first project with any language i'm trying to learn

1:27 hiredman: I think I wrote wall-hack-method for this purpose

1:28 slyphon: shouldn't :exposes-methods take care of this?

1:28 hiredman: I bet, but gen-class'ing sucks

1:28 slyphon: hahahaha

1:28 indeed

1:29 how about proxy?

1:29 hiredman: proxy?

1:29 clojurebot: proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.

1:29 slyphon: hah

1:29 hiredman: clojurebot uses proxy and wall-hacks setName

1:29 slyphon: ok

1:29 i'll look at that then

1:30 hiredman: the main issue I had with proxy is updating the methods can be a pain

1:30 technomancy: unless you've got a fair amount of java experience, you might want to avoid these kind of tricky interop things for a first project

1:30 Raynes: I think an IRC client will be my next adventure after I finally realize that I can't design an email client and give up.

1:30 slyphon: technomancy: well, true

1:31 technomancy: they're not nearly as fun and quick as a more functional project would be

1:31 Raynes: Oh joy. Ted Bundy is coming on. I like me some serial killer.

1:31 * Raynes watches

1:31 slyphon: i wrote a scalabot using PircBot, so i had something of a structure worked out

1:31 technomancy: but if you've got something that would be useful then that's a plus too

1:31 slyphon: yeah

1:32 this is always the hard thing, trying to figure out what's easy enough to mess with, the middle ground between a toy and something really substantive

1:32 hiredman: clojurebot: scala 1+1

1:32 technomancy: yup

1:32 slyphon: I had a lot of fun with mire: http://github.com/technomancy/mire

1:32 clojurebot: Int = 2

1:33 slyphon: hah

1:33 i'm afraid i'm not much of a MUD guy, but yeah

1:34 technomancy: oh yeah, I didn't actually *play* it. but it was fun to write. =)

1:34 slyphon: hahaha

1:34 hiredman: the java guys always cry if someone mentions pircbot

1:34 slyphon: oh yeah?

1:34 hiredman: they all like jerklib

1:34 slyphon: hah

1:34 hiredman: I think that is what it is called

1:34 * slyphon looks around

1:34 slyphon: pircbot is really not that awesome, it's just...i dunno, straightforward in a way

1:35 yeah, jerklib

1:35 http://jerklib.sourceforge.net/

1:35 hey, they have The Big Lebowski on their homepage, this *must* be awesome!

1:36 hiredman: :P

1:37 slyphon: ah, yeah, this is event based, which is what i always wind up having to shoehorn onto pircbot

1:39 hiredman: all of the proxy'ied methods in clojurebot end up calling a function that calls a multimethod trampolined in a future

1:39 * slyphon blinks

1:39 slyphon: you had me at "trampoline"

1:41 yeah, i was basically gonna convert the onFooBar method's arguments into a struct, then figure out some way of calling a bunch of listeners with that struct in a separate thread

1:42 future-cancelled? sounds rather...fatal

1:43 hiredman: (future (trampoline some-function arg1 arg2))

1:43 slyphon: why do you need trampoline there?

1:44 hiredman: some times some-function returns a thunk that calls some-function again with altered args

1:45 and some-function is a multimethod and recur only works with-in fns

1:45 slyphon: "a thunk" is a curried function?

1:45 hiredman: a thunk is a no arg function

1:45 slyphon: ah

1:45 hiredman: #(some-function arg4 arg5)

1:45 slyphon: gotcha

1:45 and trampoline ensures you don't consume stack

1:47 hiredman: right

1:47 slyphon: that's pretty damn cool

1:50 hiredman: the trampolining is neat

1:50 * slyphon is still trying to wrap his mind around the lack of objects

1:50 slyphon: it's very disconcerting

1:50 at first

1:50 hiredman: ~seen hiredman

1:50 clojurebot: hiredman was last seen in #clojure, 0 minutes ago saying: ~seen hiredman

1:50 slyphon: hah

1:51 hiredman: everything goes to that "plugin" and once it updates the tracking stuff it just adds an ignore me flag to the metadata and trampolines

1:52 slyphon: you're dispatching based on the metadata?

1:52 or that's something trampoline does?

1:52 (the ignore-me bit)

1:52 * slyphon should probably just go read the clojurebot code

1:52 slyphon: clojurebot: code?

1:52 clojurebot: I don't understand.

1:53 hiredman: each plugin defines a function that the multimethod uses to determine who gets a message

1:53 clojurebot: source

1:53 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

1:54 slyphon: oooh

1:54 xmpp

1:54 *FANCY*

1:54 :)

1:54 * slyphon tried some xmpp library and didn't get very far

1:54 hiredman: http://github.com/hiredman/clojurebot/blob/master/src/hiredman/clojurebot/seenx.clj

1:55 I wish there was a pircbot for xmpp

1:55 slyphon: yeah, all the jabber libs are as confusing as the jabber protocol

1:58 underdev: no one is using clojure-test-mode

1:58 i know this to be true

1:59 because on both ubuntu and windows, it throws the same error, but after dismissing the error the test results are shown in slime

2:00 if others were using it, this behavior would be know

2:00 n

2:12 i'm going to try fresh with the ESK

2:29 Raynes: Is there a standard way of shuffling the contents of a sequence?

2:29 Maybe something in contrib?

2:30 somnium: ,(doc shuffle)

2:30 clojurebot: "([coll]); Return a random permutation of coll"

2:30 Raynes: What do you know.

2:30 :|

2:30 somnium: c.c.seq-utils for 1.1

2:31 Raynes: Thaks.

2:31 Thanks*

2:31 somnium: Welome

2:40 Knekk: I am brain-dead... what's the easiest way to return a list with only the first instance of an element removed?

2:40 or any one instance of a particular element removed.

2:40 i.e. remove a \a from (\a \a \a \b \b \b) returns (\a \a \b \b \b)

2:41 maybe I should sleep on it

2:41 TheBusby: rest?

2:41 clojurebot: rest never returns a unicorn

2:42 TheBusby: ,(rest [1 2 3])

2:42 clojurebot: (2 3)

2:42 Knekk: rest only works if the element is at the first position, which is not always true

2:42 I could want to remove \b so that I have (\a \a \a \b \b) as the result

2:42 TheBusby: ahh, so for example (magic 2 [1 1 2 3 3]) would return [1 1 3 3]

2:43 Knekk: right

2:43 remove at most one instance from the list

2:43 TheBusby: er, take-while?

2:43 Knekk: ,(doc take-while)

2:43 clojurebot: "([pred coll]); Returns a lazy sequence of successive items from coll while (pred item) returns true. pred must be free of side-effects."

2:43 TheBusby: in this case, take-while not equal

2:43 Knekk: it would remove all instances, not just one

2:43 Chousuke: you might want to make a custom lazy seq for that.

2:44 _mst: maybe: (defn magic [elt coll] (let [[xs ys] (split-with #(not= elt %) coll)] (concat xs (rest ys))))

2:44 TheBusby: when-first?

2:44 _mst: (mostly untested ;)

2:44 Knekk: let me try that.

2:45 TheBusby: I heartily recommend the "clojure cheat sheet" for running these types of questions down. Not that I know the answer though :)

2:45 Knekk: _mst: very nice

2:46 _mst: hooray :D

2:49 Knekk: thanks all

2:49 fun with ProjectEuler problems, but time for bed.

2:51 vy: Considering (apply str (line-seq rdr)) expression, does str work eagerly in here?

2:52 Chousuke: yes.

2:52 strings are java Strings, so it has to :)

2:55 tomoj: is it evil to have a deftype with a field that points to an atom?

2:55 my use case: I need to implement a java interface with a single message that is called when a message comes in via xmpp

2:56 the deftype will implement that interface, and the method will push (swap!) the incoming method onto the queue

2:56 when I want to process incoming messages I can then pop (swap!) messages off

2:56 seems strange and weird, but maybe beautiful

2:57 somnium: :volatile-mutable and :unsychronized-mutable just got added as options to deftype fields in master

2:58 hamza: is reduce lazy?

2:58 tomoj: both of those sound scary

2:58 but I will take a look

2:58 hmm, I don't think they are for me

2:58 I want STM

2:59 somnium: putting an atom in a struct-map doesnt sound terribly evil

3:00 tomoj: great :)

3:01 somnium: is there any docs/discussion on how the &form &env implicit macro args work?

3:19 tomoj: is there a function version of @ ?

3:19 somnium: deref?

3:19 tomoj: ah, of course

3:19 thanks

3:34 hiredman: ,(macroexpand '@a)

3:34 clojurebot: (clojure.core/deref a)

3:34 hiredman: ,(read-string "@a")

3:34 clojurebot: (clojure.core/deref a)

3:46 bosie: how much slower is clojure compared to java? i googled but you find numbers from twice as slow to ten times as slow

3:46 Chousuke: it depends on what you're doing

3:47 hiredman: and how you do it, and how often you do it

3:47 bosie: algorithmic nature, data crunching

3:47 slyphon: hiredman: that's what she said?

3:47 * slyphon ducks

3:47 hiredman: clojurebot: do something

3:47 clojurebot: what should I do today, it is the weekend and all

3:47 hiredman: clojurebot: what timezone is that?

3:47 clojurebot: It's greek to me.

3:48 hiredman: right, europe, the worker's paradise

3:48 slyphon: hah

3:48 bosie: so the 10x is possible when you have a lot of data and have to calculate on it?

3:48 slyphon: bosie: "how much slower is it" has got to be one of the least-answerable questions in the abstract

3:48 Chousuke: I think you usually get 10x if you write straightforward, functional code with type hints.

3:49 bosie: ok

3:49 Chousuke: but you can get significantly better performance through optimisation.

3:49 bosie: slyphon: i know i know

3:50 hiredman: Chousuke: really?

3:50 (about the 10x)

3:50 slyphon: benchmark it!

3:50 Chousuke: hiredman: well, that's just my pessimistic estimate

3:51 hiredman: I haven't actually benchmarked it :)

3:52 only for now, straightforward code (using many lazy seqs, no transients or primitives, etc) is a fair bit slower

3:53 hiredman: rhickey's gvec in clojure is supposed to be the same speed as the java

3:53 Chousuke: I suppose. but I wasn't considering 1.2 yet :P

3:54 also it's not really number-crunching

3:55 bosie: so in short, I think you probably won't be able to get to 1:1 with java, but close enough for most purposes.

3:56 bosie: Chousuke: considering that a single process of the java version took 15 hours to process the data.... ;)

3:56 Chousuke: bosie: was it multithreaded, though?

3:56 bosie: Chousuke: single process, single thread

3:57 Chousuke: no

3:57 hiredman: pmap

3:57 Chousuke: right.

3:57 bosie: Chousuke: but if its 15 hours for java, multithreading doesn't help much for clojure either

3:58 Chousuke: well, assuming you can get clojure to even 2x java speed, then running it with 4 cores should help :P

3:58 bosie: i have 80 cores

3:58 hiredman: :D

3:58 bosie: but i will run the java code on those 80 cores too ;)

3:59 hiredman: have you seen the clojure widefinder write up?

3:59 somnium: bosie: have fun synchronizing the java :p

3:59 Chousuke: bosie: you might want to give Clojure a try though.

3:59 bosie: hiredman: this one? (http://clj-me.cgrand.net/index.php?s=WideFinder%202%20in%20Clojure%20(naive%20port%20from%20Ruby))

3:59 somnium: yea, no fun using threads in java

3:59 hiredman: http://meshy.org/2009/12/13/widefinder-2-with-clojure.html

3:59 ^- that one

4:00 the not naive one

4:00 bosie: Chousuke: i would like to, that's why i am reading the book

4:05 AWizzArd: Moin

4:10 bosie: thanks guys

4:24 cgrand: AWizzArd: hallo!

4:25 esj: morning all

5:32 powr-toc: What's the idiomatic way of taking everything except the last element from a sequence?

5:32 Raynes: Autodoc has a bucket load of deps.

5:32 the-kenny: powr-toc: butlast?

5:33 ,(doc butlast)

5:33 clojurebot: "([coll]); Return a seq of all but the last item in coll, in linear time"

5:33 powr-toc: the-kenny: cheers

5:33 I knew I'd seen something like that somewhere :-)

5:36 metaperl: ,(def x 5)

5:36 clojurebot: DENIED

5:36 metaperl: is it feasible to use the :test keyword of def() to set the allowable range of a variable?

5:36 bosie: the-kenny: what's your ',' doing?

5:37 metaperl: the kenny?

5:37 you mean me?

5:37 the-kenny: bosie: , is the prefix-command for clojurebot to evaluate clojure-code

5:37 metaperl: I was trying to use the bot... Im a novice

5:37 the-kenny: ,(+ 1 2 3)

5:37 clojurebot: 6

5:37 bosie: ah right

5:37 the-kenny: It doesn't let you evaluate things

5:37 s/evaluate/def/

5:37 triyo: anyone have experience with clojure and mongodb?

5:38 Raynes: My first experience with a DB will be with FleetDB in my email client.

5:38 the-kenny: triyo: Someone here uses mongodb with clojure alot

5:40 triyo: the-kenny: thanks, I'm new to NoSQL and am trying to see how to query embedded docs. A bit of a mind shift.

5:40 using congomong clojure lib that is.

5:40 * somnium raises hand

5:41 * esj chuckles

5:41 * somnium rescues hand

5:41 * triyo say hi to somnium

5:41 triyo: somnium: first off, congomongo is cool :)

5:41 second, I need some help

5:42 I have following simple case. Events collection with embedded Guests.

5:43 How do I query guest socs within the event doc?

5:43 by query I mean also inserts and updates.

5:43 do I use clojure conj, merge, etc?

5:44 somnium: probably update-in/assoc-in for embedded docs

5:44 triyo: * socs = docs

5:44 tomoj: it's likely I will be using congomongo at work soon :)

5:44 somnium: I am so far behind on patches its embarassing :/

5:45 triyo: I see, this is the route I chose.

5:45 Here is even a better q. For a give guest doc, how do I determine the event it is embedded in? :)

5:46 bosie: test

5:46 ,(+ 1 2 3)

5:46 clojurebot: 6

5:46 somnium: triyo: to search for an imbedded, (find :events :where {:guest.name "..."})

5:47 triyo: thx

5:47 somnium: triyo: Im not sure I understad, how can you get your hands on an imbedded doc without knowing what it was imbedded in?

5:48 ok, maybe ^^ was the answer

5:49 * somnium goes to start merging patches

5:49 triyo: somnium: via a browser, a http request was issued with the guest id. So I use guest id to lookup event. So your above where cond will do.

5:49 somnium: have you got a change log of patches, whats going in?

5:50 somnium: gridfs support is the main addition

5:51 triyo: are you looking to support group and sort?

5:51 somnium: experimental stripping out of the .java too, but maybe hold-off on that

5:52 triyo: sure, why not, patch?

5:56 tomoj: really, your workplace uses mongodb?

5:57 tomoj: not yet, but probably soon

5:57 I've gotten to use clojure on some prototype stuff, and expect to be using it in production soon :)

5:58 triyo: somnium: you asking for a patch, if so I'd be happy to have a look at that.

6:05 somnium: triyo: sure, atm Im unlikely to add anything to it that I dont suddenly need, but Im happy to merge in useful things. (though Ive been terribly slow about it this month)

6:09 triyo: no worries. If I produce something useful, you can look at it and maybe commit it if you wish at your own suitable time.

7:02 rrc7cz: how might you make a sorted-map by val instead of key

7:10 AWizzArd: rrc7cz: (def s (apply sorted-set-by #(compare (:username %1) (:username %2)) [1000-users]))

7:11 A a User is something like a (deftype User [username password age city ...])

7:12 rrc7cz: AWizzArd: I was something along those lines: (sorted-map-by #(compare (m %1) (m %2)) m) but it's treating m as a single key

7:12 AWizzArd: Maybe because (m of-your-obj) does not return a unique value of all your objects.

7:12 rrc7cz: AWizzArd: Then I tried various combinations of apply, like (apply (fn [& keyvals] (sorted-map-by #(compare (m %1) (m %2)) keyvals)) m)

7:12 hmm

7:12 AWizzArd: When each User has a unique :username then a sorted set is fine.

7:13 rrc7cz: okay

7:13 AWizzArd: But if 5 people live in the :city Paris it won't work.

7:13 Because a set treats two things as equal when they are the same over their comparator.

7:13 rrc7cz: My map is simple string : int, key val pairs, so it should be okay

7:13 tomoj: hmm, that seems kinda crummy

7:14 AWizzArd: tomoj: even when the two User instances are not the same under identical? it doesn't matter.

7:14 tomoj: does no one ever want to have a set, with equality on the actual items, but sorting by some function of the items?

7:14 AWizzArd: Yes.

7:14 tomoj: and, if I understand you, sorted-sets can't do that?

7:14 AWizzArd: You will have to emulate SortedMultisets or SortedMultimaps.

7:14 tomoj: ah

7:14 AWizzArd: tomoj: per se it is true, they can not do that.

7:15 But: you can have for example a SortedMap and as the key you use the :age of a person. And the value will be a set.

7:15 All people of age 85 go into the same set.

7:15 tomoj: ah, yeah, I can see that

7:16 and then to iterate in sorted order, just iterate over each set in order

7:16 AWizzArd: Yes. From a SortedMap you can ask for all Users of ages 30 to 40.

7:16 And then you will get 10 sets.

7:16 Instead of sets it can even be SortedSets, sorted by a unique key of the User deftype.

7:17 Then you can have all 20 year old people, sorted by :username.

7:22 rrc7cz: (apply sorted-map-by #(compare (val %1) (val %2)) m) seems like it should work, but after two comparisons it throws an exception, with m = {:f 1, :j 6, :n 3, :w 2, :m 9}

7:23 IllegalArgumentException: No value supplied for key: [:m 9]. It does call compare twice on [:n 3] and [:f 1] which seems odd

7:24 AWizzArd: m is a vector of maps?

7:24 rrc7cz: straight map

7:25 AWizzArd: I am not sure if map breaks m up into (map identity m)

7:29 rrc7cz: something else I don't understand is why "(sorted-map-by #(compare %1 %2) :f 1 :j 6 :n 3 :w 2 :m 9)" works (sorted by key), but "(apply sorted-map-by #(compare %1 %2) m)" throws an exception

7:30 AWizzArd: oh, I misread that you want a sorted-MAP and not a sorted-SET

7:30 ,(apply sorted-set-by #(compare (val %1) (val %2)) {:a 1, :b 5, :c 3})

7:30 clojurebot: #{[:a 1] [:c 3] [:b 5]}

7:30 AWizzArd: So, for sortedSETs this approach works.

7:31 For a map however your comparator gets a different input

7:31 you put MapEntries as input

7:32 so, for the key [:f 1] you input the value [:j 6]

7:32 while in reality you wanted to input :f 1 :j 6

7:32 rrc7cz: but I thought I was doing that: #(compare (val %1) (val %2))

7:33 I call val on the MapEntry

7:34 AWizzArd: Yes. But later you compare only with keywords, such as :f

7:35 let's try it with into maybe

7:35 ,(into (sorted-map-by compare) {f 1 :j 6 :n 3 :w 2 :m 9})

7:35 clojurebot: java.lang.Exception: Unable to resolve symbol: f in this context

7:36 AWizzArd: ,(into (sorted-map-by compare) {:f 1 :j 6 :n 3 :w 2 :m 9})

7:36 clojurebot: {:f 1, :j 6, :m 9, :n 3, :w 2}

7:36 AWizzArd: rrc7cz: even when you read out the val of your MapEntry, the MapEntry will be the key in the resulting map

7:37 rrc7cz: AWizzArd: I didn't know that. That's probably what's screwing me up

7:37 AWizzArd: yes, sorted maps and sets need a very different comparator

7:38 rrc7cz: now the exception makes sense: No value supplied for key: [:m 9]

7:39 AWizzArd: yes

7:39 apply splitted it into MapEntries, while you wanted "the brackets removed"

7:41 rrc7cz: then I have no idea how I can implement this, except using some hack using sorted-set-by, then building a map from the resulting MapEntries

7:41 AWizzArd: What again do you want to implement?

7:41 rrc7cz: a map sorted by its val

7:41 instead of key

7:42 AWizzArd: Can you make the values the key?

7:42 And btw, a sorted set could be also fine I guess.

7:43 Only the requests will look a bit ugly

7:43 rrc7cz: I can't make the values a key because they are int counts. So I have many 1, 2, etc

7:43 triyo: Is there a way, using update-in or similar, to update a specific nested map in a vector thats in a map itself? {:x 1 :y [{:id 1 :name "Bob"} {:id 2 :name "Alice"}]} -> I wish to update where :id is 2

7:43 rrc7cz: yeah

7:43 AWizzArd: rrc7cz: you could emulate a sorted Multimap

7:43 triyo: By "way" I mean a most idiomatic way. Here is my hackish attempt: http://gist.github.com/306565

7:44 AWizzArd: rrc7cz: it won't help to first build a sorted-set and then make an ordinary map out of it, as this would destroy the order again

7:45 rrc7cz: AWizzArd: I'm just finding that out now...

7:45 hmm

7:45 AWizzArd: But maybe you can have the current values (the int counts) as keys.

7:45 And the value will be a set of keywords

7:46 {1 #{:a :f}, 2 #{:b}, 3 #{:x :y :z}, ...}

7:49 rrc7cz: AWizzArd: that's an interesting idea

7:49 they could even be a sorted set of keywords, to default to alphabetical when the counts are the same

7:52 AWizzArd: Yes A SortedMultimapSortedSet ;)

7:52 rrc7cz: I think my head just exploded

7:52 AWizzArd: Yeah, I was fighting with this in the past days for my DB project.

7:52 That's why I am currently fluent in that

7:52 rrc7cz: which db proj?

7:53 I'm constantly on the lookout for a couchdb replacement for my project

7:54 AWizzArd: Well, I will tell more about it in some weeks, when I publish it. An object DB for Clojure.

7:54 rrc7cz: okay. I'll keep an eye out on the mailing list

7:58 djpowell: using mutator methods that return void with cells might be a bit annoying

7:59 are there any plans for a cell for thread safe things?

8:00 somnium: triyo: update-in works on vectors and maps, so

8:00 ,(update-in {:x [{:y 1}]} [:x 0 :y] inc)

8:00 clojurebot: {:x [{:y 2}]}

8:01 tomoj: but he needs to pick by value, not by vector index, I think

8:01 triyo: somnium: oh I see how you have index in key attr section

8:01 tomoj: (not that I have a better idea)

8:01 triyo: tomoj is right though

8:01 djpowell: cells seem pretty interesting. in clojure, it is impossible to accidentally forget synchronization; in java it is impossible to tell when you have

8:02 triyo: here is what I'm looking to prettify: http://gist.github.com/306565

8:03 its hackish I'd say since it uses filter to drop the item first then conj to add it again

8:06 Kjellski: Hi there, anyone with a latex listings definition for clojure code?

8:06 ~latex

8:06 clojurebot: It's greek to me.

8:07 somnium: seems like a higher-order 'make-updater fn should be possible, but nothing elegant springs to mind (or a macro that spits out a bunch of fetch-x-by-y-when-z fns possibly)

8:07 Kjellski: ~And you don´t speak greek?

8:07 clojurebot: Titim gan éirí ort.

8:08 triyo: somnium: thx, was thinking along similar line.

8:46 rhickey: Seajure - awesome! http://seajure.technomancy.us/

8:55 ohpauleez: haha, finally, someone did it

8:56 technomancy is awesome, he deserves some sort of community award haha

8:57 * _fogus_ Could lose a month digging into http://www.bitsavers.org/pdf/symbolics/

8:57 ohpauleez: whoa, for sure

9:03 underdev: eerrgghh!

9:03 i am desperately trying to use clojure-test-mode

9:04 i have installed in windows, ubuntu, and ubuntu

9:04 with emacs starter kit

9:04 in all cases, i am getting this error

9:04 http://gist.github.com/306633

9:05 i have one line, 1 set of parenthesis

9:05 I SWEAR TO GOD THEY AREN'T UNMATCHED!!!!!

9:07 ohpauleez: underdev: so frustrating

9:07 underdev: you know it

9:07 how can it possibly be that in 3 different installations, i

9:08 im getting the same error

9:08 yet it doesn't seem to be a problem anyone else is having??@?

9:09 ohpauleez: I would fire up a debugger and/or type it in piece by piece on the repl

9:09 I'm not a clojure-emacs user, so I can't provide much help beyond that

9:10 underdev: yeah, im not sure how to break

9:10 (use 'clojure.test)

9:10 down any further

9:10 ohpauleez: gah!

9:10 esj: i have'd had the same error for ages

9:11 underdev: okay, thank you thank you

9:11 for just acknowledging that

9:11 it runs the tests!, and displays output after the error

9:11 esj: i've never had the stomach to figure out what is going wrong

9:12 underdev: this is a broken window i'm having a very difficult time ignoring

9:13 * cemerick wonders if there should be a separate #clojure-emacs channel or something

9:13 underdev: if it didn't slam the buffer with "you're an idiot", i guess i could tolerate it better

9:14 tomoj: underdev: elpa?

9:14 underdev: this is elpa

9:14 ohpauleez: cemerick: seriously haha, this channel is 1/3 new features 1/3 emacs and 1/3 (map vector [1 2 3] [1 2 3])

9:15 :)

9:15 cemerick: well, I've no problem with the first and last thirds

9:15 ohpauleez: me either

9:15 underdev: installed by site in 2 oses, and once cloned from technomancy's "Emacs Starter Kit"

9:15 cemerick: I don't have a problem with emacs stuff either, but it seems like having a separate channel for clojure/emacs issues would be more productive for everyone

9:15 tomoj: hmm, I don't see the error :(

9:15 ohpauleez: I don't even mind the emacs chat all that much, I just feel bad it happens so much

9:16 cemerick: ...and maybe cut down on opportunities for people to start pointless editor discussions ;-/

9:16 jcromartie: Can we get a "project.clj not found" instead of a massive screen-filling stack trace?

9:16 cemerick: that was supposed to be ;-)

9:16 jcromartie: :)

9:16 underdev: tomoj, elpa?

9:16 tomoj: yeah

9:16 ohpauleez: now now now, who would do that :)

9:16 do we have to talk about window managers again?

9:16 cemerick: oy

9:16 ohpauleez: ;)

9:16 haha

9:17 cemerick: yah :-)

9:17 underdev: so this channel should be about clojure in the abstract and not clojure development in the concrete?

9:17 sorry to annoy

9:17 tomoj: underdev: what's the filename?

9:17 ohpauleez: underdev: you're totally fine, dig in. There are certainly people here that can help out

9:17 underdev: http://gist.github.com/306633

9:18 tomoj ^^^

9:18 tomoj: but, what's the filename

9:18 underdev: which filename (sorry)

9:18 tomoj: the file you wrote "(use 'clojure.test)" in

9:19 eevar2: tomoj: probably the repl?

9:19 underdev: tdd.clj

9:19 tomoj: seems doubtful

9:19 jcromartie: underdev: I just got testing working for myself

9:19 tomoj: ok, tdd.clj should be fine

9:19 you don't have any quotes or anything weird on the path?

9:19 (the path to the file, I mean)

9:19 underdev: clojure-test-mode-1.3 from elpa is working?!?

9:20 jcromartie: underdev: oh, no I'm not using clojure-test-mode

9:20 tomoj: underdev: yeah

9:20 jcromartie: it would seem that whatever it loading up that REPL is not using the most recent clojure version

9:20 if it's clojure-test-mode then I would guess they are using an old clojure 1.0 or something

9:20 tomoj: wait, no

9:20 I get the same error as you, now

9:21 jcromartie: hmm

9:21 tomoj: strange, must be some weird bug

9:21 underdev: lololol

9:21 i think so

9:21 tomoj: underdev: (ns foo.tdd (:use clojure.test))

9:21 underdev: is that my problem

9:22 tomoj: hmm

9:22 it seems to only happen when you don't have an ns declaration

9:22 jcromartie: underdev: I may have missed something, but are you just trying to eval (use 'clojure.test) from slime?

9:23 tomoj: strange bug

9:23 underdev: from a buffer, yes

9:23 esj: no, I have it with an ns too

9:23 tomoj: but anyway, you should have an ns declaration anyway

9:23 hmm, when I add an ns declaration it goes away

9:26 jcromartie: seems like a bug with clojure-mode?

9:26 perhaps '-related

9:27 tomoj: I get the same error without '

9:27 just a missing ns causes it for me

9:27 I think the bug is in swank-clojure

9:28 jcromartie: hmm

9:29 tomoj: anyway, it doesn't bother me that much :/

9:29 ns is a good thing

9:29 jcromartie: I can C-x C-e a (use 'clojure.test) expression

9:29 is that what you guys are doing?

9:29 tomoj: no, clojure-test-mode

9:29 jcromartie: oh

9:29 tomoj: C-c C-,

9:29 jcromartie: underdev said he wasn't using that

9:30 tomoj: hmm

9:30 I only see you saying you weren't using it

9:30 :)

9:30 underdev: YEAH!

9:30 jcromartie: oh wow, I totally read that wrong

9:30 :D

9:30 underdev: thank you so much

9:31 i was trying to work from d:

9:31 Linux tcltk 2.6.18-164.2.1.el5.028stab066.10 #1 SMP Sat Dec 12 18:52:53 MSK 2009 i686

9:31 To access official Ubuntu documentation, please visit:

9:31 http://help.ubuntu.com/

9:31 System information as of Wed Feb 17 07:03:36 EST 2010

9:31 jcromartie: NOOOOOOOOO

9:31 underdev: System load: 0.0 Memory usage: 0% Processes: 13

9:31 Usage of /: 3.4% of 20.00GB Swap usage: 0% Users logged in: 0

9:31 Graph this data and manage this system at https://landscape.canonical.com/

9:31 11 packages can be updated.

9:31 * jcromartie looks at watch

9:31 underdev: 11 updates are security updates.

9:31 Last login: Wed Feb 17 00:26:05 2010 from cpe-98-27-227-21.neo.res.rr.com

9:31 cemerick: oh gawd

9:31 underdev: To run a command as administrator (user "root"), use "sudo <command>".

9:31 See "man sudo_root" for details.

9:31 sorry

9:32 chouser_: shouldn't the IRC clients have this fixed by now?

9:32 underdev: i'm just so sorry

9:33 there is a tutorial on kakkaya.com that uses examples without namespaces

9:33 tomoj: maybe the bug didn't exist then, I dunno

9:34 anything real needs to have a namespace anyway

9:34 underdev: rt

9:34 tomoj: though I guess it might be convenient to be able to C-c C-, on a temporary file

9:34 just to screw around

9:34 underdev: rt

9:34 at least o

9:34 i'll know how to advice the next guy

9:36 or cemerick can handle it

9:36 :)

9:41 wthidden: any issues with metadata on functions in 1.2.0-master-SNAPSHOT?

9:51 underdev: as penance, i have posted a comment in his blog warning others of this problem

9:52 chouser: Huh. Blog comments in general make a lot more sense now ... I didn't realize they were penance.

9:53 underdev: in my case it is

9:54 chouser: that must be why each blog as its own incompatible and slightly broken comment markup syntax

9:55 underdev: rt, his comment system crashed firefox twice, chrome handled it though

9:55 rhickey: anyone try cells yet?

9:55 AWizzArd: They are already available?? In what branch?

9:56 Some days ago chouser and I were discussing and it sounded as a feature for the distant future..

9:56 rhickey: just a gist right now: http://gist.github.com/306174

9:56 chouser: not yet. my use cases are all in code using 1.1

9:57 AWizzArd: Okay, I must study them. Chris mentioned they may be usable in my DB.

9:57 stuartsierra: Someone remind me again what cells are for?

9:57 AWizzArd: Oho, they are implemented in Clojure :)

9:57 Where is the Java code? ^^

9:58 chouser: stuartsierra: new reference type

9:59 AWizzArd: Okay, do I need a specific branch to run this? When I compile I get: error: java.lang.RuntimeException: java.lang.IllegalArgumentException: Cannot assign to non-volatile: val (cells.clj:26)

9:59 rhickey: a cell is a new reference type that arbitrates the possibly multi-step/multi-threaded process of producing a new value

9:59 encapsulates the use of transients

9:59 stuartsierra: ok, how is that different from transients?

10:00 rhickey: can bring POJOs into the sane concurrency story

10:00 chouser: transients aren't a reference type at all

10:00 stuartsierra: yes

10:00 So a cell isolates an object on a single thread?

10:01 rhickey: note in the examples in the gist, String/StringBuilder are used as Value/Transient duals

10:01 stuartsierra: there are both single thread guaranteed and multi-thread capable cells

10:02 imagine a future (into "" some-source-of-chars)

10:02 AWizzArd: Is it okay to use the clojure.jar from build.clojure.org?

10:02 To try cells?

10:03 stuartsierra: AWizzArd: I think not

10:03 chouser: hm, hadn't realized pass/fetch would be macros and support object methods.

10:03 rhickey: AWizzArd: yes, the latest build there has all you need

10:03 AWizzArd: ok, I will then try this

10:04 rhickey: chouser: I'm still playing with that. I think it's critical if we want people to put their POJOs in cells that the perf be the same. Right now it can be. But the option for .method ==> fn is still open

10:05 stuartsierra: So a cell is a mutable value locked in a thread-safe container?

10:06 rhickey: stuartsierra: the internal transient isn't a critical part of the story. They are still unique reference types in being coordinated and in serializing activity, not just data succession

10:07 so, using a cell instead of an atom would differ in that your function would never retry

10:07 stuartsierra: Ah, so it's a means of serializing operations without the overhead of transactions?

10:07 AWizzArd: Hmm hmm, this could be interesting on a lot of levels...

10:08 rhickey: they (cells/refs) are at different points in a multidimensional space. Transactions can have arbitrary, discovered footprints, in that nested calls can enlarge the set of affected refs, whereas multithreaded cells have a fixed up-front footprint and don't support nesting

10:10 from a completely different perspective, cells might solve the 'stream' problem (and obviate chunks). I'm working on this now

10:10 chouser: I somehow thought that the ops for converting to/from the mutable version of the value would properties of the cell itself.

10:11 rhickey: chouser: that's a to-come option. If not provided would be based on protocol

10:12 I just haven't decided where to stick them (val/transient fns) and how to make their use fast

10:12 chouser: a protocol that would for example be extended to String?

10:12 * stuartsierra is still struggling with this

10:12 rhickey: that protocol is in the gist right now, including extension to string

10:12 chouser: ah, I see it

10:13 cemerick: stuartsierra: same here. :-/

10:13 stuartsierra: Is there a paper somewhere with the theory behind this?

10:13 cemerick: I was just going to suggest a assembla wiki writeup or something.

10:13 rhickey: stuartsierra, cemerick: well, I'd like to help you all understand, as I think this is very important, the missing piece of a complete model for state

10:14 stuartsierra: ok, so why would I create a cell, and what would I do with it?

10:14 chouser: have you guys looked at the previous IRC discussions?

10:14 stuartsierra: chouser: no

10:14 rhickey: stuartsierra: have you ever used a StringBuilder or transient?

10:15 metaperl: rhickey: would like write access to the wiki --- I'm bringing up a lot of points about the reference docs that need fixing and am willing to make what contribution I can

10:15 cemerick: chouser: I think I caught the first one (a few weeks ago?), but it didn't stick either.

10:15 stuartsierra: rhickey: yes

10:15 chouser: it makes the most sense to may as applied to transients ... I'm still trying to think through to understand these other possible uses.

10:15 stuartsierra: both

10:15 rhickey: stuartsierra: then you need cells

10:15 stuartsierra: ok

10:15 rhickey: cells make transients better, and potentially multithreaded. Cells make mutable things like StringBuilders safe and sane

10:16 stuartsierra: as in, safe to pass around to different functions?

10:16 rhickey: basically transients had their polict built in - cells splits it out. Once split out, the policy can be applied bot hto the transient data structures and those less, ... well less

10:16 chouser: yes! just like all reference type objects

10:16 rhickey: stuartsierra: yup

10:16 policy

10:17 * stuartsierra feels a monad coming on

10:17 cemerick: stuartsierra: that's what I said at first

10:17 rhickey: but cells preserve a very important part of Clojure's state model, that observing an identity yields a value

10:18 monads embed serialization in a call sequence, but in doing so thwart parallelization

10:18 monads are essentially non-cooperative - this monad is mine, mine, all mine

10:18 stuartsierra: :)

10:19 cemerick: rhickey: but you can't have multiple threads whacking away at a cell either -- put a StringBuilder or a transient vector in one, and you'll still get garbled results, no?

10:19 stuartsierra: cemerick: That was my next question

10:19 rhickey: cells stick with the identity/state/value model. They just acknowledge, as transients did, that sometimes creating the next state is a multi-step, and now possibly multi-participant, process

10:20 cemerick: no! multi-threads whacking works!!

10:20 a thread cell will prevent it, and a locked-cell will make it correct

10:20 cemerick: well, works in that there's no breakage, or works in that the order of entrance into the cell is defined?

10:20 Chousuke: so, for creating a new mutable vector you could perhaps have one thread change one branch and another work on the other?

10:20 could that be coordinated with cells? :/

10:20 chouser: would still be serialized in a locked-cell

10:20 stuartsierra: rhickey: So you're telling me I can make a StringBuilder, put it in a cell, append to it from multiple threads, and get a reasonable result?

10:21 rhickey: cemerick: what does it mean to define the order of independent activities? then they're not independent

10:21 cemerick: ah...so only non-sequential data structures make sense in cells?

10:21 * cemerick feels a beat-down coming ;-)

10:21 rhickey: stuartsierra: as cemerick just said, the sequentiality of Strings might not be useful

10:22 chouser: or sequential data structures where the order doesn't matter to you.

10:22 rhickey: but it really depends on what you are doing

10:22 Chousuke: cemerick: I think the idea is that only non-sequential things make sense in a multithreaded context in the first place :)

10:22 rhickey: chouser: right

10:22 stuartsierra: ok

10:22 cemerick: ok, so we should not talk about any stringy stuff at all

10:22 rhickey: go process these web sites in parallel and ad your results to a vector - you might not care about the order in the vector

10:22 cemerick: maps, structs, sets, etc.

10:23 rhickey: cemerick: if your granularity was lines, still might work for strings

10:23 chouser: it's important to do all your << inside the >> form, if you using that to build up the value?

10:23 cemerick: yeah

10:23 ...wonky java objects.

10:23 rhickey: chouser: inside which form?

10:24 cemerick: rhickey: so, say I'm keeping a reference to an embedded database in an agent right now, and using send-off to serialize access to it. Would putting that reference in a cell help me at all?

10:24 rhickey: cemerick: it's not just about Java objects - Clojure persistent/transient is made efficient, safe and multi-thread capable

10:25 chouser: I'm looking at the s4 example in the gist. if (<< .length ...) was done before >> and then its value used inside the >>, it would no longer be correct, right?

10:25 rhickey: cemerick: yes, it would likely be faster and the embedded DB could be a transient, only creating new values when read

10:26 chouser: no, because you are wither single threaded or in-cells

10:26 cemerick: rhickey: why faster? Less/no thread mgmt?

10:26 stuartsierra: Going back to the identity/state/value model: the 'value' is a mutable object, the 'identity' is the cell object, yes?

10:27 rhickey: so, that's the other part of cells, multiple actions can affect the transient, even across calls, across threads, acrross multiple in-cells blocks, before a value is produced

10:27 * cemerick is just a little sad that cells are taking <<

10:27 Chousuke: cemerick: that's still open

10:27 rhickey: stuartsierra: no - values go in, and values come out. The transient is locked in the cell, an implementation detail of the birth of a new value

10:27 Chousuke: pass/fetch is the other suggested naming scheme

10:27 cemerick: hrm

10:28 rhickey: cemerick: pass/fetch are there - I encourage people to try both and give feedback from use

10:28 cemerick: right, no thread dispatch, no message queues

10:28 cemerick: rhickey: I'm probably biased because of my string interpolation lib, but it is odd that cells get << and >>, but all other reference types have descriptive names for their "actions".

10:29 stuartsierra: So a cell is kind of a magician's box: immutable data goes in, becomes something mutable, gets bashed around, then new immutable data comes out.

10:29 rhickey: cemerick: plus, cells can be coordinated where agents can't

10:29 AWizzArd: ,(doc >>)

10:29 clojurebot: Gabh mo leithscéal?

10:29 rhickey: stuartsierra: that magician's box thing happens every time you assoc to a Clojure persistent map.

10:29 chouser: I think it's not uncommon for people to use agents and then await on the results. In such circumstances, cells should definitely be considered instead.

10:29 AWizzArd: rhickey: how to cooperate?

10:30 cemerick: oh, I totally get it now. Yeah, cells, baby! :-D

10:30 rhickey: AWizzArd: (in-cells [a b c] ...)

10:30 wthidden: so this implementation of cells is getting "similar" to Kenny Titton's cells, yes?

10:30 AWizzArd: no

10:30 very different from, uhm, Tilton

10:30 chouser: rhickey: ah! ok, glossed over the in-cells. good.

10:30 cemerick: If we can get transient sorted maps and sets, then this would make me *very* happy.

10:31 AWizzArd: cemerick: yes :)

10:31 Chousuke: wthidden: http://gist.github.com/306174 this is apparently the entirety of the implementation for now :P

10:31 AWizzArd: I would be willing to "insert" in the exact correct order, if it only were faster, going around the comparator check

10:31 rhickey: wthidden: nothing to do with those kind of cells

10:31 cemerick: rhickey: yes, what sort of coordination are you referring to?

10:32 * cemerick gotta go, bbl, will review the logs :-)

10:32 AWizzArd: cemerick: reads out of multiple cells

10:32 rhickey: AWizzArd: also modifications of multiple cells

10:32 as part of a single unit of work

10:33 * stuartsierra is still stumbling in the dark

10:34 rhickey: stuartsierra: does the rationale for transients work for you? http://clojure.org/transients

10:34 AWizzArd: yes okay, now I just need to see the major difference from refs.

10:34 stuartsierra: rhickey: yes, and I've used transients successfully

10:35 AWizzArd: Like refs, but for state which is still in the process of being built?

10:35 rhickey: stuartsierra: ok, so, cells are a way to take the policy out of the transient data structure and put it in a reusable place, the cell, coupling it with work I had been doing on a lock-based reference type

10:35 Chousuke: AWizzArd: refs can't work with mutable data.

10:35 or rather, non-persistent data.

10:35 chouser: or other side effects.

10:35 ohpauleez: does anyone have the "Are we there yet?" video link on hand, I can't seem to google it correctly

10:35 the one that shows video and slides

10:35 stuartsierra: OK. Cells are a generalization of transients. Check.

10:36 Chousuke: ohpauleez: add infoq

10:36 AWizzArd: So, Cells are closest to refs?

10:36 rhickey: stuartsierra: but they go further in adding a second policy to single-threaded - lock-based multi-threaded

10:36 chouser: AWizzArd: I wouldn't say that. They have some properties like several reference types

10:36 stuartsierra: rhickey: Ah!

10:37 rhickey: stuartsierra: they also abstract out what it means to be a value/transient dual, and, right now, expose that as a protocol

10:37 stuartsierra: So a cell does the work of wrapping access to some piece of mutable state in a lock.

10:37 rhickey: which means you can extend it to String/StringBuilder

10:37 chouser: AWizzArd: as I said, you might use a cell instead of an agent with a lot of awaits

10:38 AWizzArd: With the cell fn being executed in the calling thread

10:38 chouser: AWizzArd: right.

10:38 stuartsierra: Where in C, I would write spin_lock(x), modify(x), spin_unlock(x); in Clojure I can write (let [c (cell x)] (>> modify c))

10:38 rhickey: stuartsierra: as much as it is a feature of cells, the support for mutability inside isn't essential. In fact, I'd thought of making the default for transient/persistent be identity, so you can use with all Clojure value types

10:38 chouser: AWizzArd: and I've been doing ugly things with atoms (doing side effects in the update fn) that would be cleaner with cells

10:39 AWizzArd: chouser: well yeah, I am currently doing something similar. I will see how and where I can apply this now.

10:39 rhickey: stuartsierra: and as chouser is highlighting, the serialization of activity is a new feature vs refs and atoms

10:39 AWizzArd: But a deeper understanding won't hurt :-)

10:40 chouser: AWizzArd: and yes, multiple cells can be coordinated like refs

10:40 stuartsierra: But the basic idea is still a value protected by a lock, right?

10:40 chouser: rhickey: Is the mutation semantic really a property of the identity?

10:40 rhickey: agents serialize activity, for a single reference. Like I said, it really is multidimensional.

10:41 stuartsierra: there are still single-thread cells that throw on access from another thread too

10:41 chouser: stuartsierra: protected by a Sentry, which may be lock or something else

10:41 * stuartsierra is clinging to the cliff edge of comprehension

10:42 rhickey: stuartsierra: and as chouser says, the sentry abstraction is also broken out

10:42 stuartsierra: What other sorts of Sentries might there be?

10:43 chouser: hm. would there be any value in a Sentry that uses a real queue instead of just a lock?

10:43 rhickey: stuartsierra: dunno yet. Lock fairness is exposed tight now already

10:43 right

10:43 also, sentry usage can be hierarchical. Given a cell, you can adopt it as a parent by making a new cell with the same sentry

10:44 thus supporting coarser-granularity locking

10:45 Chousuke: hmm

10:45 chouser: rhickey: will there never be a situation where I want a single identity to sometimes participate in-cells and other times in a dosync? Or whatever...

10:45 rhickey: I'm still amazed at how tiny this was with deftype and protocols - 4 protocols, 2 deftypes, 4 extensions, bunch of macros and factories, 150 lines

10:46 stuartsierra: Ok, some of the code makes more sense now.

10:46 rhickey: chouser: I think that would be extremely hard

10:46 stuartsierra: yeah, obviously some docs strings are in order :)

10:46 chouser: Yeah, I'm talking more about high-level semantics and design than implementation challenges.

10:46 stuartsierra: There are 2 kinds of cells right now: ThreadCell is isolated to a single thread; LockCell uses a Java lock and supports access from multiple threads.

10:46 ohpauleez: Chousuke: thanks a ton

10:46 Chousuke: wonder if you could build a "dependency" system out of cells so that for one cell to yield a value, its parent cell must also be able to yield one. (otherwise it would block or something)

10:47 rhickey: Chousuke: that's a different notion of cells

10:47 bosie: is there a way to adjust the number of cores which arer used by agents?

10:49 chouser: heh. locks sorted by hash. :-)

10:50 rhickey: chouser: that may change

10:50 chouser: why?

10:50 clojurebot: why not?

10:50 raek: I think I'm starting to comprehend what cells are about...

10:51 how is << used?

10:51 rhickey: I've never really stressed identity hash uniqueness, but a failure will be caught

10:51 bosie: i have 8 cores + 8 hyperthreaded chores. i have to use 16 agents to use my 8 physical cores which is obviously sub optimal

10:51 raek: it produces an immutable value, right?

10:52 rhickey: so, if you look at the slides here: http://wiki.jvmlangsummit.com/images/a/ab/HickeyJVMSummit2009.pdf

10:52 slide 31 shows the epochal time model

10:53 chouser: raek: it ends up calling value-of on the "Transient" held in the cell, so yes that ought to return an immutable value.

10:53 stuartsierra: ok

10:53 rhickey: what cells do is allow the Fs (pure functions), to become Ps (processes) that have some extent. This is only possible and correct if observers not involved in the process can only obtain state values (Vs)

10:53 cells ensure that

10:54 and so, follow the model

10:54 but instead of saying - pure functions but correct use of transients is ok, makes a reusable construct for processes

10:55 stuartsierra: Hmm. So a process can be bashing away at a value, and an outside observer can still see a consistent state at any time.

10:55 rhickey: so, while functional people look at that diagram and see a monad, I never did. I always imagined multiple participants/parallelism

10:56 stuartsierra: there's no such thing as bashing at a value

10:56 values are immutable

10:56 stuartsierra: arghhh.

10:56 right

10:56 rhickey: they bash at transients, which are *unobservable* outside of the process

10:57 stuartsierra: right

10:57 rhickey: that's key, just like a transient inside the scope of a single function F would be

10:57 AWizzArd: While the fn is running all derefs in other threads will yield the value of the cell before fn started, yes?

10:57 rhickey: only now, F becomes P and can have some extent, while preserving the unobservability, and transitions of the identity from state to state

10:58 stuartsierra: So the cell expands the scope of a transient to multiple processes, ok.

10:58 Chousuke: AWizzArd: wouldn't that be decided by the sentry?

10:58 rhickey: stuartsierra: right, or across calls

10:58 * stuartsierra sees a glimmer

10:59 Chousuke: AWizzArd: I suppose sometimes you might want a deref to block instead of returning an old value

10:59 rhickey: across calls being equally critical and useful, especially when multiple cells are involved

10:59 stuartsierra: Nuts, have to go to a meeting, back in a bit.

10:59 raek: so cells do transient-like stuff, but not limited to single functions, single threads or clojure transients?

10:59 chouser: AWizzArd: I think that depends on the type of sentry and the scope of in-cells (if that's being used)

10:59 rhickey: raek: right

11:01 chouser: rhickey: any particular reason you don't import java.util.concurrent.locks.ReentrantLock in that gist?

11:01 rhickey: AWizzArd: so, still in flux is value production. I've baked in one policy but there are several. Single thread cells produce a value on any deref. LockedCells create a value on any deref in-cells

11:01 chouser: no

11:01 but there could be other policies - never auto-generate values, only on request for render

11:02 or, for locked cells, try to generate on deref but don't wait if busy

11:02 or, always enter the process to see if there is a new value on deref

11:03 I'm not sure if I will expose all of these. There are other composite ones like yields new value every N edits

11:03 AWizzArd: Maybe in some complex way they can be exposed, so if people really need such fine granularity it would be there.

11:04 And some typical use cases for very easy use.

11:04 rhickey: some knobs will be useful, as you have very distinct scenarios - heavy writing, any interim value is good, block writing, no interim value is good

11:04 sporadic writing

11:04 what is true in all cases is that the last value is remembered and constitutes the observable state

11:05 like the other refs

11:05 chouser: but when the shole cell protocol is described in 12 lines of code, I wonder how many knobs are worth including before you just tell advanced users to write their own cell.

11:05 rhickey: references

11:05 chouser: could be, but want to avoid multiple implementations of common needs

11:06 elevensies (tea)

11:10 raek: >> and << are just synonyms for pass and fetch now, right?

11:10 chouser: raek: yes

11:16 raek: an observation: the order of the arguments of >> is not consitent with that of alter, swap!, send etc...

11:17 i.e. f - ref - args instead of ref - f - args

11:18 BrandonW: is it wrong that i actually like the enforcement of loop/recur when creating a tail recursive function?

11:18 the-kenny: BrandonW: No, I like it too

11:19 BrandonW: good

11:19 it just makes it seem more readable to me

11:19 was wondering if i was missing something...

11:22 chouser: raek: that's intentional, to keep conversion of existing persistent code to the use of cells as straight-forward as possible.

11:23 hm, I wonder if it would make sense for >> and << to keep the arg order they have now, and make pass and fetch match the other reference fn arg order.

11:27 raek: chouser: I was thinking about that too...

11:29 rhickey: chouser: yes, I'm definitely not sold on the different arg order

11:34 AWizzArd: so far Strings and StringBuilder and some Clojure collections can be edited in Cells, yes? If I want to modify different objects I have to extend on a Protocol?

11:34 chouser: that they're macros is another important difference.

11:35 rhickey: chouser: that could go away with .method fn literals

11:36 chouser: oh right, you mentioned that. That's mostly blocking on a decision about how they would support hinting?

11:37 rhickey: I think I ended up with the generated fn having a type switch for overloads

11:38 chouser: I don't know what a type switch is

11:38 rhickey: if it's a This do this, else if it's a That do that ...

11:39 but essentially, given .AClass/aMethod, generate a single fn that could deal with any arirty or same-arirty type overloads

11:40 AWizzArd: are pass/fetch supposed to be used in user code? Or will it be << and >>?

11:40 rhickey: AWizzArd: right now, use whichever you prefer and report back

11:41 chouser: rhickey: oh, I see. I forgot about having the class in the symbol. so then a couple runtime tests would remove the need for any arg hints

11:42 rhickey: right

11:42 chouser: but I guess that might not produce a consistent return hint

11:42 * dnolen likes << and >>, they stand out

11:42 rhickey: also right, but when used as a higher order fn, that's not really in play

11:43 AWizzArd: rhickey: do you think the pure Clojure implementation of Cells performs practically equally well, compared to a Java implementation?

11:43 rhickey: AWizzArd: yes

11:46 Draggor: Hey hey, so, is Programming Clojure the main book to get?

11:46 chouser: Draggor: it's the only complete book so far.

11:46 AWizzArd: Rumours say another book is currently written..

11:46 chouser: Draggor: but some lovely options are on the way

11:47 Draggor: I've got a brithday coming up, and my programming book library is rather thin, so it's time to beef it up!

11:47 chouser: Draggor: There's one book from APress and two from Manning that have some chapters available online already.

11:49 Draggor: Oh Apress, knew that was familiar, got PCL from there

11:50 rhickey: so, today's wake-me-up-at-4am idea is - the transient dual of a seq is an iterator/stream-like thing. So, given appropriate plumbing, putting a seq in a cell will give you an allocation-free yet safe stream, convertible back to a value at any time

11:51 LauJensen: wow ... at 4am? :)

11:51 mattrepl: hmm, I thought the variants ending with * (e.g., bound-fn*) were just function variants of macros. but what of list and list*?

11:51 rhickey: LauJensen: unfortunately, that's frequently the case - I wake up working

11:52 LauJensen: Sounds a little stressful - Long walks help. Anyway, the idea sounds incredible interesting

11:52 Chousuke: mattrepl: the convention is not limited like that :)

11:52 mattrepl: the * just means "variant"

11:53 chouser: like x and x' ("x prime") in math. related in some unspecified way, yet different.

11:54 StartsWithK: what are << and >>?

11:55 chouser: StartsWithK: operators on cells, a new kind of reference object: http://gist.github.com/306174

12:01 eyeris: In the definition of dotimes (or just about any other std macro), why is body deref'd but bindings is not?

12:02 chouser: that's not a deref ~@ splices a list into the output, where ~ just inserts an item

12:03 ,`(1 2 ~[:a :list] 4 5)

12:03 clojurebot: (1 2 [:a :list] 4 5)

12:03 chouser: ,`(1 2 ~@[:a :list] 4 5)

12:03 clojurebot: (1 2 :a :list 4 5)

12:03 eyeris: Oh. I see.

12:04 ,`(1 2 ~@[:a [:x :y] :b] 4 5)

12:04 clojurebot: (1 2 :a [:x :y] :b 4 5)

12:04 eyeris: Thanks

12:04 dnolen: rhickey: so another silly mental model thing. are cells about perf at all the way transients are? using a cell to modify a string (via StringBuilder) will that be faster than modifying a string using Clojure primitives?

12:06 rhickey: dnolen: no, not about perf, but good perf. Strings can't be modified. Some string transforms could be done with stringbuilders, many not

12:10 * stuartsierra returns

12:12 rhickey: imamgining transient seqs: http://paste.lisp.org/display/95115

12:12 imagining

12:13 so, lazy-seqx takes a recipe for a lazy seq and a recipe for a transient seq

12:13 all seqs on data structures support transient versions

12:14 mattrepl: this is looking like great stuff for agent-based models

12:15 rhickey: then things like reduce and into can simply hoist a stream out of a lazy seq chain

12:15 without giving up the ability to get a value at any time. And unlike the stream design, this is restartable/continuable

12:17 chouser: you're too far away to hear the sound of my head exploding

12:17 dnolen: rhickey: for some reason I had gotten the notion that << is expensive, I guess not true?

12:17 rhickey: chouser: do you see where I am going?

12:17 dnolen: not true

12:17 dnolen: rhickey: also what you're saying ^ seems to imply that into would be cheap (unlike how it is now)

12:18 chouser: I think so. still working on "restartable"

12:19 rhickey: chouser: the only things that wouldn't be restartable, and for which you couldn't use lazy-seqx. are seqs sourced from IO

12:19 but restartable/continuable means you could grab a val from a transient seq and then call move! on it - no problem

12:19 djpowell: rhickey: in JCIP he uses a tie-breaking lock of the identity-hashcodes are the same for two objects, and locks that, followed by the two locks in an arbitrary order. would that work for locked-cells - as a fallback

12:20 chouser: if you have a lazy-seqx obj, you can get either a seq or an Iter+Transient out of it

12:20 rhickey: chouser: right

12:20 lazy-seqx would implement Editable in terms of a call to the latter

12:21 chouser: if you take the Iter, you can mutate it safely and at any point capture a lazy-seqx of the remainder

12:21 rhickey: so (cell a-lazy-seq) works

12:21 the Iters are always in cells

12:22 you can't directly touch them

12:22 This solves the long-standing problems of iterators - you can't safely share them, and can't get values out of them

12:23 chouser: the second expr in that lazy-seqx example is returning an Iter+Transient, but you're saying when I can't get that directly -- the lazy-seqx object would give me a cell of it instead (not collc but another cell)?

12:23 s/when/that/

12:24 rhickey: when you said (cell lazy-seqx), that calls transient-of on it, which is implemented by it in terms of a call to the second expr

12:24 leaving you with that iter in the cell

12:25 chouser: ok. then I can fetch the Iter and move! it?

12:25 rhickey: calling transient-of directly is a no no

12:25 chouser: use the iter through the cell

12:25 chouser: pass not fetch

12:25 rhickey: you can't get it out of the cell

12:26 jlilly: (-> world (nth x) (nth y)) ~= ((nth (nth world))) ?

12:26 rhickey: pass move!, fetch current

12:26 jlilly: err. with the right number of parens, that is.

12:26 chouser: jlilly: (nth (nth world x) y)

12:27 jlilly: chouser: ahh. that makes much more sense. and is apparent now that I reread the docs. thx.

12:28 chouser: rhickey: and @(cell lazy-seqx) gets me a regular sequence

12:28 rhickey: right

12:29 even after having move!d it a few times, and ok to move! it afterwards

12:30 chouser: right! and the cost of inserting a deref into that process is just a couple allocs.

12:30 rhickey: right

12:30 but it means a chain of map filter blah blah turns into a single value-producing factory

12:30 chouser: though walking the seq and the seqx would each compute each new value

12:31 rhickey: while in the cell

12:31 chouser: yes, but no [lazy]-seq nodes

12:31 i.e. the fns produce values, but have to

12:31 chouser: lazy-seq nodes for the seq, but not for the seqx

12:32 djpowell: you can use .method in your fetch/pass call, but usually in Java mutators return void - would calling mutators want any special support?

12:32 somnium: very ot, but is there a convention for 'partial-ear-muffs', like choosing *foo vs. foo*?

12:32 rhickey: once you've put the lazy-seqx in a cell, there is no allocation other than that done be the work itself (e.g. map call (f x))

12:33 djpowell: possibly. The first use case - StringBuilder, happened to return the object

12:33 chouser: ok, but that's an unusual case anyway. perfectly safe and hardly any more expensive than pre-chunk seqs. Most of the time a seq chain is used once.

12:33 rhickey: chouser: much less overhead than pre or post chunk seqs

12:34 tomoj: somnium: the only time I've seen that is for foo* as a helper to foo

12:34 chouser: I meant walking the same lazy-seqx from two different places, one as a seqx the other as a seq. Rare but still safe.

12:35 rhickey: chouser: oh, yes, the realized/lazy seq has same overhead as always

12:35 chouser: that is, rare and each value gets computed twice (once for the seq and once for the seqx), but not terrible perf and a reasonable cost for the safety

12:36 rhickey: but the critical thing here is that you can start with a bunch of normal lazy-looking calls in a chain, only to have the end consumer know they will slurp in in one go - they put it in a cell and bam - the seq is completely virtual

12:36 or reduce or int do that for them

12:36 into

12:37 chouser: right. and a chain that includes links that *don't* use lazy-seqx will still use the cell for the spans of the chain that support it, right?

12:37 rhickey: so, this dimension of cells is also quite important, IMO

12:38 chouser: hm, just the final span I guess.

12:38 rhickey: chouser: well, lazy-seqx is for computed seqs, but all of the concrete seqs will support editable. If a chain has non-Iter nodes then move! will fail

12:39 it's a good question

12:39 chouser: (->> big-vector (map f) (filter g) (partition 2) (map h) (filter i))

12:40 rhickey: yes, put that in a cell and the whole calculation is virtual, no cons cells

12:40 chouser: Right. But in instead we assume map and filter support lazy-seqx, but partition does not ...

12:40 s/in/if/

12:41 rhickey: I understand

12:41 IO seqs the most likely problems

12:42 chouser: bah, screwed it up

12:42 (->> big-vector (map f) (filter g) (partition 2) (map h) (filter i) (into []))

12:42 there. so if into also supports lazy-seqx...

12:42 rhickey: for ordinary seqs, move! == next

12:43 chouser: does the whole chain go lazy-seq, or can into drive a cell for map h and filter i, while pulling lazy-seqs from map f, filter g, and partition?

12:43 rhickey: there is nothing about cells that demands the implementation be mutating

12:43 so, ordinary lazy-seq implements Iter where current == irst and move! == next

12:43 first

12:44 value-of == this

12:44 done

12:45 chouser: but filter i will returh a lazy-seqx, right? and into would use the cell version of that?

12:45 rhickey: oops, transient-of == seq. Now done

12:46 (cell an-ordinary-lazy-seq) will work if ordinary lazy seqs, in the absence of a high-performing mutating impl, have a simple impl of Editable/Transient/Iter as above

12:47 current/first, move!/next, transient-of/seq, value-of/this

12:48 because cells capture return values, they work fine with values

12:48 chouser: ok, I'm not getting this detail, but I see how normal usages will always be compatible and sometimes be alloc-free. very cool.

12:48 rhickey: and pure fns

12:49 chouser: much easier to support than chunks as well, for individual seq library fns.

12:50 rhickey: right. I'd still like to make that second expr more succinct

12:50 but with the above recipe for compatibility, people could add more efficient transient support as needed

12:51 i.e. lazy-seq looks exactly as it does now and support Iter/Editable as I've described, with no client help

12:51 ordnungswidrig: aloha

12:51 rhickey: swithc to lazy-seqx (or whatever it is called), provide an Iter impl, and you're off to the races

12:53 lazy-seq-iter?

12:54 chouser: heh. better than lazy-seqx. :-)

12:55 * rhickey will try to prototype it

12:55 jlilly: http://pastie.org/private/hp1lhudpqpfjozqjlb7cq -- any chance someone can walk me through line 7 of this? Having a hard time with all the alters and assocs.

12:56 or perhaps there's a better explanation of assoc / alter than (doc) ?

12:57 arkrost: Hi! Tell me please what difference between let and let*.

12:57 Chousuke: jlilly: it takes the value of p, and alters it by associng a value to the key :ant

12:57 chouser: arkrost: let* is an implementation detail. ignore it.

12:58 Chousuke: arkrost: if you're looking at a macroexpansion, just treat let* as let

12:58 chouser: arkrost: if you're looking at macroexpand output, try macroexpand-1 instead -- might be clearer.

12:58 Chousuke: except that it doesn't support destructuring

12:58 jlilly: assoc :ant p is basically an equivalent of mymap['p'] = new_p ? (for other languages)

12:59 Chousuke: jlilly: assoc takes the map first.

12:59 jlilly: but in this case, because it's used with alter, it's *alter* that passes it the map, behind the scenes

13:00 eg: (assoc {:a 1} :b 2) -> {:a 1 :b 2}

13:01 but (def p (ref {:a 1})), (dosync (alter p assoc :b 2)), @p -> {:a 1 :b 2}

13:03 jlilly: so just to get all of my noob questions answered..

13:03 Chousuke: jlilly: in most languages there's no direct equivalent for this

13:03 jlilly: since they don't separate values from identities

13:03 jlilly: @p is really saying "Get me the value of the ref (ref being an indirect pointer to some data) p" right?

13:03 Chousuke: yes.

13:04 jlilly: and because that was in a dosync, and we altered p, p's new value should be {:a 1 :b 2} when we finish. right?

13:04 Chousuke: yes

13:04 jlilly: or, assuming someone else updates the datastructure out from under us, we'll at least know that p has :b 2 in it, b/c that's what our operation does. right?

13:05 my interpretation of what happens is that it tries to alter the structure, fails, is told to retry, then it runs again on the updated datastructure?

13:05 Chousuke: at commit, yes. of course, someone might independently update it after the transaction has finished and right before you read it

13:06 something like that happens, but it's just the implementation. the semantics are more important than what it actually does :)

13:06 jlilly: I'm basing nearly all of my knowledge here on ants.clj and the "clojure for java programmers" talk, despite not being a java programmer.

13:06 :-P

13:07 Chousuke: heh

13:07 jlilly: I'm assuming that ants.clj is a solid reference for this stuff?

13:07 or at least well written enough to based style and practices from?

13:07 stuartsierra: ants.clj is old

13:07 Chousuke: I think it should be okay, but it's a bit dated in style.

13:08 jlilly: is there better example code?

13:08 Chousuke: for refs and such it's still valid. they haven't changed.

13:15 bosie: Chousuke: but for the agents?

13:16 Chousuke: probably :P

13:17 bosie: i am a bit confused with most of the concurrent programming articles in clojure. isn't refs nothing more than a mutable object?

13:17 to run it on multiple cores i always need agents, no?

13:17 Chousuke: no

13:18 you can use threads to run functions on multiple threads :P

13:18 bosie: you mean the java class Thread?

13:18 Chousuke: yeah.

13:19 ,(do (.start (Thread. #(do (sleep 1) (println 'foo)))) (println "bar"))

13:19 clojurebot: java.lang.Exception: Unable to resolve symbol: sleep in this context

13:19 Chousuke: eh

13:19 ,(do (.start (Thread. #(do (Thread/Sleep 1000) (println 'foo)))) (println "bar"))

13:19 clojurebot: java.lang.IllegalArgumentException: No matching method: Sleep

13:19 Chousuke: :(

13:20 oh well, something like that anyway

13:20 stuartsierra: ,(do (.start (Thread. #(do (Thread/sleep 1000) (println 'foo)))) (println "bar"))

13:20 clojurebot: bar

13:20 bosie: Thread/sleep

13:20 ye

13:20 Chousuke: hm, I guess the thing in the other thread got printed somewhere else :D

13:20 stuartsierra: yep

13:21 Chousuke: anyway, the thing is that refs are mutable boxes with well-defined concurrency semantics

13:23 whereas concurrently reading/writing regular mutable variables in a common language usually results in undefined behaviour

13:23 which is why you need locks

13:27 rhickey: live notes around cells, not docs! http://www.assembla.com/wiki/show/clojure/Cells

13:27 ben_m: Greetings! :)

13:28 * Licenser shakes the bars, "Let me out of my cell!"

13:29 ben_m: In Clojure, what would be the best way to concurrently run some functions and then, after they're all done, return a list with the results?

13:29 Licenser: is there a document about this cell stuff aka what it is suposed to do in the future?

13:30 rhickey: ben_m: pmap or pvalues

13:31 ben_m: Thanks! :)

13:31 _fogus_: Licenser: Chapter 8 of "The Joy of Clojure" ;-)

13:31 Licenser: Now I may sound stupid but what is "The Joy of Clojure?"

13:31 * _fogus_ runs off to start writing chapter 8

13:32 * Licenser laughs

13:33 Licenser: ah cells seem to be a way to encapsulate mutable objects in a imutable hull when I get the notes from rhickey right

13:41 BrandonW: is there some information posted somewhere on this talk of cells lately?

13:41 it sounds very interesting

13:41 rhickey: BrandonW: logs here: http://clojure-log.n01se.net/

13:42 BrandonW: thanks

13:42 ordnungswidrig: was there an agreement on the naming around cells? I left the conversation early the other day

13:48 BrandonW: wow that does sound useful

13:49 rhickey: ordnungswidrig: current best names in use now, all subject to change

13:49 BrandonW: i was just thinking today what the best way to wrap something like the java commons http client

13:50 if you could put that in a cell and operate on it (and any cookie containers and others objects that would get potentially altered by each use of the client) in a thread-agnostic way

13:50 jakarta*

13:51 although that might be better served with an existing threading mechanism

13:51 ben_m: I hate ELPA, it makes my .emacs messy :(

14:03 ordnungswidrig: oh, nice.

14:04 ben_m: Anyone using clojure with slime without using ELPA? If yes, could I see your .emacs?

14:04 technomancy: ben_m: if your .emacs is messier with Emacs than without, you're probably confused about how to set it up.

14:05 ben_m: Might be true

14:05 technomancy: because it should be one or two lines

14:06 ben_m: When I last tried it I had to do a lot of config in my .emacs to get stuff to work after I started using ELPA

14:06 So I got rid of it

14:08 maxhodak: hey -- i need some help debugging this: http://github.com/franzinc/agraph-java-client/blob/agraph32/clojure/src/com/franz/util.clj

14:09 basically what they're doing is using (declare) and then referencing a variable (*with-open-stack*) before it gets bound, leading to fail

14:09 and i can't figure out the right way to solve it

14:10 L29 and L49 are the most interesting

14:11 i've already changed contrib.stacktrace to clojure.stacktrace

14:11 rhickey: maxhodak: they document you're not supposed to use those outside the scope of with-open

14:12 maxhodak: with-open2 binds *with-open-stack*

14:14 maxhodak: rhickey: hmm, let me find where this is called; it's deep enough inside their logic i'd be surprised if the with-open was needed all the way up

14:15 http://github.com/franzinc/agraph-java-client/blob/agraph32/clojure/src/com/franz/agraph.clj#L28

14:15 so i call agraph-repoconn on L37

14:16 do i need with-open outside of my invocation of that?

14:19 Chousuke: maxhodak: seems like anything that calls open needs to be within a with-open2 context

14:21 maxhodak: and that means dynamic scope, so anything that might call open in any way to be wrapped in with-open2 :P

14:21 +needs

14:22 maxhodak: Chousuke: ok, thanks, i'll try that

14:22 rhickey: thanks for pointing out "read the obvious doc" too

14:22 Chousuke: maxhodak: looks like you can use the scope* functions too

14:23 or macros :P

14:25 lancepantz: clojure-yaml/clojure-build.xml:86: Could not find clojure.lang.Compile. Make sure you have it in your classpath <----- looking for clojure.jar in my classpath, right?

14:27 because clojure.jar is indeed in my classpath

14:27 i have no clue what is throwing that error

14:33 chouser: Huh. From twitter: "Moving from #clojure to #scala, watching as the entire software community passes me going in the opposite direction."

14:34 Chousuke: heh

14:34 rhickey: chouser: I saw that - funny

14:34 ben_m: Scala is interesting

14:35 But it's not a Lisp :D

14:35 chouser: lancepantz: I've not seen a stack trace pointing at a line in an xml file before. Is that maven or ant or something?

14:35 lancepantz: ant

14:35 which i'm new and unfamiliar with /idiot disclaimer

14:37 rhickey: names again - Iter interface: has-item, item, move! ?

14:38 I don't like has-item

14:39 chouser: has-item is the complement of empty?

14:39 rhickey: kinda

14:39 lancepantz: so no one can make sense of that ant error? because otherwise i'm going to have to use jyaml :/

14:39 and i really don't like java :)

14:40 Chousuke: lancepantz: maybe you need to pass ant some parameter that tells it where clojure.jar is :/

14:40 for contrib it used to be ant -Dclojure.jar=/some/path

14:40 lancepantz: cool, let me try it

14:41 Chousuke: lancepantz: take a look at the build file and see if it has something like ${clojure.jar} or whatever

14:41 rhickey: chouser: the protocol is (when (<< has-item cc) (use-it (<< item cc)) (>> move! cc))

14:42 jlilly: sanity check, is #(..) shorthand for defining a macro on the fly?

14:42 rhickey: one benefit of has-item is it keys you into the fact that you (must) call it before item

14:43 Chousuke: jlilly: no, a function

14:43 jlilly: got it. thx.

14:43 chouser: so has-item/item/move! are used very roughly where one would ahve used seq/first/next

14:44 rhickey: right, except the return of has-item isn't useful except in a conditional

14:44 jlilly: Chousuke, and % represents the the args to the function?

14:44 Chousuke: jlilly: the first arg

14:44 jlilly: %n represents the nth arg

14:44 chouser: sure

14:44 Chousuke: % is short for %1 :)

14:48 (when (fetch permit cc) (f (fetch item cc)) (pass move! cc)) :P

14:50 jlilly: Chousuke, so I don't have to keep bothering you, is there a place that lists all of these # syntax things? I think I've come across #( #' and now #^

14:50 Chousuke: clojure.org/reader does I think

14:50 jlilly: rokk

14:57 ben_m: When editing Clojure code with paredit and I'm typing a closing ], it jumps to the end of the expression. Can I disable that somehow?

14:57 Chousuke: isn't that what it's supposed to do? :/

14:58 ben_m: (defn foo [n]), after pressing ] it jumps to the ), so I have to move the point back a character before I can write the rest of the defn

14:58 point being at n

14:59 Chousuke: I think I should fix my paredit. it doesn't work properly in slime.

14:59 ben_m: works for me. :/

14:59 ben_m: :/

15:00 Maybe my paredit version is old

15:00 morphling: ben_m: you can move out of [] by typing ), regarding your question: you can find out what ) is bound to and bind ] to the same

15:00 ben_m: ] and ) do the same thing for me

15:00 But they're bound to different functions

15:01 chouser: if a sequence isn't made up of items, perhaps it's made up of steps?

15:02 step, do-step!, steps-done? :-/

15:02 morphling: ben_m: ah, ok, then I have no idea

15:03 Chousuke: chouser: I think it would have to be steps-left?

15:03 chouser: ah, better.

15:04 Chousuke: but "step" is a common local name already ;/

15:05 chouser: step isn't right anyway. There is an action involved, and make next-step would work, but item is supposed to return the result of the pervious step, not the action itself.

15:05 rhickey: chouser: it has to be really clear which order to call. Both Java and .Net collapse these into 2-method protocols in order to avoid mistakes, and still added foreach. But we can't combine like hasNext/next of Iterator since next needs to return the item and move, but we need to capture the moved iter

15:06 chouser: Java's .next() freaks me out.

15:06 rhickey: the first cut I showed had move! potentially returning nil when done, but was eager, and longer than the 3-method impl

15:07 Chousuke: how about the "permit" name I suggested? :P

15:07 chouser: the counter arithmetic in gvec's ListIterator implementation seems almost completely arbitrary to me.

15:07 rhickey: chouser: it has one benefit which is you can only call it once. current usually means having to cache. I don't intend to, so multiple calls to current/item mean multiple calls to work

15:07 chouser: hm, so it is like redoing the current step

15:08 rhickey: Chousuke: permit doesn't work for me

15:08 chouser: yeah, although I'm not keen on step. These will operate over plain data also

15:09 chouser: sure, but are still logical sequences.

15:09 I don't like 'step' either, just trying to get ideas flowing.

15:09 rhickey: yes, but step implies 'job/work' to me

15:09 chouser: item is so generic

15:10 rhickey: yes, item is, but it is just data. first still works, sort of

15:15 technomancy: oh nice, metadata on fns landed.

15:15 this pleases me. =)

15:43 stuartsierra: Am I correct in thinking that any class that will be stored in a cell must extend Editable and Transient?

15:44 rhickey: stuartsierra: there might be per-cell options to specify to-transient and to-value functions, otherwise yes

15:45 stuartsierra: ok

15:49 So: one reasonable use case: I create a date/time datatype, extending transient-of to return a java.util.Calendar. Then extend value-of on Calendar to return my date/type type. Then I can put a Calendar in a cell and roll it, but get a reasonable value back out.

15:51 rhickey: stuartsierra: you would put the value in, and the cell would call transient-of/value-of as needed. But yes, values in and out

15:53 stuartsierra: right

15:54 In that case, what benefit does the cell give me?

15:54 cemerick: rhickey: caught up on logs, I'd say I grok the important bits. Stellar stuff.

15:56 chouser: seems like it may be reasonable to put a mutable thing in a cell in an agent, when you might now just put the mutable thing in the agent and try to remember to never mutate directly.

15:56 rhickey: stuartsierra: well, a cell gives you identity (as do all ref types), so if that data was a 'due date' or something that might be associated with different values over time, the same benefits would apply. Processing a date functionally is pretty cheap so no real benefit to the transience. But changes to the date could be coordinated (like refs), and activity serialized

15:56 also if you pass it around you will get thread safety checks

15:57 unlike a raw Calendar

15:57 stuartsierra: Right, so I'm protected from mutating it from multiple threads.

15:57 rhickey: yes, if you want to be. or coordinated across threads if desired

15:58 stuartsierra: So a cell is most useful in the case when realizing a persistent value could be expensive.

15:58 rhickey: i.e. if any logged in user's thread could change the due date

15:58 ben_m: How do I specify a -D argument when starting clojure in Emacs?

15:59 stuartsierra: ben_m: use a shell script

15:59 rhickey: stuartsierra: I'm not going to let cells be pigeonholed like that. There are a number of use cases related to the serialization of activity that still apply even if the contents are pure values (which will be possible)

15:59 chouser: (send agt #(>> set! (.field %) val))

15:59 rhickey: also see recent conversation about transient seqs based on cells

16:00 stuartsierra: yeah, those left me even more confused.

16:00 rhickey: hrm

16:00 stuartsierra: So: cell guarantees transition going in (transient-of) and transition coming out (value-of)

16:01 rhickey: yes, but you could use with Clojure data values by supplying identity for both. It's not just about transience

16:01 stuartsierra: ok

16:02 rhickey: people sometimes need once-and-once only activity coordinated with data change

16:02 stuartsierra: More importantly, it guarantees that all operations on the thing inside the cell will be mediated by >>

16:02 chouser: set! was a bad example -- I was thinking something that took some work thus useful to do in another thread.

16:02 Chousuke: Was the idea that you could specify two ways of generating a seq: a persistent and a transient one; then a function which knows it's going to consume the entire seq will request the transient version?

16:02 rhickey: chouser: not sure of the benefits over (future (>> foo! acell))

16:03 chouser: oh, good point.

16:03 rhickey: given the cell must be lock-based for any thread pool access to work

16:04 I wonder if a shorthand for (in-cells [c] (>> foo! c)) is in order

16:04 chouser: yeah, I hadn't thought of using future there. cell instead of agent+await. future+cell instead of agent

16:05 rhickey: the diff with latter being a defined order on sends from same threads

16:06 agent+await should die

16:06 almost always a bad design that's avoiding latches or queues

16:07 (pass-in foo! c) ?

16:10 * rhickey likes pass less and less

16:11 chouser: (in>> foo! c) ? :-P

16:18 powr-toc: Just watching Rich's awesome lecture on clojure's philosophy for time management (again)... And I'm wondering where these ideas on the seperation of identity, state, values and time come from... Are there any other languages that share these notions, or is clojure unique?

16:18 if so are there any references (beyond whitehead etc...) to this?

16:21 chouser: man, it *so* frustrating to get stack traces that include a line inside a try-block that was somehow never caught

16:21 Chousuke: there is at least one language where time is a fundamental type. Processing only occurs if you advance time.

16:22 powr-toc: Chousuke: do you have a reference/

16:22 ?

16:22 chouser: I've seen this before, and it hurts every time. Sometimes it's a wrapped exception thing, but right now I have (catch Throwable e ...) and it's still not catching

16:22 Chousuke: powr-toc: I think it was this one http://chuck.cs.princeton.edu/doc/language/

16:23 hiredman: chouser: maybe a lazy thing, or a delay of some kind

16:24 macro re-arranging something?

16:24 line numbers could be lies

16:24 powr-toc: Chousuke: cheers... what about Rich's critique of OO's confused mix of identity, state and time? Are there any papers or other work mentioning this?

16:25 Chousuke: I'm not aware of any

16:25 chouser: hiredman: those are all good thoughts, but I don't think any of them apply here.

16:25 * chouser stares more...

16:27 hiredman: println time

16:27 technomancy: debug-repl!

16:27 chouser: I'm catching it successfully at an outer level, where it claims to be a java.lang.IllegalArgumentException

16:27 hiredman: println at the top of the try and at the bottom

16:27 Chousuke: your catch form has illegal arguments! :P

16:27 chouser: Chousuke: :-P no it doesn't

16:28 Chousuke: (or the try form)

16:28 I wonder what happens if you do (try foo (catch ...) blah)

16:28 underdev: powr-toc: the notions of time/state/identity seem to me more along the lines of kant vs hume than identity

16:29 whiteheads notion of identity, state, and time would be very different

16:29 chouser: oh, no I'm successfully catching in an *inner* scope.. dang it. my tests have been faulty

16:29 Chousuke: compile error I think

16:30 ,#(try 0 (finally 1) 2)

16:30 clojurebot: chouser: I don't understand.

16:30 chouser: , #(try 0 (finally 1) 2)

16:30 clojurebot: chouser: It's greek to me.

16:30 underdev: ie higher order actual occasions would have intrinsic identity, with state changing due to prehensions, with time created to accomodate the change in state

16:30 chouser: ,(fn [] (try 0 (finally 1) 2))

16:30 clojurebot: chouser: It's greek to me.

16:30 powr-toc: underdev: Thanks I might well check that out :-)... but I'm wondering if there is an argument similar to Rich's in cs literature anywhere.

16:30 * hiredman giggles

16:30 hiredman: clojurebot ignores try's

16:31 chouser: hmph

16:32 might proxy eat an exception?

16:33 hiredman: pircbot tends to eat exceptions

16:33 chouser: what do you mean?

16:33 methods on a proxy object, inside methods?

16:34 chouser: wait...

16:36 ok, there are a few extra layers of proxy and macro involved here than I was thinking.

16:36 why do I create such complicated things!?

16:37 hiredman: you are driven by a faustian bargain with management

16:39 chouser: I can't blame management -- they leave me alone here, to create my own hell...

16:40 somnium: yay freedom

16:40 Chousuke: at least it's a hell written in clojure

16:40 chouser: Chousuke: yes!

16:41 But that means I can't blame management *or* the language. Which leaves ...

16:41 ... google protobuf! *whew* that was close.

16:43 jasapp: chouser: how did you convince management to let you write in clojure?

16:44 chouser: they are enlightened :-)

16:44 hiredman: depending which faust you read that could work

16:44 jasapp: nice, I'm jealous

16:44 chouser: it's mostly meant as "prototype" code. We'll see if it stays that way. :-)

16:45 we're hiring!

16:45 jasapp: working from home ok?

16:46 ben_m: I'd relocate for a Clojure job

16:46 heh

16:46 chouser: http://www.sentryds.com/company/employment/

16:47 jasapp: I would, but my wife wouldn't

16:47 guess she'd just have to deal with it

16:47 ben_m: tell her it's clojure

16:47 She'll understand

16:47 eyeris: Is the complexity of expanding -> linear or better?

16:47 chouser: Many of us work from home. Some of us write in Clojure.

16:47 eyeris: -> is all at compile time -- no runtime cost

16:48 powr-toc: chouser: looks like an interesting company

16:48 eyeris: chouser: Right. I have a program that could be written as one huge -> macro with 1000+ forms.

16:48 hiredman: :(

16:48 eyeris: Would it take forever and a day to compile?

16:48 chouser: ha! I have no idea

16:48 ben_m: "4 year undergrad degree or higher"

16:48 Meh :(

16:48 Chousuke: eyeris: I think you wouldn't even notice the difference :/

16:48 hiredman: the compiler expands macros recursively (not iteratively)

16:50 stuartsierra: got to get my resume together

16:50 hamza: gents, is there a way to check if calling deref on a future object will block or not?

16:50 Chousuke: future-done? I think

16:51 hamza: ,(doc future-done?

16:51 clojurebot: EOF while reading

16:51 hamza: ,(doc future-done?)

16:51 clojurebot: "([f]); Returns true if future f is done"

16:52 hiredman: man, github fails horribly at displaying Compiler.java

16:52 hamza: Chousuke: thanks a lot, hate it when functions have obvious names :)

16:52 hiredman: I guess it could be firefox fails at displaying github displaying Compiler.java

16:54 Apage43: i'd tell you how IE6 handles it but I don't think it'd be worthwhile to know

16:54 stuartsierra: So I was thinking about rewriting clojure.test yesterday.

16:54 But I don't know if it's worth the trouble.

16:56 chouser: stuartsierra: what would you do to it?

16:56 stuartsierra: Redesign around first-class objects.

16:56 I.e., a Test is a collection of Assertions.

16:57 eyeris: Indeed, hiredman, a ->> macro with 1000+ forms results in a stack overflow :(

16:57 Darn

16:57 stuartsierra: a Test runs in one or more Contexts

16:57 Contexts are nested hierarchically..

16:58 Running a set of tests produces a sequence of TestResults

16:59 technomancy: I like the idea of more separation between assertions and the setup they require. the intermixing of these is probably the greatest hindrance to test readability in my experience.

16:59 stuartsierra: yes, that was the big idea

17:00 Writing tests as fns is easy, but mixes assertions with setup/teardown.

17:00 That's one thing that object-oriented test frameworks actually do better.

17:00 powr-toc: Is there an explanation of what Cells are yet... I saw the discussion on this channel about them, but would like to understand more about them

17:01 chouser: powr-toc: your most complete and accurate info will be IRC for a while. They're too much in flux to warrant real docs yet.

17:01 powr-toc: there is the implementation and "notes" links -- you saw those?

17:02 powr-toc: chouser: no, I don't think I did... Are they on assembla?

17:02 chouser: powr-toc: src/java/com/sentryds/qdc/rpc/clojure.clj

17:02 er

17:02 not that

17:02 hiredman: it is amazing how fast stuff goes from rhickey saying "I am playing around with idea X" to everyone demanding docs for X

17:02 chouser: powr-toc: http://gist.github.com/306174 and http://www.assembla.com/wiki/show/clojure/Cells

17:02 powr-toc: hiredman: lol

17:02 Chousuke: hiredman: heh

17:02 stuartsierra: hiredman: Because no one understand's rhickey's code.

17:02 rhickey: ouch

17:03 Chousuke: stuartsierra: I think that only applies to java

17:03 stuartsierra: rhickey: No offense meant, it's beautiful code.

17:03 powr-toc: Chousuke: yeah I saw that gist... somehow missed those notes though

17:03 stuartsierra: It's just so abstract that it's rarely obvious what it's for.

17:05 hiredman: rhickey is fluent in the language he is writing while the rest of use running around with dictionaries

17:06 stuartsierra: hiredman: good analogy

17:06 Re testing again, the problem I'm stuck on is how to share values between assertions and setup/teardown.

17:06 clojure.test fixtures do it via dynamic bindings, but the syntax is awkward.

17:06 powr-toc: Chousuke: I've found that the java code I've looked at has mostly been very clean and readable... Just very un-idiomatic... I've only skimmed it though

17:07 stuartsierra: And if you're not defining setup and assertions in the same fn body, you can't use let-bindings.

17:08 Chousuke: powr-toc: I suppose the un-idiomatic feel comes from the functional data structures used and the style in general. at least the reader was like that.

17:08 hiredman: stuartsierra: unless you use eval

17:08 er

17:08 stuartsierra: But eval doesn't capture lexical scope, right?

17:08 hiredman: forget I said that

17:08 :/

17:09 stuartsierra: ,(let [x 42] (eval 'x))

17:09 clojurebot: DENIED

17:09 stuartsierra: Anyway, it throws "x not defined"

17:11 chouser: you could put the tests inside the setup/teardown via macros.

17:11 stuartsierra: I thought about that.

17:11 chouser: do you setup/teardown per test?

17:11 stuartsierra: I want to support both options: once per test and once per test suite.

17:12 But if the assertions are inserted into the setup/teardown code, then there could be a clash of locals.

17:12 hiredman: you can have the assertion creation macro analyze forms for free symbols and generate a function taking a map that does keyword destructuring

17:12 stuartsierra: And setup/teardown contexts are no longer reusable.

17:12 chouser: don't you *want* to capture the locals?

17:12 stuartsierra: no

17:12 chouser: then what are you setting up?

17:13 stuartsierra: Or, I want something that *looks* like local capture, but in a safe manner.

17:13 hiredman: That's where I might be headed.

17:13 But it seems so complicated.

17:14 I want something that looks more like fn pre/post conditions.

17:14 chouser: (defwrap foo (let [a ... b ...] (.open b) :insert-tests-here (.close b))) (with-wrap foo (.write a "blah"))

17:14 hiredman: tree-seq is your friend

17:14 technomancy: stuartsierra: per-test-suite really means per-ns, right?

17:14 stuartsierra: technomancy: In the current definition of a suite-as-namespace, yes. But

17:15 Ideally, I'd want to support nested suites.

17:15 hiredman: why?

17:15 clojurebot: why not?

17:15 hiredman: clojurebot: thanks!

17:15 clojurebot: Excuse me?

17:15 technomancy: if you support nested contexts wouldn't that amount to the same thing?

17:15 hiredman: nesting :(

17:15 stuartsierra: Not quite.

17:16 I tried to make it possible to run a single test at the REPL by calling a function.

17:16 With fixtures, that doesn't work, because the test function doesn't know which fixtures it needs.

17:16 But if the test retains a reference to the contexts it needs, it can be run by itself.

17:17 Or in the context of a test suite, without running fixtures more times than necessary.

17:18 ordnungswidrig: stuartsierra: oh running single tests would be very nice

17:19 stuartsierra: clojure.test already supports that, just not with fixtures

17:19 technomancy: ordnungswidrig: clojure-test-mode makes that pretty easy in Emacs

17:19 StartsWithK: stuartsierra, i used http://paste.pocoo.org/show/179465/ a syntax similar to let form in my tests, is this what you would like to do?

17:20 ordnungswidrig: technomancy: really? I always run all tests using C-,

17:20 Raynes: technomancy: Ola Bini apparently heard my cries. He's strongly considering moving Ioke to a new repo with no history. :D

17:20 StartsWithK: for once/every i was planing to use memoize over the setup function, but don't need that for now

17:21 stuartsierra: StartsWithK: That's pretty close to what I had in mind.

17:21 technomancy: Raynes: high-five

17:22 ordnungswidrig: C-c M-,

17:22 ordnungswidrig: technomancy: nice, I'll try

17:25 * triyo just finished my wedding rsvp site in clojure, compojure + mongodb

17:27 dakrone: triyo: neat, is it opensource?

17:28 cemerick: stuartsierra: did you leave out basic auth in http.connection intentionally?

17:28 triyo: dakrone: well not as of yet. I'm gonna clean up the code a bit over the weekend, hopefully, and put it up on github.

17:28 stuartsierra: cemerick: no, just an omission

17:28 dakrone: triyo: cool, look forward to it :)

17:29 stuartsierra: cemerick: http.connection is another child of mine that needs to die

17:29 Not to sound nihilistic or anything.

17:29 cemerick: replaced by?

17:29 stuartsierra: Something involving the Apache HTTP client.

17:29 cemerick: heh

17:30 I suggested that many moons ago, but people didn't like the notion of 3rd party deps.

17:30 ;-)

17:30 stuartsierra: Another reason why contrib itself needs to die.

17:30 Basically, everything sucks. ;)

17:30 cemerick: That's funny, since you're probably the leading contributor :-D

17:30 stuartsierra: I know.

17:30 cemerick: but yes, I absolutely agree

17:31 stuartsierra: If rhickey could stop revolutionizing computer science long enough to care about menial details like packaging...

17:31 Or if Maven 3 really IS a unicorn...

17:32 * triyo immigrated namespaces suck. Compojure *errors* binding as an example :)

17:32 stuartsierra: triyo: immigration doesn't work

17:32 hiredman: yeah, compojure is hardly a beacon of light for the masses

17:33 jasapp: hiredman: why do you say that?

17:33 hiredman: the use of immigration for one

17:33 triyo: hiredman: once you dive beyond a hello world web apps, it stings.

17:33 cemerick: stuartsierra: at a certain point, I'm going to have to start caring about what rhickey is doing only once every 3 months or something ;-)

17:33 hiredman: the single segment namespace, but that should be fixed next release

17:34 I mean it works, and is fine, but it is not a paragon of style

17:34 cemerick: anyway, binding start-http-connection is a perfectly decent way of adding basic auth to contrib.http :-)

17:34 stuartsierra: cemerick: Ah, good. Glad to be of service. :)

17:35 hiredman: cemerick: until direct binding bites!

17:35 technomancy: I thought base64 was added to contrib specifically to support auth in contrib.http

17:35 jasapp: I'm trying to think of web frameworks that are paragons of style

17:35 technomancy: or was that something other than basic auth

17:35 cemerick: hiredman: direct binding?

17:35 stuartsierra: technomancy: I started base64 but quit before I finished.

17:35 hiredman: jasapp: ok, but immagration and single segment namespaces are *grossly* bad style

17:35 technomancy: heh

17:35 hiredman: cemerick: no rebinding

17:36 jasapp: agreed.

17:36 Chousuke: single-segment namespaces aren't just bad style, they break things :P

17:36 cemerick: hiredman: totally not following you (not the firs time, tho ;-) )

17:36 hiredman: immigration

17:37 cemerick: as mentioned single segment namespaces break stuff

17:37 jasapp: can you explain? I have no idea what immigration is

17:37 hiredman: and immigration is just icky

17:37 triyo: agreed

17:37 to much magic :)

17:37 somnium: the immigration was a failed experiment, but the goal was noble

17:37 hiredman: it re-defs stuff in a new namespace basically

17:37 jasapp: ahh, ok

17:38 hiredman: somnium: road to hell... etc

17:39 Raynes: I read that as 'rot in hell'.

17:39 :o

17:39 somnium: hiredman: noble goals are the road to hell?

17:39 _mst: good intentions :)

17:40 hiredman: http://idioms.thefreedictionary.com/road+to+hell+is+paved+with+good+intentions

17:48 kylesmith: Is anyone here good at writing parsers?

17:50 shrughes: it depends how you want to write them

17:50 hiredman: if I was any good writing parsers why would I use lisp?

17:50 triyo: hehehe

17:50 hiredman: I kid, I kid, I love the parens

17:51 kylesmith: I need a parser for CIF files, but some of the files do not follow the format exactly.

17:52 * triyo clojure destructuring + some pattern-patching goes very far in clojure IMHO

17:52 triyo: * patching=matching

17:53 hiredman: fnparse is the only clojure parser library I have used at all, it is ok

17:53 kylesmith: FYI, the files are in this zip file http://www.crystallography.net/cod.zip (BEWARE, 314 MB)

17:54 hiredman: constantly under developement and changing though

17:54 which can be a drag

17:55 kylesmith: I don't mind using a library, but due to the irregular nature of these files, I need to be able to first try the correct way to parse the file, then try another way, etc.

17:55 hiredman: sure

17:56 fnparse just creates functions that have a certain input and output

17:57 triyo: night all

19:11 powr-toc: Does anyone else find it annoying that the API docs at http://richhickey.github.com/clojure/ don't link back to clojure.org? It's hard to browse to the docs for special forms etc...

19:14 technomancy: powr-toc: I think the real problem is that so many special forms lack docstrings

19:14 or they just say "see clojure.org for details"

19:14 powr-toc: technomancy: yeah, that's really annoying too

19:15 technomancy: what's the procedure for submitting documentation patches/suggestions?

19:15 can I just github fork?

19:15 presumably I'll need to sign a contributor agreement

19:15 technomancy: powr-toc: yeah, but don't use pull requests. http://clojure.org/contributing

19:15 that too

19:17 powr-toc: I also find the docs for reduce a little cryptic... Especially how it doesn't document the form of the function you pass it very well.

19:23 technomancy: reduce is really hard to explain well without some sort of visual aid

19:24 powr-toc: technomancy: true... but my problem isn't in understanding reduce, more remembering the order of arguments for the supplied function... I always get the accumulator and current item mixed up

19:24 and the docs dont even mention the order of arguments there

19:28 dnolen: ,(:arglists ^#'reduce)

19:28 clojurebot: ([f coll] [f val coll])

19:30 powr-toc: dnolen: yes, but reduce requires f to take two arguments. The order of those arguments are not mentioned.

19:32 dnolen: powr-toc: yeah I see what you mean. I suppose that's what clojure.contrib.repl-utils source is good for. In Emacs I'm always jumping into the core definitions to see how things work. refreshing actually coming from other langs.

19:34 powr-toc: dnolen: ahhh a handy package, thanks for the pointer... yeah having clojures source code to hand is seriously handy and far more accessible than in most languages

19:39 dnolen: powr-toc: only thing cooler

19:39 will be when Clojure is written in Clojure. will be almost Smalltalkish then

19:41 powr-toc: dnolen: yeah that'll be sweet! But I do worry that the whole bootstrapping/meta-circularity thing might make things a little less accessible

19:41 hamza: guys, I have a func called start defined in leiningen.start namespace but lein is not picking it up. lein help start says it can't find the file but it is there this in a fresh lein project.

19:42 dnolen: powr-toc: in what way do you mean?

19:42 hamza: and is your source organized src/leiningen/start.clj ?

19:43 hamza: dnolen: yeap its the only file there..

19:45 powr-toc: dnolen: I think clojure in clojure will totally rock, and absoloutely is the way to go... I just think a big part of my learning clojure was digging through the clj and java source code and seeing things grounded in a language I knew (Java)... If it's turtles all the way down, that learning process is harder

19:46 dnolen: Plus you'll need a build of a clojure to build clojure, which makes the build process more convoluted

19:46 dnolen: hamza: hmm I'm assuming you're writing a plugin, I note that lein-swank itself can't work that way.

19:46 powr-toc: dnolen: But everything else is pure upside!

19:48 hamza: yeap its a plugin, are you saying i can't test it until i build a jar and add as a dev-dep?

19:48 dnolen: hamza: I just wrote my first lein plugin for dealing with native deps today, and I know it works if you build a jar and add as a dev-dep.

19:49 hamza: and put in your lib directory

19:50 hamza: dnolen: kk so during testing just mock something for the arguments to the function?

19:50 dnolen: powr-toc: heh, not knowing Java well, I haven't had the experience you have. It also seems Clojure attracts a lot of people with only passing familiarity with Java. Being written in Clojure widens the number of people interested in contributing core code.

19:51 hamza: heh, I didn't bother writing any tests for my plugin too simple for that really. but that sounds like a good approach.

19:51 hamza: dnolen: kk thanks alot.

19:53 slyphon: argh, i hate log4j

19:53 powr-toc: dnolen: I don't disagree... I just think it's a sign of clojure growing up... I'm happy for it to become an adult, but I'll miss its childhood.

19:55 nuggien: if i have a java class Foo with a constructor like Foo(Bar b) where Bar is an interface and Baz is a class implementing Bar, and in clojure I do (let [x (Foo. (Baz.))] ...) why does it keep telling me Baz cannot be cast to Bar?

19:56 chouser: What you describe should work. Are you very very sure you're creating a Baz, that Baz implements Bar, and that Foo's ctor takes a Bar?

19:57 nuggien: yes, does it matter if both Foo and Baz are declared as final?

19:59 chouser: I don't think so.

19:59 try (instance? Bar (Baz.))

20:00 nuggien: yes that returns true

20:00 powr-toc: nuggien: No, I can't imagine how... final classes prevent java inheritence

20:01 nuggien: Have you cleaned and recompiled your java code? You might have stale class files

20:01 nuggien: powr-toc: this is just using classes in the unit testing jars that come with google app engine

20:02 powr-toc: nuggien: is the constructor public?

20:02 nuggien: basically the line: private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()); from

20:02 http://code.google.com/appengine/docs/java/tools/localunittesting.html

20:02 LocalDatastoreServiceTestConfig is a final class implementing the LocalServiceTestConfig interface

20:04 i can do (cast LocalServiceTestConfig (LocalDatastoreTestConfig.)) just fine in the repl

20:05 chouser: what about the ctor. can you use repl-utils 'show' to confirm the ctor you want is there?

20:05 nuggien: but as soon as i pass that to LocalServiceTestHelper, it bails out saying it can't cast LocalDatastoreServiceTestConfig to LocalServiceTestConfig

20:05 chouser: let me try that

20:06 i guess this line is the constructor? [ 2] (class [Lcom.google.appengine.tools.development.testing.LocalServiceTestConfig;)

20:07 chouser: looks like it wants an array

20:07 varargs in java is an array for objects in Clojure

20:07 nuggien: the [L is array?

20:07 powr-toc: yes

20:09 hiredman: [ is an array

20:10 nuggien: what is the L for?

20:10 hiredman: the L and the ; at the end are just part of reference type names

20:11 nuggien: thank you all, it seems to work now

20:11 hiredman: the jvm has two or three different ways of giving type names, and Ljava.lang.Object; is one of them

20:11 also java/lang/Object

20:24 slyphon: hiredman: did you know another lisp before clojure?

20:51 hiredman: slyphon: I'd poked at scheme a little, but just sort of hello worldish stuff

20:52 slyphon: i read through the "programming clojure" prag-prog book, i'm wondering what else is out there that's good

20:52 technomancy: Qi is spoken highly of by rich

20:52 slyphon: Qi?

20:53 technomancy: Qi!

20:54 http://www.lambdassociates.org/

20:54 scgilardi: http://en.wikipedia.org/wiki/Qi_%28programming_language%29

20:56 slyphon: man, you know, i just had to pull the ex-nasa-physicist-pretending-to-be-a-CS-professor

20:57 who argued with me that OO was useless because "it's just another way of referring to a pointer"

20:57 and wondered why everyone didn't just write MASM

21:01 not that i'm bitter or anything

21:05 lithpr: wow, that

21:05 Qi book looks very interesting

21:23 ag90: A question about GUI programming: Assuming that I'm using Swing, is there a more functional or lisp-y way to write the GUI instead of the standard Java imperative way? If not, what about other toolkits (like SWT)?

21:25 Modius: Is there a macrolet/environments in Clojure? Just need a name to look up if there is.

21:26 ag90: Modius: Do you mean this? http://richhickey.github.com/clojure-contrib/macro-utils-api.html#clojure.contrib.macro-utils/macrolet

21:26 Modius: ag90: Is the expansion environment available?

21:28 ag90: Modius: I don't know. I was just guessing.

21:28 TheBusby: contextual macros? the idea is interesting, but sounds a little dangerous

21:33 lancepantz: how do you use the class? function?

21:33 it only takes one argument, but i would expect it to take an instance and a class name

21:33 and return true if that instance is in that class

21:34 arohner: ag90: stuart sierra had a few blog posts on the topic...

21:35 ag90: http://stuartsierra.com/tag/swing

21:35 lancepantz: it returns true if the object you pass it is a class

21:35 as opposed to say, a number

21:35 lancepantz: maybe you want instance?

21:36 lancepantz: ah

21:36 yes, thank you :)

21:37 and i can pass the expected class as a string, correct?

21:38 looks like i cant

21:38 arohner: the actual class object

21:39 ,(instance? String "hello world")

21:39 clojurebot: true

21:39 arohner: ,(instance? String 42)

21:39 clojurebot: false

21:39 lancepantz: got it

21:39 thanks

21:39 arohner: np

22:17 TheBusby: Hmm, how would this work? (magic even? [1 2 4 6 5 5 5 7 8 8 10 11]) => [2 6 8 10]

22:18 chouser: who no 4?

22:19 TheBusby: looking for the bounds of valid ranges

22:19 "why no 4" right?

22:20 chouser: I thought you wanted distinct even values, but that would ahve included 4 in the output.

22:21 TheBusby: yeah, filter and distinct would have been a good option then

22:21 but finding the boundary values...

22:22 was hoping that maybe there was a split function where I could get (magic-split even? [1 2 4 6 5 5 5 7 8 8 10 11]) => [ [2 4 6] [8 8 10] ]

22:26 arohner: TheBusby: so you're looking for seqs of consecutive values that pass the predicate?

22:26 TheBusby: arohner: yes

22:26 arohner: I think you'll have to write that

22:27 TheBusby: k, just wanted to make sure there wasn't something hiding in contrib or somewhere that I wasn't aware of

22:27 I know re-seq kind of does what I want for strings, so I thought a more general function might be hiding somewhere

22:28 lancepantz: anyone mind helping me get this recursive function correct? http://www.pastie.org/830208

22:28 it returns nil, but i'm expecting it to return a nested map

22:30 chouser: ,(use '[clojure.contrib.seq :as seq])

22:30 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/seq__init.class or clojure/contrib/seq.clj on classpath:

22:30 chouser: ,(use '[clojure.contrib.seq-utils :as seq])

22:30 clojurebot: nil

22:30 chouser: ,(->> [1 2 4 6 5 5 5 7 8 8 10 11] (seq/partition-by even?) (filter (comp even? first)))

22:30 clojurebot: ((2 4 6) (8 8 10))

22:30 TheBusby: ah, partition-by!

22:31 chouser: much thanks!

22:31 chouser: ,(->> [1 2 4 6 5 5 5 7 8 8 10 11] (seq/partition-by even?) (filter (comp even? first)) (map (juxt first last)))

22:31 clojurebot: ([2 6] [8 10])

22:32 arohner: lancepantz: doseq returns nil

22:35 dannycoates: can anyone here help a noob compile clojure-clr? I've got 3 build errors

22:36 lancepantz: arohner: is there a different function i should use instead, or is my approach flawed?

22:37 maybe loop/recur?

22:37 arohner: lancepantz: I'm not entirely sure what you're trying to accomplish

22:37 lancepantz: hahah

22:38 i've got a nested yaml string, and snakeyaml returns a nested java.util.LinkedHashMap, i'm trying to recursively turn that into clojure maps

22:38 *turn that into a clojure map of clojure maps

22:44 arohner: lancepantz: try using reduce and assoc

22:45 lancepantz: k, ty!

23:15 TheBusby: data

23:16 chouser: code

23:16 TheBusby: whoops, sorry wrong window :)

23:56 lancepantz: alright, got it

23:57 arohner: this is what i was trying to do:: (defn to-seq [data] (into {} (for [[k v] (into {} data)] [k (if (instance? java.util.LinkedHashMap v) (to-seq v) v)])))

23:58 arohner: cool

Logging service provided by n01se.net