#clojure log - Nov 25 2009

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

0:26 technomancy: KirinDave: I think I got the bootstrapping issues sorted out for leiningen; sorry about the rough spots.

0:26 self-hosting is Fraught with Peril.

0:30 danlarkin:

0:37 defn: technomancy: what do you do your blog with?

0:39 technomancy: defn: I use this script: http://p.hagelb.org/Rakefile.html

0:39 along with htmlize from Emacs for code snippets

0:40 defn: cool, thanks

0:41 technomancy: comments are done with a short ruby CGI script, but it's not very good, so I won't share it.

0:45 chouser: ,(last 2 (range 10))

0:45 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$last

0:45 chouser: hmph

0:46 ,(take-last 2 (range 10))

0:46 clojurebot: (8 9)

0:46 chouser: ah, there it is

0:47 kzar: in case you still care

1:02 efarrar: hello!

1:02 chouser: efarrar: ha!

1:03 er, hi!

1:03 efarrar: I'm trying to work through translating this (http://www.arduino.cc/playground/Interfacing/Java) to clojure

1:03 pretty much plain old reading from an io stream

1:04 and I've got it sort of reading, i can often get the \H out

1:04 but think i'm running up against a problem of blocking io in this loop: http://gist.github.com/242517

1:06 have i somewhat correctly transliterated the loop from java to clojure?

1:09 KirinDave1: technomancy: That's awesome news

1:10 technomancy: KirinDave1: and this time I've actually tried it instead of just informally reasoning about it.

1:10 I realized informal reasoning doesn't work for shell scripts.

1:10 KirinDave1: :D

1:11 technomancy: A nice guy on the mailing list gave me a built version.

1:11 technomancy: ah, good old sourdough software

1:28 hiredman: clojurebot: ping?

1:28 clojurebot: PONG!

1:32 chouser: efarrar: yes, that's pretty much the same, though that nested java loop is a little weird

1:33 ...and in clojure, to have a loop like that the doesn't return a value is also a little weird, though not unheard-of in IO stuff.

1:52 defn: Good god -- Why do people use these site generator thingamabobs?

1:52 What a f****ing headache.

1:58 efarrar: (if (< 0 (. istream available)) (print (char (.read istream)))) ; works

1:58 (while true (if (< 0 (. istream available)) (print (char (.read istream))))) ; never prints anything

2:00 hoeck1: efarrar: maybe you need println or `flush' after each print to actually see the output?

2:00 hiredman: if you close the stream that automatically flushes

2:01 so if you close your streams properly you never have this problem anyway

2:10 efarrar: wow

2:10 println did it

2:10 vs print

2:11 i mean its now printing each char on it's own line, but it is progress

2:11 thanks guys

2:11 hiredman: yeah

2:11 you aren't closing the stream properly

2:17 tomoj: looks like a vector in destructuring bind ignores any unmentioned elements?

2:17 so [[foo bar] aseq] gets you the first two into foo and bar and doesn't care if there are more?

2:18 hiredman: correct'

2:18 tomoj: I realized I was writing ugly literals like [[k1 v1] [k2 v2]] for some reason :(

2:27 alexyk: is there a fold, in addition to reduce?

2:28 hiredman: uh

2:28 what would the difference be?

2:28 alexyk: hiredman: init value of a different type and function reducing to that

2:28 hiredman: alexyk: reduce can take an init value

2:29 ,(doc reduce)

2:29 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the r

2:29 alexyk: hiredman: ah, so it's a fold, too.

2:29 hiredman: ,(reduce conj () [1 2 3 4])

2:29 clojurebot: (4 3 2 1)

2:31 alexyk: cuute

2:31 defn: that's interesting

2:31 never seen that before

2:32 hiredman: it's very handle

2:32 it's very handy

2:32 defn: why is it in reverse?

2:33 the result I mean...

2:33 hiredman: ,(conj () 1)

2:33 clojurebot: (1)

2:33 defn: because that's how conj acts on vectors?

2:33 hiredman: ,(conj (conj () 1) 2)

2:33 clojurebot: (2 1)

2:33 hiredman: etc

2:33 defn: ahhhh, right

2:33 cool

2:33 conj is actually acting like cons here, no?

2:34 hiredman: with the arg order reversed

2:34 ,(cons 2 (cons 1 ()))

2:34 clojurebot: (2 1)

2:35 defn: so forgive me, but a () is just a list always right? I get a little confused with the context switch between seqs and other types

2:35 efarrar: ,(+ 1 1)

2:35 clojurebot: 2

2:35 efarrar: nice

2:36 defn: heh

2:36 hiredman: () is a list

2:37 defn: i guess ive just been confused by the quoted form and the () form, since you can't (cons 0 (1 2 3))

2:37 which seems to make sense to me, instead you have to quote it

2:37 why is that?

2:37 hiredman: sure, () is special cased

2:37 I mean, it's obviously not a function call

2:38 defn: but why the need to quote in the case of (cons 0 (1 2 3)), but not when you (cons 2 (cons 1 ()))?

2:38 hiredman: because () is special cased

2:39 defn: oh, i see what you're saying

2:39 you can only cons onto an empty list, not onto a list with values, unless you quote it

2:39 hiredman: no

2:39 that is not qhat I am saying at all

2:39 defn: ,(cons 0 ())

2:39 clojurebot: (0)

2:39 defn: ,(cons 0 (1 2))

2:39 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

2:40 defn: I think maybe I'm not being clear

2:40 hiredman: that has nothing to do with cons

2:40 it is the expression (1 2)

2:40 defn: is that not a list?

2:40 hiredman: lisp treats lists as function calls

2:41 what is the difference between the lists (+ 1 2) and the list (1 2 3)?

2:41 defn: the function

2:41 (+)

2:41 hiredman: there is no difference

2:41 they are both lists

2:42 defn: haha, yes, but one of them does contain a function, where the other does not, no?

2:42 hiredman: literal lists are all treated as function calls

2:42 defn: a function is just another value

2:42 tomoj: even () ?

2:42 defn: () is the special case

2:42 hiredman: tomoj: if you scroll up, you will see I am trying to explain that () is a special case

2:42 tomoj: I see

2:43 defn: hiredman, i see what you're saying now, the populated list is in essence a function, it returns itself?

2:43 hiredman:

2:43 no

2:43 defn: lol damnit

2:43 hiredman: a function is just another value

2:43 tomoj: if it returned itself (+ 1 2) would be '(+ 1 2), no?

2:44 hiredman: so there is no difference between (+ 1 2) and (1 2 3)

2:44 so they are both treated as function calls

2:44 1 is not a function, so you get an exception

2:45 tomoj: on the other hand you have

2:45 hiredman: a compiler/interpreter is more or a less a giant switch statement

2:45 tomoj: ,'([1 2] 0)

2:45 clojurebot: ([1 2] 0)

2:45 efarrar: ,(class ())

2:45 clojurebot: clojure.lang.PersistentList$EmptyList

2:45 tomoj: ,([1 2] 0)

2:45 clojurebot: 1

2:46 hiredman: tomoj: vectors are functions

2:46 defn: ok, so... () is a special case because there is nothing for a function to act on, whereas when you have (1 2), by virtue of the fact that it is in (), the 1 is treated as a function, and so you get the exception?

2:46 tomoj: which makes me quite happy :)

2:46 efarrar: ,(class '(1))

2:46 clojurebot: clojure.lang.PersistentList

2:46 hiredman: so that has no effect on this disucssion

2:46 defn: no!

2:46 () is a special case because there is no function to call

2:47 defn: that's what i was saying i suppose

2:47 hiredman: (foo) has nothing for the funtion to act on, but it is still a function call, just with no args

2:47 defn: nothing for a function to act on within the ()

2:47 because there is no function in ()

2:47 hiredman:

2:47 sure

2:48 defn: but once you have (1), the first of that list will be treated as a fn

2:49 hiredman: it's not "the first of the fn is treated as a function" it's a list of size greater than zero is a function call, and it just happens the function to call goes at the front of the list

2:49 but oh, we wanted a function but got a number, better throw an exception

2:49 tomoj: hmm.. () is nil in CL

2:49 defn: hehe tomoj

2:49 tomoj: I wonder if this is the same special case, since '() is nil too

2:49 defn: it's different in clojure

2:50 tomoj: or if they're doing what seems right to me, calling no function gives you no result

2:50 hiredman: I mean literal a special case

2:50 I expect there is a case in a switch statement, or if statement, in the compiler

2:50 defn: hiredman, i think you might have just answered my question, but if I do:

2:50 hiredman: that says for () emit ()

2:50 defn: ,(asdf 1)

2:50 clojurebot: java.lang.Exception: Unable to resolve symbol: asdf in this context

2:50 defn: ,(1 asdf 1)

2:50 clojurebot: java.lang.Exception: Unable to resolve symbol: asdf in this context

2:51 defn: why doesnt it throw any error about the iFn?

2:51 tomoj: I guess clojure evals the args before trying to call the function?

2:51 hiredman: because symbols are resolved before functions are called

2:51 defn: ahhh, thank you so much

2:52 hiredman > *

2:52 efarrar: just think of 1 as a symbol, but luckily it is symbol that resolves to the number 1

2:52 defn: 1 is not a symbol

2:52 efarrar: so since one resolves ok, it goes on to try the next part of the expression

2:52 defn: well at least not in my reasoning

2:52 efarrar: where it hurls

2:52 defn: 1 is a primitive

2:53 tomoj: wouldn't have surprised me if it barfed before evaling asdf because 1 isn't an IFn

2:53 1 isn't a primitive :/

2:53 defn: i think we made hiredman angry

2:53 tomoj: I guess it can be in some places maybe?

2:53 efarrar: after it's resolved all of them, it goes back and tries to call the function

2:54 defn: im relying on some very spotty reminder of SICP where Sussman talks about the primitives of a language, and IIRC mentions the integers 0-9

2:54 as being primitives

2:54 tomoj: yeah that's the strange thing to me, it shouldn't need to resolve all the args

2:54 arohner: defn: scheme isn't clojure

2:54 hiredman: defn: efarrar is proposing a thought experiment

2:55 tomoj: once it's got 1, it could just bail out

2:55 doesn't matter what the args are, you can't call 1

2:55 that doesn't matter anyway I suppose

2:55 defn: efarrar: yeah i suppose your way of reasoning makes sense in this case

2:55 hiredman: I could easiliy imagine a lisp where numbers are symbols, and the symbol resolution step just turns the number

2:56 defn: what do you mean by "turns"?

2:56 efarrar: it's also the way that many homo-iconic languages choose to deal with primitives, to make "1" a valid symbol, that happens to return 0x0001 or whatever

2:56 hiredman: returns

2:56 defn: ahhh

2:56 hiredman: actually, I'm kind of thinking of using numbers to represent symbols in this compiler I am toying with

2:57 tomoj: efarrar: what's an example of one of these languages?

2:57 hiredman: hmmm

2:57 tomoj: I would be surprised if I couldn't add numbers in my macros without evaling them as symbols

2:57 hiredman: clojurebot: history?

2:57 clojurebot: No entiendo

2:58 hiredman: ~google history of lisp

2:58 clojurebot: First, out of 134000 results is:

2:58 History of Lisp

2:58 http://www-formal.stanford.edu/jmc/history/lisp/lisp.html

2:58 defn: god, i've felt like a noob before, but never as much as right now

2:58 hiredman: great paper, guy steele and some other guy whose name I always forget

2:58 defn: people have been coding lisp for 40+ years, and here I am just getting on board

2:59 if i ever have children interested in programming I will force them to learn lisp first, the rest second

2:59 hiredman: there used to be a huge diversity of languages called lisp, before the ai winter

2:59 defn: ai winter being post mid-1980s?

3:00 hiredman: I am sure one of them, some where, treated numbers as symbols at some point

3:00 defn: sounds right, the actually timeline didn't stick as well as the catchy name

3:01 defn: The worst times for AI were 1974−80 and 1987−93.

3:01 (per the wiki article)

3:01 1987 == Collapse of the lisp machine market

3:02 http://en.wikipedia.org/wiki/Fifth-generation_computer

3:02 that's an interesting article

3:02 hiredman: that link from google is not the history of lisp I was looking for

3:04 defn: http://www.infoq.com/presentations/Lisp-Guy-Steele-Richard-Gabriel

3:04 Why is InfoQ so crappy and so great at the same time?

3:05 hiredman: I found a pdf of it online

3:07 ah!

3:07 ~google the evolution if lisp

3:07 clojurebot: First, out of 13900 results is:

3:07 Lisp (programming language) - Wikipedia, the free encyclopedia

3:07 http://en.wikipedia.org/wiki/Lisp_(programming_language)

3:07 hiredman: ~google the evolution of lisp

3:07 clojurebot: First, out of 31200 results is:

3:07 The Evolution of Lisp

3:07 http://www.dreamsongs.com/NewFiles/HOPL2-Uncut.pdf

3:07 hiredman: that one

3:07 ++

3:07 A++

3:13 defn: thanks hiredman

3:15 Yuck. It's Richard "Fineman" not "Feighn-men"

3:16 tomoj: I have a vector like [[[k1, foo], v1], [[k2, bar], v2], [k3, baz], v3]

3:16 is it possible to get two lazy seqs (k1, k2, k3) and (v1, v2, v3) without walking this vector twice?

3:18 at this point it doesn't really matter since the vector isn't lazy anyway, but I'm just curious

3:18 I guess the idea might not even make sense, you can't have two lazy seqs which cooperate realizing something together

3:20 defn: My intuition tells me it's possible

3:20 but I couldn't tell you how

3:23 tomoj: my intuition tells me that if it is possible, it requires evilness to do it

3:24 if someone realizes some of the one seq, the other seq needs to somehow know this and not redo the work

3:34 defn: tomoj: yeah that becomes very weird

3:35 but i suppose i can conceive of some sort of function approaching 0 which is able to capture those on its way

3:35 does that make sense?

3:37 tomoj: uh

3:37 no :(

3:52 defn: Pascal is for building pyramids. Imposing, breathtaking, static structures built by pushing heavy blocks into place. Lisp for building organisms.

3:55 tomoj: the perfect combination of functions selecting points "around" the point they intend to meet, for any logical structure, over the course of a handful of generations, or thousands, approaches the answer you seek

3:56 tomoj: hmm

3:56 yes I really have no idea what you're talking about

3:57 defn: haha, im philosophizing a bit

3:57 but suppose you have 3 functions which take wild stabs at the point their intended result resides

3:58 now suppose they split off into smaller pieces, inching closer towards their "goal"

3:58 tomoj: are you stoned

3:58 defn: yes

3:59 tomoj: ah, now I understand

3:59 defn: 100% -- not even joking

4:00 but no I just am saying that if we have what we describe functions, they can be part of a larger system which inches them towards our intended result

4:00 describe as*

4:02 so the purely functional thing is great, but that's why Lisp > Haskell IMO, because you can create those side-effect laden state-loving function-manipulating entities in order to evolve your pure structures in ways they couldn't do on their own

4:04 tomoj: just tell me to shut up if this is ridiculous

4:06 tomoj: I don't know if it's ridiculous or not

4:06 I can barely parse it

4:06 defn: little pure bits manipulated by impure bits

4:07 err impure "bytes"

4:08 ordnungswidrig: hi all

4:09 tomoj: don't talk about your impure bits in public

4:13 licoresse: Good morning

4:18 hoeck1: ordnungswidrig, licoresse: good morning!

4:20 licoresse: so, been away for a while, anything new?

4:22 had a peek at clojats

4:23 clojars

4:23 hoeck1: licoresse: how long have you been away?

4:23 licoresse: 1 month

4:27 hoeck: licoresse: there are now `protocols' in the new branch

4:28 licoresse: I'll have a look

4:28 any videos of protocols?

4:28 hoeck: licoresse: and the next release (1.1) is not that far away, only three patches left, from what Ive heard

4:28 licoresse: joy!

4:29 hoeck: licoresse: they are documented extensively in the docstring, and there is an assembla wiki-scratchpad page

4:29 licoresse: ok

4:29 hoeck: clojurebot: protocols

4:29 clojurebot: http://www.assembla.com/wiki/show/clojure/Protocols http://clojure-log.n01se.net/date/2009-10-13.html#12:02

4:31 hoeck: licoresse: and there is deftype for buildung small structlike objects dynamically, but thats about 1 month old, maybe you've already heard of it

4:31 licoresse: clojurebot: deftype

4:31 clojurebot: deftype is see datatype

4:32 licoresse: clojurebot: datatype

4:32 clojurebot: datatype is see datatypes

4:32 licoresse: clojurebot: datatypes

4:32 clojurebot: http://www.assembla.com/wiki/show/clojure/Datatypes

4:32 licoresse: ah

5:40 any clojure activity at wave.google.com?

5:42 ordnungswidrig: hi all

5:42 ups

5:50 liwp: licoresse: search for "with:public clojure" in wave

5:51 seems like there are 20 public waves with clojure in them

5:51 licoresse: ah, great, thanks

7:50 Bjering: I am 10 days into clojure now, and wow, I haven't had this much fun programming in 15 years!

7:52 rhickey: Bjering: Great! (sorry about the last 15 years)

7:53 AWizzArd: Bjering: grats! Sounds familiar to me :)

7:53 * AWizzArd thanks rhickey for Clojure

7:53 AWizzArd: I should do this every day.

7:53 rhickey: yw

7:53 AWizzArd: "Clojure - brings the fun back to programming"

7:54 Raynes: "Clojure - More fun than Python. Yes, I went there."

7:56 Bjering: rhickey, I saw your presentation "are we there yet" on info-q that really sold it to me. I am mainly a C++ guy and whenever I've been in Java och C# the lack of value-based programming made me uncomfortable.

7:57 I think that presentation was very important since it does not say "Clojure" in the subject it felt generally applicable and drew me (and I am sure other non-converts) in :)

7:58 rhickey: Bjering: yeah, avoiding talking about Clojure specifically was a goal of that talk

7:59 It includes an inside joke for Clojure users - "I wish there was a programming language where these persistent data structures were the default"

7:59 AWizzArd: That allowed me to forward this vid to several non (not-yet) devs.

7:59 Bjering: :)

7:59 AWizzArd: uhm, non-clojure devs

8:00 Bjering: My thinking during most of the talk was, I sure hope the boost guys watch this and make me a nice C++ lib.

8:02 From my perspective the whole modern C++ community is working really hard to do things "Clojure things" with template meta-programming and a focus on value-types.

8:03 rhickey: Bjering: it is certainly possible in most langs, but not idiomatic in many

8:04 Bjering: rhickey: I notice you usually compare against C# and/or Java, is this becuase you think C++ is long dead ;) Or because you think C++ has more things "right"?

8:05 rhickey: I think the lack of GC in C++ is a huge problem

8:06 Bjering: ref-counting with something like boost::smart_ptr isn't enough?

8:06 rhickey: no

8:07 * rhickey was writing smaprt ptrs and template calbacks in C++ long before boost was an idea

8:07 Bjering: You think its a huge problem in general, or did you mean specifically for the persistent datastructures?

8:07 rhickey: in general

8:07 cemerick: rhickey: you should toss out a "...and get off my lawn!", just for the hell of it ;-)

8:08 rhickey: cemerick: I'm not trying to discourage the questions, and am happy to oblige, really, just a little been there, done that :)

8:09 cemerick: rhickey: oh, I know. It doesn't come through irc, but that was a *huge* wink at the end of the line.

8:10 Bjering: Ok, well, honesly memory-management has never been a problem for me, i've had much more problems with such things in Java and C#, possibly because I was fooled into thinking "well I have gc, I dont need to care...". Now mutable state otoh, that just break things...

8:10 rhickey: Bjering: lack of standard GC completely changes library design

8:10 Bjering: But good C++ code has alot of immutable value-classes.

8:11 rhickey: Bjering: I've also become very sensitive to incidental complexity, and C++ is chock full of it

8:11 Bjering: agreed

8:12 rhickey: power/complexity is the key ratio

8:12 Bjering: I am already at 3/10 of knowing Clojure I think, and after 20 years of C++ I think I am barely at 6/10 ;)

8:13 cemerick: rhickey: what's your take on the "JRoR in front, clojure in the back" notion? I have to say, it makes a lot of sense from where I sit, even though I'd love to say clojure is the best solution end-to-end.

8:13 gerry`: jdk7 will support closures, any benefit to clojure?

8:15 rhickey: cemerick: people should do what is most productive. I think in the end there will be Clojure-based web tools that make Clojure devs most productive, but in a mixed skills shop multiple langs might make sense

8:15 personally I find ORM quite goofy and wrong

8:16 cemerick: indeed, but when you're not using an RDBMS, that issue goes away nicely :-)

8:16 rhickey: gerry`: hard to say

8:16 esj: rhickey: interesting! How do you think about DB backed apps ? (genuinely curious)

8:17 rhickey: cemerick: then what's rails doing for you?

8:17 cemerick: rhickey: I agree completely re: productivity. I just worry about the (perhaps large) population that expects a language to cover the full stack.

8:17 rhickey: esj: I think databases are great and people should really learn the relational model and stop being afraid of it

8:18 gerry`: rhickey: much less class files due to closures?

8:18 cemerick: rhickey: sane templating, tons of fiddly glue libraries for making working with HTML and js easy, etc.

8:18 rhickey: cemerick: well, the backend of say, Flightcaster, seems to me the harder job, so if you can cover that well then reaching the front end is a matter of libs and frameworks

8:19 cemerick: that's a matter of opinion, re: templating

8:19 cemerick: right, which is exactly why 99% of our "backend" as it were is in clojure

8:19 rhickey: yeah, templating is a very personal choice -- hard to argue on merits because of the huge variety in requirements + opinions.

8:20 Bjering: rhickey: How do you see best-pracitce for persistens (as in stored on disk! (what shall I call this now that you use the word in another meaning?)) working in clojure?

8:20 rhickey: my concentration for Clojure has always been about making a language suitable for the back end - that's where all the hard parts live

8:20 cemerick: I personally think that sexpr templating is insane.

8:20 rhickey: cemerick: I think the bigger issue is - where is the code, how does it interleave with the doc structure, if at all?

8:21 tomoj: cemerick: what about enlive-style?

8:21 rhickey: So, functional templating a la Enlive, String Template, GXP, all appeal to me

8:21 gerry`: #(int i, Strings) (i + s.length()) = #(fn [x y] (+ x (count y)))

8:21 Bjering: I mean, do you beleive in marrying a RDBMS transaction handling, so we can get similiar behavior to the STM only fully persisten. Some "ref" type that live on disc?

8:21 cemerick: tomoj: I like enlive a lot. I don't like the current state of the rest of the clojure web stacks.

8:21 rhickey: Bjering: that's impossible to answer generally

8:22 cemerick: ok, but that's a maturity thing, not a language capability thing

8:22 tomoj: I still haven't tried to do much of anything with compojure

8:22 chouser: In Soviet Russia, lazy sequences hold *your* head!

8:23 rhickey: but Clojure is pragmatic - being able to compose a solution with JRoR is just another feature

8:23 cemerick: rhickey: absolutely. I just can't spend our time on helping with web front end stuff, as it's simply not that important to us.

8:24 Bjering: Ok, if I try to be more specific, say your making a bank-system, with clojure as language, what would be the most convenient way to work Once and Once only with the transaction logic and still have it persistent?

8:25 I can see doing it with Refs in the STM, but then I'll have to duplicate it for my Database updates.

8:25 rhickey: Bjering: a huge issue with data and databases in general is that the business has a set of rules for the data - where should they live? probably not in apps

8:27 cemerick: when I look at RoR I see an incidental-complexity fest

8:27 Bjering: ...and for now you are happy to replace Java, not SQL :)

8:27 cemerick: rhickey: even leaving aside activerecord?

8:27 rhickey: yes

8:28 cemerick: but I can't say I've spent much time with it (RoR), just evaluated and rejected

8:29 gerry`: Bjering: in your case , just use database logic not use clojure STM to do that,i think

8:29 rhickey: cemerick: that's just my preferences though, others love it

8:29 cemerick: rhickey: Perhaps I'm blind to it. Web development is absurdly and unnecessarily complicated all on its own, and rails seems to shield me somewhat.

8:29 rhickey: cemerick: until...

8:32 * cemerick waits for the punchline :-)

8:32 rhickey: cemerick: exactly

8:33 cemerick: heh

8:33 rhickey: that's how incidental complexity works

8:33 AWizzArd: cemerick: I find Compojure nice.

8:33 cemerick: well, it sounds like you're saying that rails doesn't properly abstract from the nuttiness of the web. Are there any solutions that do?

8:33 rhickey: ^^

8:35 rhickey: cemerick: probably not, but I'd rather have transparency and simplicity

8:35 cemerick: AWizzArd: as far as it goes, yes, it's OK. It needs time to cure though.

8:35 rhickey: rather than opacity and apparent simplicity

8:35 cemerick: I suppose GWT is pointing in that direction, but that has a boatload of its own problems.

8:35 Bjering: Ok, scrap the bank-system idea then, as it is clearly a case where data-integrity/performance tradeoff is an easy win for data-integrity and take something like an game-server instead. This also need to be able to survive a blackout, but at the same time if any time you fire a weapon is a database insert you wont get the responsiveness you need.

8:38 rhickey: cemerick: right, GWT is another example - is it really changing the power/complexity ratio? If more power comes with more (esp. implicit) complexity, you really aren't getting anywhere

8:40 Bjering: I guess what I want is a system where events both get saved forever to disk, and at the same time, following the same logic, affects the state "in RAM" following the same rules. Without me writing duplicated logic, and without the "in RAM" version reading from the DB all the time (for performance reasons).

8:40 rhickey: usually we can do 90% of the job with 10% of the complexity, but the other 90% of the complexity is sitting there in the langs/frameworks and we use it because it's there

8:41 cemerick: I wonder if anyone is willing to pay the price associated with a web framework that actually does change the power/complexity ratio. Seaside comes to mind, but that's hardly a common choice.

8:42 Bjering: you're wanting a terracotta cluster, or something similar

8:42 rhickey: cemerick: I think people don't normally consider incidental complexity, they are infatuated with apparent simplicity

8:43 cemerick: rhickey: right...and what I was saying is, perhaps that's the legitimately sane choice for web front ends -- which are ditched and replaced, wholesale, every 9 months on average (or whatever)

8:44 rhickey: cemerick: could be

8:44 but when they are not ditched, then what?

8:45 tomoj: do frameworks like sinatra and compojure not change the power/complexity ratio?

8:45 (compared to like django and rails)

8:45 cemerick: rhickey: till the soil, and see what comes up next, I suppose

8:46 chouser: I've been very pleased with the power/complexity ratio of ring, so far anyway.

8:46 Bjering: I have an arrow, hitting an ogre, the ogres state should change to "wounded" at the same time the arrows state should change to "stuck", this seems prefectly nice to do in the STM. Its also nice to do with database transactions. What if want both? The right answer is "no if you want both, you do it only in the DB and then re-read your data to the APP? :(

8:46 rhickey: cemerick: line with bad choices has been my experience, fewer things ditched than not, systems lasting well beyond when they ought to

8:46 live with

8:47 Bjering: it might be possible in the future to tie STM in with a transaction coordinator, but not yet

8:48 cemerick: Bjering: from what I understand, most MMORPGs run entirely in-memory, with only selected bits (inventory, XP, etc) being persisted to disk

8:49 _ato: I would consider GWT and Seaside to be two very good examples of opacity and apparant -- but not real -- simplicity. What happens with GWT when you reach the 10% that GWT can't do for you, or worse you encounter a bug? With something small and transparent like Sinatra/Compojure you can go read the code, tweak it etc. With GWT it's just overwhelmingly complex.

8:49 cemerick: Bjering: but what you're describing is exactly what terracotta and similar clustering frameworks aim for

8:50 Bjering: cemerick: Ok, this sounds cool, but when I hear Terracotta I feel like "whoaa" thats big and dangerous and an overkill for what I want, but perhaps it doesnt have to be?

8:51 cemerick: Bjering: no, it doesn't have to be, but if you're looking for that transparent (called "orthogonal" elsewhere?) solution, then that's where you have to go

8:52 People have built such things on top of other object systems (like CLOS), but stuff like that seems like a hairball to me.

8:52 Bjering: I havent been looking for anything transparent since I got burned by COBRA 15 years ago ;)

8:52 eh corba..

8:53 rhickey: chouser: I started this to give us a place to hang issues related to agent exceptions: https://www.assembla.com/wiki/show/clojure/Agent_exception_handlers

8:56 Bjering: I want persistence, and performance, at the same time. Persistence doesn't have to be immidiate, it can queue up, but in the end I need a guarantee any transactions are resolved the same as it was in RAM. All as "simple" as possible. Maybe this is impossible?

8:58 chouser: Bjering: if you don't care about immediate, you might look at doing your database writes in an agent

8:58 Bjering: if you send to an agent from inside a transaction, the send will be held back until the transaction commits

8:59 esj: Bjering: have you thought about mongodb, redis, scalaris and friends ?

8:59 Bjering: Chouser: Unless someone pulls the plug before it happens ;) but yeah for many apps that should be ok.

9:00 chouser: Bjering: right

9:01 AWizzArd: When I modify a ref inside a transaction then there is no need to call ensure on that ref, right?

9:01 chouser: AWizzArd: right

9:02 Bjering: esj, nope, I guess I get confused with the talk about scalability and distribution, those arent my problems. Performance and persistence are. I'll check them out now though. Thank you.

9:02 chouser: rhickey: can I add notes to that assembla page?

9:02 that is, may I?

9:02 rhickey: sure

9:03 * rhickey gets more tea

9:03 StartsWithK: hi, quick question about gen-class, what is a right way to declare ctor/method takes primitive type and array?

9:05 and why if :constructors is omitted will gen-class create constructors that match base class?

9:11 Bjering: chouser: I guess a condensed way to phrase it is that if I want to be sure that unless a state is recreateable from disc, I don't want anyone to see it. And that for now, I either have to solve this by reading all state from the DB after it has runs its transaction (as I am used to) or investigate 3rd party solutions (such as terracotta or the ones esj suggested) until the STM integration with a Transaction Coordination happens.

9:13 chouser: hm, yeah.

9:13 I wonder if you could do some kind of speculative blocking write within the transaction.

9:14 blocking so that the STM commit doesn't happen until the write is complete

9:14 speculative so that an STM retry even after the disk write could still be "re-done"

9:16 Bjering: If so I think that would solve it yes.

9:19 chouser: I guess I don't know how you'd finally "commit" that speculative write without still risking out-of-sync if something failed right after STM commit.

9:20 maybe at startup in such circumstances you could manually reveiw all writes that were neither committed nor rolled back and resolve them yourself. :-/

9:22 Bjering: Although I don't know how myself, I get the feeling its exaclty this kind of problem any DBMS has to solve to provide ACID. So there should be a well tested way.

9:23 chouser: rhickey: I like a queue. Our first-class asynch queue is an agent, so the handler is an agent and an action.

9:24 this nicely closes the door on fixing the error and all its incidental complexity

9:25 though it does leave the question of what is the meaning of the error-agent's state. hrmmm

9:25 AWizzArd: btw, while you are at agents: is there a way to make agents await (await-for) for the job which was sent off in the current thread?

9:25 Currently I need to serialize parallel requests on my webserver to an external program. I do so via an agent and forward it a promise which I am setting inside the agent fn

9:26 chouser: AWizzArd: what's wrong with await and await-for?

9:26 AWizzArd: This way I get for sure the value for the current thread.

9:27 chouser: await does not return a value

9:27 I mean, not the agents value

9:28 when I deref the agent again it may already contain the result of a different request

9:28 chouser: ah

9:28 AWizzArd: even if the await will await only the current threads send

9:28 So I pass in a promise, and instead of await I will just deref the promise.

9:29 chouser: not a bad solution

9:30 and more or less what 'await' is doing anyway. :-)

9:30 oh, I see -- await is good for multiple agents

9:31 AWizzArd: yes, my solution is usable

9:31 chouser: which doesn't fit with your feature request

9:31 AWizzArd: it's maybe not too important

9:31 a special case of serialization

9:32 chouser: there's an undocumented await1 that could potentially return the value of the agent at that moment rather than the agent itself

9:33 it could be implemented using a promise

9:34 (let [p (promise)] (send agent (partial deliver p)) @p)

9:36 heh. but don't actually do that.

9:38 rhickey: chouser: an agent isn't a full queue, it's a sink

9:38 cgrand: AWizzArd: or use java's futures with a single-thread pool

9:39 chouser: (let [p (promise)] (send a #(do (deliver p %) %)) @p)

9:39 rhickey: because you can't choose to pull, poll and/or block on it?

9:40 rhickey: chouser: right, it's not a conveyance. A queue might have multiple consumers, for instance

9:41 * rhickey watching painfully here as people try to define queues with agents and promises

9:41 rhickey: when you need a queue, use a queue

9:43 AWizzArd: I see.

9:43 rhickey: chouser: I know fixing adds complexity, but it's not incidental. Without it, you are just leaving many real scenarios unaddressed - like action where order is important. Many of the complexities revealed by 'fix' still exist - what about the rest of the queued actions? the future life of the agent?

9:45 Armstrong's thesis remains a good read on error handling: http://ftp.sunet.se/pub/lang/erlang/download/armstrong_thesis_2003.pdf

9:45 I just don't know that we could/should dictate the strategy as Erlang does

9:49 ambient: i'd be happy if somebody actually told me how things should be done

9:50 multiple ways of doing things, if there's really no difference between them, just makes things harder

9:52 the ideal, for me, would be having just one proper tool for the job, and not having to choose between the red and the blue hammers, when there are no practical differences

10:18 dmiller7: ,(namespace 'ab/cd/e)

10:18 clojurebot: "ab/cd"

10:19 dmiller7: http://clojure.org/reader says '/' can be used _once_ in the middle of a symbol to separate namespace from name

10:19 It is mute on multiple occurrences, but I always thought that would be an error.

10:19 Is this correct behavior?

10:20 chouser: I think the docs may be out of date on that.

10:20 (namespace 'http://foo.bar/qux/my-thing)

10:20 ,(namespace 'http://foo.bar/qux/my-thing)

10:20 clojurebot: "http://foo.bar/qux"

10:21 rhickey: chouser: thoughts on proposal at bottom of: https://www.assembla.com/wiki/show/clojure/Agent_exception_handlers ?

10:22 * chouser reads

10:27 chouser: I haven't yet experienced the need for industrial strength error handling, just that agents' current default of reporting nowhere and killing the agent is pretty much never what I want.

10:28 So I'm easy to please. Your proposal is entirely acceptible.

10:28 you don't like tying :on-error :continue to the existance of a handler?

10:29 rhickey: chouser: no, because the handler could be just about centralized reporting, but the from-agent exception ties into the call chain, so if you wanted to fail because a component you rely on has failed, you can

10:31 chouser: do you have something in mind for :die that's different than what agent-errors do now? For example, if you have 2 actions queued, A and B, even if A fails and queues an error, B will proceed.

10:31 rhickey: the default can be :continue if handler

10:31 chouser: what they do now is broken in the pending actions proceed

10:31 in that

10:32 chouser: ok

10:32 rhickey: as for un-die, dunno

10:33 chouser: if you could :on-error :pause, I wonder if you could get some error-fixing features without some of the complexity

10:34 hrm, maybe not. I guess you still have all the questions about what's paused. pending sends? pending watchers? etc.

10:34 rhickey: pause could be cool, but restart has it's own set of stuff - with what state, what about pending actions, is a restart an action (e.g. notifies watchers)

10:35 we could add later

10:35 chouser: yes

10:35 rhickey: this seems to be the simplest thing that doesn't box us in

10:35 I'm ok w/o synch fix

10:36 use a proper transactional queue if you never want to drop anything

10:37 chouser: with a static :on-error policy, we have a perfect place to plug in broader changes if needed.

10:37 later

10:37 rhickey: yeah

10:37 just a question about the meaning of :on-error with no handler

10:38 chouser: I mean, handler may currently fire after pending sends are cleared, but if :pause or something else were added it could change even that, having the handler fire earlier or whatever makes sense.

10:38 I wonder how often people use clear-agent-errors except manually at the repl

10:39 rhickey: yes, the big toggle is on handler does policy or agent does

10:40 chouser: yeah, clear-agent-errors is difficult for program policy

10:40 chouser: if it's not used much, maybe :die and stay dead is default?

10:41 rhickey: :on-error could be ignored if no handler - thus same as before semantics

10:41 chouser: keep the broken queued actions proceed?

10:42 or maybe replace the error seq with a single error and all pending actions, pending sends, watchers, etc. are dropped.

10:42 rhickey: chouser: that's trickier, I'd like to fix it, but fix requires that clear-agent-errors restarts queuing, else clear and pending actions wouldn't happen

10:44 chouser: I didn't realize until yesterday that pending actions proceed after error, and so I hadn't understood how errors could ever have more than one exception

10:44 rhickey: It tends to happen that all actions sent before the first fails fail themselves, often due to some bogosity in the agent state, and you end up with a bunch of the same failures. simply clearing errors without being able to fix state won't help, so maybe throw away pending actions is best

10:45 i.e. if we are keeping clear-agent-errors the same

10:45 chouser: ok. and this would be part of the :die policy that could be toggled to some new feature later

10:46 rhickey: I saw this as separate from the die policy, as clear-agent-errors leavesa viable agent

10:46 chouser: ah.

10:47 rhickey: without a handler, you are saying, I'll deal with this manually, with a handler, automatically, and thus policy-driven

10:48 then we can eventually deprecate clear-agent-errors since we haven't tied it into the new stuff

10:49 chouser: so :die means forever dead?

10:50 and no handler would mean something else -- hold the error, drop pendings, wait for clear.

10:58 rhickey: I think :or-error :continue or :propagate (or something)

10:59 the latter will rethrow the error to future sends, and leave the pending actions in place, the agent suspended

11:00 then 2 functions - (clear-pending-actions agt) , and (restart a new-state)

11:00 so, no permanent death

11:01 only ever one error on agent, we can get rid of the error list and clear errors at some point

11:01 you can restart with the pending actions or with (by clearing them first)

11:01 without

11:02 :continue or :pause, :pause seems too weak for this state (throwing until restart)

11:03 :continue or :fail ?

11:03 a failing agent will throw until restarted

11:04 gotta run for now, bbl

11:21 AWizzArd: ,(doc await-for)

11:21 clojurebot: "([timeout-ms & agents]); Blocks the current thread until all actions dispatched thus far (from this thread or agent) to the agents have occurred, or the timeout (in milliseconds) has elapsed. Returns nil if returning due to timeout, non-nil otherwise."

11:22 AWizzArd: On my system await-for returns false when timed out.

11:23 stuartsierra: First wave of survey results: http://groups.google.com/group/clojure/msg/df61abf2aca68985

11:25 the-kenny: I think some informations about Chunked Sequences should be provided ;)

11:25 chouser: heh

11:25 part of what needs to be documented for 1.1 :-/

11:26 stuartsierra: Sequences are a great abstraction; maybe we need ways to specify different kinds of sequences for different situations.

11:27 E.g., chunked/unchunked, caching/non, lazy/non, ...

11:29 Right now, the sequence interface is tied to a single implementation - chunked lazy sequences with caching.

11:30 pao: sorry for the dump question

11:30 how do I build a lazy seq starting from 1 to "infinity"?

11:30 stuartsierra: pao: (iterate 1 inc)

11:30 pao: stuartsierra: thanks

11:31 stuartsierra: pao: you're welcome

11:32 chouser: wow, I was off by more than 50%. We've got many more 1.0 users than I thought.

11:33 stuartsierra: Lots of people like downloading binaries.

11:33 Clojure's about the only Java software I regularly compile myself.

11:33 the-kenny: I think there should be a build-bot, as the github-checkouts tending to be very stable

11:34 stuartsierra: Yes, same for me.

11:34 I have a small script for pull, update, clean and build for clojure and contrib

11:35 stuartsierra: the-kenny: that's basically what Hudson does

11:35 the-kenny: hm.. never heard of it

11:36 stuartsierra: http://build.clojure.org/

11:37 You can always download the latest stable jar from http://build.clojure.org/job/clojure/lastStableBuild/artifact/clojure.jar

12:05 bgs100: Hi. How could you convert a list/vector of characters to a string? (Already tried str)

12:05 hiredman: apply str

12:06 bgs100: hiredman, Thanks

12:16 churib: hm, in my irc-client ctrl-k doesnt seem to kill the line, it kicks people from the channel

12:22 chouser: rhickey: wrote up my understanding of your latest suggestions as Proposal B on the assembla page

13:03 danlarkin: mccraig mccraig of the clan mccraig?

13:12 drewr: danlarkin: +1

13:30 KirinDave2: Is there a more formal way to do this (or am I doing something terrible that makes babies wail?)

13:30 https://gist.github.com/4c8d5e355d69cd140811

13:32 chouser: taking keywords args like that is not uncommon

13:33 j0ni: win 1

13:33 the-kenny: KirinDave2: There is a special defn for functions with keyword argument in contrib

13:33 (contrib.core or so)

13:34 chouser: you can also use destructuring to declare in one place what keyword arks you're expecting.

13:34 the-kenny: ,(doc defnk)

13:34 clojurebot: "clojure.contrib.def/defnk;[[fn-name & fn-tail]]; Define a function accepting keyword arguments. Symbols up to the first keyword in the parameter list are taken as positional arguments. Then an alternating sequence of keywords and defaults values is expected. The values of the keyword arguments are available in the function body by virtue of the symbol corresponding to the keyword (cf. :keys destructuring). defnk accepts

13:34 KirinDave2: I should use that.

13:34 Would be way better.

13:34 I am surprised defn doesn't integrate that functionality by default.

13:35 chouser: KirinDave2: I might also recommend that you separate the creation of the object from modifying global state

13:35 the-kenny: KirinDave2: It's integrated in Common Lisp ;)

13:36 chouser: it has performance implications that keep it out of defn, I think.

13:36 KirinDave2: the-kenny: AndPLT Scheme

13:37 chouser: I have separate functions for that as well, this is the state push. The :name is just a convenience.

13:37 replaca_: Rich wants function invocation to be as fast as raw JVM function calls can be. Keyword parsing would undermine this

13:38 KirinDave2: replaca_: I don't think that's a valid reason to dismiss the functionality being integrated.

13:38 the-kenny: replaca_: I like the way it's now. Just use a seperate macro for functions with keyword-arguments :)

13:38 KirinDave2: replaca_: defn could make the decision if there are no keywords specified to use a faster piece of generated code.

13:39 That's one of the many reasons why I love macros, they can have conditionals for optimizations.

13:39 chouser: I believe there was a proposal on the list for this

13:39 KirinDave2: Btw can you tell how heavily tasked I am at my job right now? :D

13:40 No managers, just a computer installing software (AGAIN), and clojure writing a foosball scoring app.

13:40 Yes, I work hard.

13:40 chouser: Have there been proposals for macro-by-example systems as well?

13:41 chouser: The more I read into it the more it looks like clojure could allow for this along with automatic capture protection.

13:41 chouser: I don't think anyone's made a deep proposal for macro-by-example.

13:42 KirinDave2: Doing an MBE without automatic capture protection is not terribly difficult.

13:42 chouser: I assume the biggest obstacle there is (perceived or real) lack of need.

13:42 KirinDave2: What's difficult is the protection.

13:42 chouser: I dunno. Once you get used to MBE it's WAY clearer and faster for 90% of all macros.

13:42 chouser: clojure macros are already hygenic

13:42 KirinDave2: chouser: Uh, so symbol# was abolished?

13:42 drewr: is there any limitation on using exceptions in fns called from proxy methods?

13:43 KirinDave2: chouser: If you have to decide which variables to gensym, it's not really hygienic.

13:44 chouser: KirinDave2: no, but if you forget in a context where you need a gensym, the compiler won't let you use your macro.

13:45 KirinDave2: Well anyways, I'm hoping that the new defproto stuff will make this very noun-y code easier.

13:51 hiredman: KirinDave2: why not just use map destructuring directly?

13:51 ,((fn [{:keys [a]}] a) {:a 1})

13:51 clojurebot: 1

13:51 hiredman: no need for defnk

13:53 KirinDave2: hiredman: Now you're passing a map in though

13:53 hiredman: sure

13:53 why not?

13:53 KirinDave2: hiredman: That's why.

13:54 Because unless that's done implicitly that's a tedious convetion for the caller which is seldom consistent.

13:54 hiredman: Calls in clojure pass maps when they mean to pass maps, not as a convention for keyword args.

13:54 hiredman: Further there are already examples of keyword args and they are not maps.

13:54 hiredman: KirinDave2: those examples are dumb

13:55 KirinDave2: the difference between what you want, and what is by default available in every binding form is a single set of curly braces

13:56 KirinDave2: hiredman: Yes.

13:56 hiredman: so just use the curly braces

13:56 KirinDave2: No.

13:56 It's ugly. Sorry.

13:56 Small differences count here.

13:57 hiredman: how is it ugly?

13:57 KirinDave2: Worse than ugly, it's inconsistent. That's not an acceptable tradeoff.

13:57 hiredman: how is inconsistent?

13:57 keyword args are a map

13:57 KirinDave2: Some keyword args are as maps, some keyword args are inline.

13:57 Keyword args get represented to the callee as a map

13:57 but standard destructuring syntax (i.e., :as …) is not represented as a map to the callee.

13:58 err, the callerr

13:58 hiredman: KirinDave2: it is a linear collection of things

13:58 [[a b]] vs {:keys [a b]}

13:58 er

13:58 [[a b]] vs [{:keys [a b]}]

13:59 KirinDave2: hiredman: Do you get that I don't agree with you at all yet, or shall we continue?

13:59 hiredman: I get that you are stuck in the mud

13:59 KirinDave2: hiredman: I do appreciate help, but I find that decision unacceptable. Especially when the much more consistent defnk is already written and available.

13:59 hiredman: but I am just so tired of defnk and apply hash-map

14:00 KirinDave2: So maybe it would make sense to provide something like & for this kind of mapping?

14:00 hiredman: no

14:01 KirinDave2: [% :a 1 :b 2]

14:01 hiredman: map destructuring is fine as is

14:01 defnk actually generates a map at runtime from keyword args

14:01 KirinDave2: Does it support defaults?

14:02 hiredman: ~destructuring

14:02 clojurebot: destructuring is http://clojure.org/special_forms#let

14:02 hiredman: yes

14:02 KirinDave2: Okay. Well I'm going to use denfk though. In fact, I just did.

14:03 chouser: reference type factory methods also use apply hash-map to generate a map at runtime from keyword args

14:03 agent, ref, atom, etc.

14:04 hiredman: :(

14:05 I am well aware of the prevelance of apply hash-map

14:05 chouser: I guess I don't see the problem

14:05 doing work in an API to make life easier of the API-user seems right to me

14:06 hiredman: chouser: which map destrucuring does

14:06 chouser: yes, but requiring users of my fn to insert extra {} does not

14:06 hiredman: why?

14:07 clojure has literal maps, they are not some add on

14:07 KirinDave2: Well, the major weakness of lisp syntax (and smalltalk caller syntax, incidentally) is that it requires prediction. Increasing the depth of that prediction is not a good idea.

14:07 chouser: when used in a fn call where they aren't required, the extra {} is just clutter

14:08 KirinDave2: At least with paredit mode it's easy when you get the prediction wrong.

14:08 hiredman: chouser: you don't need them in every fn call, just the fns that expect a map

14:08 KirinDave2: But adding extra glyphs just to make the author's life slightly easier.

14:08 hiredman: Hence inconsistency, again.

14:08 hiredman: how is that inconsistent?

14:08 a map is a value like 1 or 2, or a list

14:09 KirinDave2: Because you're not passing a map. the function doesn't require a map

14:09 You're using a map as a calling convention.

14:09 You're asking the caller to think about your impl details.

14:09 hiredman: the function does require map

14:09 if the function did not require a map, then why are you generating one?

14:10 chouser: why would I want to write (ref v {:meta m}) when I could write (ref v :meta m) ?

14:10 hiredman: chouser: why write (ref v :meta m) when you can write (ref v {:meta m})?

14:12 chouser: because in that case the {} is unnecessary clutter

14:13 to be more purely what 'ref' itself care about there would be no keyword args at all, and I'd have to write (ref v nil nil nil m nil) or something.

14:13 hiredman: ref treats those params as a map, and generates a map internally

14:14 so a {} is exactly what it is

14:14 chouser: and then destructures the map to get at the specific values for :meta and :validator

14:14 what ref really wants is meta and validator args

14:14 not a mpa

14:14 map

14:15 hiredman: I'm late for work

14:15 slyrus_: has anyone tried getting swank-clojure to work with the "new" branch?

14:16 chouser: hiredman: ok, ttyl. :-)

14:16 the-kenny: slyrus_: It's working here.

14:17 slyrus_: the-kenny: hmm... wonder what I'm doing wrong. master HEAD works fine, but I get java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V (pprint.clj:1) with new

14:17 the-kenny: slyrus_: You have to recompile contrib, clojure and maybe swank-clojure itself.

14:17 (a complete rebuild, with ant clean)

14:18 slyrus_: oh, forgot about contrib. thanks the-kenny.

14:18 the-kenny: You're welcome

14:18 clojurebot: restfn

14:18 clojurebot: I don't understand.

14:18 the-kenny: clojurebot: RestFn

14:18 clojurebot: Excuse me?

14:18 the-kenny: hm ok

14:20 slyrus_: the-kenny: that works. thanks again!

14:21 it would be nice if "new" bumped the version number or name such that both master and new didn't say: "Clojure 1.1.0-alpha-SNAPSHOT"

14:22 chouser: heh. that's a good point. There was much wrangling over just getting what we've got.

14:23 I guess it was assumed that alpha-SNAPSHOT was sufficient to communicate the broad category of unreleased versions people might be using.

14:23 * slyrus_ is blissfully ignorant of such wrangling and therefore has no problem griping about the status quo :)

14:23 technomancy: considering new is not going to make it into 1.1.0, it could be considered misleading

14:24 slyrus_: and the name "new" itself is rather suspect, IYAM. something that describes the functionality (protocols, perhaps?) rather than the age of the branch would seem appropriate

14:24 dysinger: slyrus_: also we could have "new" in the maven repo if it didn't have the same version.

14:24 slyrus_: but, hey, who am I to complain? :)

14:25 dysinger: technomancy: I think the point is "not the same version & qualifier as master"

14:25 * slyrus_ is blissfully ignorant of maven repos and wants to stay that way

14:25 slyrus_: i'm sensing a common theme here...

14:26 chouser: "new" *does* describe the feature, it's just the feature go renamed from 'new' to 'reify'

14:26 it's not "new" as in less old, it's "new" as in (new Foo) was getting updated features.

14:27 slyrus_: chouser: ah! I see... never mind then :)

14:27 chouser: heh

14:27 slyrus_: let's hope the inverse of reify isn't named old

14:28 alinp: hi guys

14:28 is there a way to use time for a map ?

14:28 e.g. (time (map fib (list 38 39)))

14:28 which is not working accordingly

14:28 the-kenny: alinp: doall

14:29 alinp: (time (doall (map .... ?

14:29 the-kenny: Yes

14:29 alinp: cool, thanks

14:29 the-kenny: (time (doall (map inc (list 38 39))))

14:29 ,(time (doall (map inc (list 38 39))))

14:29 clojurebot: (39 40)

14:29 "Elapsed time: 0.172 msecs"

14:29 alinp: yeah, that's right

14:29 the-kenny: hm... bad example ;)

14:32 alinp: ah, map is returning a lazy seq

14:32 that's why time is irelevant when used with a lazy seq

14:32 and that's why doall is needed ;)

14:33 chouser: Clojure 1.1.0-new-alpha-SNAPSHOT

14:33 user=>

14:33 the-kenny: alinp: Exactly

14:35 technomancy: chouser: nice; thanks.

14:35 dysinger: Inice

14:35 * dysinger hooks up in the maven repo

14:35 chouser: well, I can't check that in

14:35 without approval

14:36 * dysinger hears some thunder in the distance

14:36 lisppaste8: Chouser pasted "tweaking clojure version reporting" at http://paste.lisp.org/display/91109

14:37 chouser: but it makes sense to me for public branches to contain tweaks like that.

14:37 dysinger: agree

14:37 chouser: When doing a major merge from, say, 'new' to 'master', we just have to remember to correct the version number.

14:37 alinp: The thing is that I knew a while a go that doall is needed

14:37 but ... I forgot exactly why

14:37 and I used it like this: (doall (time (map .... :)

14:37 obviously is not right

14:37 dysinger: we can the build them on the CI server and have them accessable to lein, mvn & ivy

14:37 s/the/then

14:38 chouser: maybe it would make more sense to replace the word "alpha" with the branch name

14:38 dysinger: skeptomai ! {hello}

14:39 chouser: 1.1.0-master-SNAPSHOT, 1.1.0-new-SNAPSHOT, etc.

14:39 dysinger: chouser: agree

14:39 skeptomai: dysinger: how are things?

14:39 chouser: assuming we don't do non-SNAPSHOT pre-releases

14:40 dysinger: skeptomai: great - see otp news today re: github :)

14:40 ?

14:40 skeptomai: already forked & built. putting my crypto changes in now :)

14:40 it's a happy day

14:41 dysinger: skeptomai: there's already 11 forks and 170 watchers in a couple hours

14:41 skeptomai: clearly much of the community has been waiting for this

14:42 dysinger: yes

14:42 skeptomai: I'm still puttering about with the otp_build script and understanding how it's supposed to work though

14:49 cemerick: well, it's (mostly) settled, I'm getting dragged into maven. Joining the dark side, as it were.

14:49 chouser: via lein?

14:50 cemerick: no, totally divorced from that

14:51 I had cooked up my own little dependency mgmt system based on git submodules...which is *way* nicer than ivy or maven for smaller stuff, but it's now creaking under the weight of our aggregate codebases.

14:51 alexyk: how do you take a length of a list or a vector?

14:51 chouser: alexyk: count

14:51 cemerick: ,(count [1 2 3])

14:51 clojurebot: 3

14:52 chouser: alexyk: use 'counted?' to see if its fast or slow for a certain object.

14:52 ,(counted? [1 2 3])

14:52 clojurebot: true

14:52 alexyk: is it the same for a seq?

14:52 chouser: ,(counted? (map inc [1 2 3]))

14:52 clojurebot: false

14:52 chouser: ,(count (map inc [1 2 3]))

14:52 clojurebot: 3

14:52 chouser: alexyk: yes, 'count' works on seqs

14:52 but it's linear time

14:53 constant time on lists and vectors (where counted? is true)

14:53 alexyk: how can I measure the time someting takes, e.g. the count on a long seq?

14:53 cemerick: due respect to technomancy, I can't bring myself to jump on lein yet. By the time we're transitioned to maven, lein will be matured (for a clojure project).

14:53 chouser: ,(time (count (map inc [1 2 3])))

14:53 clojurebot: 3

14:53 "Elapsed time: 0.164 msecs"

14:54 alexyk: nice

14:54 technomancy: cemerick: of course; it's only been announced for a week. caution is prudent.

14:54 cemerick: technomancy: I'm rootin' for you, though :-D

14:55 danlarkin: we're trying!

14:55 cemerick: A friend of mine is using lein for a side project of his, so I can draw karma from there.

14:55 chouser: I'll have to try out lein and clojars for clojure-jna or something.

14:56 cemerick: what do people here use for internal maven repos, anyway?

14:57 technomancy: cemerick: you can just drop ~/.m2/repository behind a static web server, but hudson is pretty easy to set up too, and you get CI as a bonus.

14:58 rhickey: chouser: your subset example shows a problem - now the validity of clear-pendind-actions and restart call into question their validity in a handler

14:58 cemerick: technomancy: hrm. If it's so easy, when what's with all the commercial options?

14:58 chouser: rhickey: I thought they might. :-)

14:58 * cemerick loves the opportunity to ask noob, off topic questions

14:59 rhickey: I don't see the equivalence you are making

14:59 :continue doesn't clear actions

14:59 technomancy: cemerick: auto proxying-and-caching jars from central is nice, I guess. I don't really know beyond that.

14:59 alexyk: everybody in JVM world cooks up their own build systems. Which is the one preferred in clojure these days?

15:00 cemerick: hrm, if that's all it is....

15:00 rhickey: and restart must kick the queue off again, tricky while in action

15:00 chouser: oh, yes, I seem to have confused myself.

15:00 alexyk: btw, for maven, it would be nice to have full pom.xml files in clojure and clojure-contrib

15:01 rhickey: so maybe (restart a new-state :clear-pending-actions true/false), only allowed on failed agent, and an agent failing is not yet failed

15:01 chouser: the actions pending sends are thrown away on error immediately. clear-pending-actions is about actions queued from elsewhere.

15:02 rhickey: actions are about the agents queue

15:02 maybe just clear-actions

15:02 chouser: right, I tripped up, thinking clear-pending-actions was about the held sends

15:03 rhickey: (restart a new-state :clear-actions true/false)

15:03 default :clear-actions false

15:03 chouser: I like that.

15:03 rhickey: but the important job of restart, reprimingthe queue, can't happen in an action

15:03 so calling restart in handler a no no

15:04 chouser: I don't see why yet.

15:05 rhickey: that pop/CAS stuff is very tricky

15:05 chouser: maybe it'll be clear when I go to implement. :-)

15:06 rhickey: it ensures that only a returning action or a new dispatch to an idle agent will place a single action into thread pool, and that the agent never stalls

15:06 also ensuring the one-thing-at-a-time rule

15:07 technomancy: alexyk: I recommend http://github.com/technomancy/leiningen, but I'm admittedly biased

15:07 rhickey: so you are in the middle of handling an error, haven't even set the error state up, and restart is called - what is it going to do?

15:08 vs you have a failed agent not in an action, with a stalled queue - what is retart going to do?

15:08 the latter case is the one we need, the former somewhat pathological - not yet failed or stopped

15:09 chouser: ok, I see. Being in a state of :fail but not yet done with handler is broken

15:09 rhickey: yeah, and restart needs to spin the queue up again

15:10 which will be tricky enough

15:10 chouser: so agent goes to :fail atomically after handler is done

15:10 rhickey: i.e. its interaction with dispatch

15:10 chouser: right

15:10 chouser: until then, send is ok but restart is an error

15:10 rhickey: right

15:12 chouser: after agent is :fail, send is error but restart ok.

15:12 restart goes atomically back again.

15:12 rhickey: I'm wondering if we should throw on deref of failed or not

15:12 right

15:13 chouser: ok, I put that in because of current behavior, but didn't consider alternatives

15:17 rhickey: so, just a single restart function, always taking a state and optionally a clear-actions flag?

15:17 restart never notifies watchers

15:18 restart state could fail validation, immediate exception, stays failed for original reason

15:18 chouser: ok

15:18 want a keyword arg on restart, or just true/false?

15:19 rhickey: keyword

15:20 putting it in restart saves us from having to define when clearing is ok

15:21 chouser: yes, and it's pointless to clear unless you intend to restart

15:21 rhickey: right, we don't want a separate clearing concept

15:22 chouser: no backward compatibility for clear-agent-errors or agent-errors? We could try to deprecate but leave a "similar" behavior for now.

15:23 rhickey: the latter

15:23 chouser: clear-agent-errors is a bit like (restart @a :clear-actions true)

15:23 rhickey: there will never be more than one error, but we can wrap in list

15:24 chouser: I mean (restart @a :clear-actions false)

15:24 rhickey: chouser: since the actions went through before, it's like (restart a @a)

15:24 chouser: right

15:24 rhickey: whic is how it should be defined now

15:24 chouser: ok

15:24 rhickey: and deprecated

15:25 chouser: new agent-error to retreive the single exception?

15:26 alexyk: how do you use reduce to count the size of a collection, i.e. to implement count? just for learning

15:27 chouser: ,(reduce (fn [count _] (inc count)) 0 '[a b c d e])

15:27 clojurebot: 5

15:28 alexyk: ah... I've tried: (reduce #(inc %1) 0 [1 2 3]) ; failed -- why?

15:28 chouser: #() looks at the highest-numbered % to see how many args it should expect

15:28 in your case, 1. But reduce calls with two args.

15:28 alexyk: chouser: so I'd have to uselessly employ %2

15:29 chouser: yes

15:29 alexyk: how?

15:29 chouser: don't

15:29 :-)

15:29 alexyk: i.e. what's a null way to use it? just for fun

15:29 chouser: (fn [count _] ...) is clear -- I'm taking a second arg and ignoring it (the idiomatic meaning of _ in clojure)

15:29 ,(reduce #(do %2 (inc %)) 0 '[a b c d e])

15:29 clojurebot: 5

15:30 chouser: ^^^ less clear

15:30 alexyk: hmm, %2 ... % -- so % always means %1?

15:30 chouser: yes

15:31 timothypratley: how do I git the 'new' branch to test a patch against it? the 'new' branch doesn't appear when a do a normal git clone...

15:31 alexyk: and do returns the last value, so %2 is evaluated and discarded?

15:31 chouser: alexyk: yes

15:31 alexyk: timothypratley: git checkout -b new origin/new, or something like that

15:31 timothypratley: thanks!

15:39 rhickey: chouser: yes, agent-error

15:40 alexyk: if I have a prog.clj file, do I need to compile it to run?

15:40 or just unleash clojure on it?

15:40 chouser: rhickey: I'm updating assembla now

15:41 rhickey: chouser: thanks

15:43 hiredman: if I have two vars that == says are not the same, why would alter-meta! on one effect the metadata on the other?

15:43 rhickey: hiredman: ==?

15:44 did you mean = ?

15:44 hiredman: should I be using =?

15:44 rhickey: almost always

15:44 hiredman: oh right

15:45 I want identical

15:45 I want identical?

15:45 rhickey: = for reference type is identical, use =

15:45 hiredman: ok

15:45 rhickey: == is for numbers only

15:45 hiredman: and it, of course, returns true, which explains the problem

15:46 thanks

15:46 rhickey: np

15:56 qed: alexyk: You could C-c C-k it if you have a slime repl open in emacs, otherwise yes, you need to compile it

15:57 the-kenny: C-c C-l is possible to (slime-compile-file or something is mapped to this)

15:57 Ew I mean slime-load-file

15:59 alexyk: thx!

15:59 qed: yeah or that

15:59 or C-c at the end paren of a line to load aprts of it into slime

15:59 C-c C-c

16:00 I wish there was some way for me to hit a hotkey at the end of a function im writing in a SLIME repl that would paste it into a currently open corresponding buffer

16:00 the-kenny: do you know if that's possible?

16:00 the-kenny: I'm sure it's possible.

16:00 qed: sometimes i test something and then i have to re-write it quick or copy/paste it, it would be nice to just pop it over from slime

16:01 the-kenny: Should be a few lines in elisp...

16:01 Just press C-M-b, M-x mark-sexq, M-w, C-c o, C-y :D

16:01 You could record a macro for that

16:01 qed: haha, too much work!

16:02 the-kenny: Then just create a macro :)

16:02 qed: sure, i think that's what ill do

16:02 how do you record a macro?

16:02 the-kenny: Ew.. I don't know

16:02 qed: ill figure it out

16:02 thanks though

16:02 the-kenny: No problem

16:05 I think it's fairly easy to write a "real" function for that. Just write out these shortcuts

16:05 (There's also M-x copy-to-buffer, maybe that's helpful)

16:07 qed: yeah thats better

16:07 that way ill just copy to whatever .clj is open

16:16 zaphar_ps: wget doesn't like clojure.org

16:17 it keeps asking for index.html which gets it a wikispaces page instead :-(

16:17 back to the drawing board

16:28 KirinDave1: Is there an elegant way to insert something into a vector at index n, displacing the other elements?

16:28 Or is that a for loop?

16:28 hiredman: assoc

16:28 ,(assoc [1 2 3] 0 4)

16:28 clojurebot: [4 2 3]

16:28 chouser: vectors are no good at shifting around their elements

16:29 KirinDave1: Is there a way todo that for lists?

16:29 hiredman: oh

16:29 display

16:29 chouser: into and subvec is about as good as it gets for now

16:29 KirinDave1: Okay, so it's a for loop. :)

16:29 That's fine, just wanted to make sure I wasn't missing anything.

16:29 hiredman: :|

16:30 chouser: you're missing finger trees is what you're missing

16:30 hiredman: it's definite possible to do it as a lazy-seq

16:30 KirinDave1: chouser: Pardon?

16:31 rhickey: KirinDave1: you really want a data structure oriented towards insertion, and none of the Clojure data structures are like that. There is a finger tree in the works that will have fast insertion. operations that would have linear time are usually not included (there are some exceptions)

16:31 KirinDave1: What I want is given (let [ladder '(:a :c :d)] (displace ladder :c :b)) => (:a :b :c :d)

16:32 chouser: ,(let [v '[a b c d e]] (-> (subvec v 0 2) (conj 'X) (into (subvec v 2))))

16:32 clojurebot: [a b X c d e]

16:32 hiredman: chouser: if he is fine with a seq or list instead of a vector, it is doable as a seq

16:32 KirinDave1: rhickey: It's fine if I just do it as a list in this place, the size of this structure is limited to 10.

16:34 technomancy: foosball doesn't scale

16:34 chouser: hehe

16:35 KirinDave1: technomancy: It's the "ladder"

16:35 Which is the top 10 teams.

16:35 Not by absolute wins, but by wins recently.

16:35 chouser: rhickey: assembla updated. still some questions about handler args and what to do if a handler throws

16:35 hiredman: it's a ring buffer

16:36 KirinDave1: hiredman: Is it?

16:36 hiredman: well, not really

16:36 KirinDave1: Actually this foosball project has been surprisingly good as way to get familair wih clojure. And I'm really excited to get to the compojure part of it.

16:36 hiredman: hmm

16:38 arohner: is there a way to refer to the "default" (.assoc) method for a deftype that implements IPersistentMap?

16:39 I'd like to write my own validator for a deftype. I was thinking that I could do something like (.assoc (my-validator ...) (default-assoc-method))

16:39 hiredman: arohner: I think the idea is you don't hang methods on deftype

16:40 chouser: I think that default method is generated only if you don't provide your own implementation.

16:40 hiredman: but assoc would be a operation in the protocol Associative

16:41 arohner: hiredman: is there a protocol Associative yet?

16:41 hiredman: arohner: ask chouser

16:41 chouser: no, clojure lang interfaces don't have protocols yet, afaik

16:44 rhickey: chouser: reading

16:45 ordnungswidrig: re

16:53 rhickey: chouser: I've updated, with answers to al q's, but am still unsure about :on-error default when handler provided

16:53 qed: rhickey, you wont sue me for buying getclojure.org/com will you?

16:54 drewr: qed: that entirely depends on what you do with it

16:54 rhickey: qed: dunno - what are you going to do with them

16:55 qed: haha, it's just going to be a clojure learning site, beginner/intermediate/advanced tutorials and examples, and then links to off-site reference material

16:57 for free of course...

16:57 are you consulting a lawyer?

16:58 hiredman: crack team of legal beagles

16:58 danlarkin: Bob Loblaw

16:58 djork: getclojure.com -- where you can buy a clojure + contrib jarfile with enterprise license for the low price of $4999

16:58 hah

16:58 Bob Loblaw Lobs Law Bomb

16:59 also http://thebobloblawlawblog.blogspot.com/ (not really related)

16:59 ok that's enough of my rambling

17:02 chouser: rhickey: :continue is a poor default when there's no handler. I suspect :fail is going to be relatively uncommon when there *is* a handler.

17:03 maybe if we list the handler first document it carefully, changing the default won't feel like bad magic?

17:03 rhickey: chouser: right, that's why I initially advocated the 'magic'

17:03 KirinDave1: blugh thats not pretty. :\

17:04 https://gist.github.com/c1345f116c96f19564c4

17:04 chouser: or could default to :continue with a default handler as well.

17:04 that ... prints the exception to *err* or something.

17:05 KirinDave1: I guess I could move that calc out ofthe let and maybe abstract an index function.

17:05 rhickey: chouser: or just a user-supplied default handler

17:05 chouser: KirinDave1: there's an indexed function in contrib seq-utils

17:05 KirinDave1: chouser: I suppose it's not ugly given that I wrote the whole thing without that. :D

17:05 chouser: KirinDave1: but you might try avoiding indexes altogether. insert using mapcat or something.

17:06 rhickey: chouser: I'm not sure I consider it magic to say - if there's a handler it won't fail (by default) and if no handler it will, unless you explicitly say otherwise

17:07 less about the default value of a flag than what it means to have a handler

17:07 chouser: yeah, with careful docs may not be bad. Feels worse if there are other policies later.

17:09 well, this should be plenty to start coding. not sure when that will happen :-/

17:09 rhickey: well, the fact of it is there is no universally good default

17:10 chouser: do you still want to shoot for 1.1., or should we just approved backlog it?

17:10 no code made it in already did it?

17:10 chouser: right, no code. just an aborted patch

17:11 rhickey: sounds like post 1.1

17:11 chouser: I would hate to hold up 1.1 -- this is the last patch. otherwise just docs, right?

17:11 rhickey: there's still: https://www.assembla.com/spaces/clojure/tickets/210

17:12 patch fails tests

17:13 timothypratley1: Hi rich

17:13 I've found the reason for that!

17:13 rhickey: since there is so much new-ness in this agent thing I think definitely post 1.1

17:13 chouser: ok, fine with me

17:13 michaeljaaka: , (letfn (me [mm e] e) 12 )

17:13 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

17:13 michaeljaaka: what is wrong with that?

17:13 chouser: michaeljaaka: still need []

17:13 rhickey: timothypratley1: and?

17:13 chouser: ,(letfn [(me [mm e] e)] 12)

17:13 clojurebot: 12

17:14 michaeljaaka: ok

17:14 timothypratley1: the problem with #210 is more deletion is required :) For some reason there are some other shadowed methods

17:14 which work fine on my setup

17:14 but I can see if they get called (and they are on your report)

17:14 would fail

17:14 Its a trivial fix

17:14 michaeljaaka: chouser: the doc doesn't say that

17:14 timothypratley1: but I'm struggling with making the git patch atm

17:14 sorry taking so long

17:14 rhickey: timothypratley1: np

17:15 chouser: michaeljaaka: "Takes a vector of function specs"

17:15 michaeljaaka: chouser: ok :)

17:25 mccraig: danlarkin: aye, tis me

17:26 timothypratley1: rhickey: patch is up http://www.assembla.com/spaces/clojure/documents/bHx3hk2Her3QkseJe5aVNr/download?filename=ssb2.diff for #210 just FYI :)

17:46 qed: is there a partition-with floating around?

17:46 i seem to remember one existing in a contrib pkg

17:47 danlarkin: probably in seq-utils

18:10 rhickey: https://www.assembla.com/spaces/clojure/tickets?milestone_id=93750&tickets_report_id=5

18:12 chouser: so ... what now?

18:12 oh, I remember. ...dinner.

18:13 timothypratley1: cool! :)

18:13 nathanmarz: is there any sort of object I can use in clojure that can be destructured as either a seq or a map?

18:13 rhickey: timothypratley1: thanks for the patch

18:14 timothypratley1: np :)

18:17 Knekk: how do I cast a float to an int again?

18:18 timothypratley1: ,(doc int)

18:18 clojurebot: "([x]); Coerce to int"

18:18 timothypratley1: ,(doc cast)

18:18 clojurebot: "([c x]); Throws a ClassCastException if x is not a c, else returns x."

18:18 Knekk: thanks

18:21 nathanmarz: tried using LinkedHashMap, but it doesn't respond to "nth"

18:23 rhickey: nathanmarz: LinkedHashMap doesn't implement RandomAccess

18:24 nathanmarz: i see

18:24 rhickey: nathanmarz: nth doesn't make sense for non-sequential things, and isn't fast for non-indexed things

18:25 nathanmarz: yea, that's ok for my use case, just want the convenience of it

18:25 rhickey: you can always seq it first

18:26 nathanmarz: but then it wouldn't be able to be destructured as a map?

18:27 rhickey: , (nth (seq (java.util.LinkedHashMap. {:a 1 :b 2 :c 3})) 1)

18:27 clojurebot: #<Entry :b=2>

18:28 rhickey: ,(let [[a b] (nth (seq (java.util.LinkedHashMap. {:a 1 :b 2 :c 3})) 1)] [b a])

18:28 clojurebot: [2 :b]

18:28 rhickey: legos

18:32 nathanmarz: hmmm, let me clarify

18:32 i want to be able to say (defn foo [[a]] ...)

18:32 or (defn foo [{a :field1}] ...)

18:33 where both versions are passed the exact same object, some sort of ordered map

18:34 rhickey: in the first case you'll have to move the destructuring into a let, (defn foo [amap] (let [[a] (seq amap)] ...

18:36 Chousuke: Which reminds me, what happened to the -> destructuring?

18:36 nathanmarz: if i wrote a class in java which implements map and randomaccess, would that work?

18:36 Chousuke: is there a ticket on it or was it just irc talk?

18:43 rhickey: nathanmarz: clojure.lang.Indexed is the simplest way to add nth

18:44 nathanmarz: rhickey: thanks, will check that out

18:44 rhickey: for RandomAccess you also have to implement j.u.List, which is a bigger deal

19:08 cads: hey it possible to somehow reduce the number of parentheses in lisp expressions by defining an equivalent enriched syntax?

19:09 cark: hehe not gain !

19:09 not again i mean

19:09 cads: hehe, I'll try to be as non-aggravating as possible with this line of question :D

19:10 cark: i guess you're new to lisp ?

19:10 chouser: Chousuke: https://www.assembla.com/spaces/clojure/tickets/211

19:10 hiredman: it's not aggravating, just, you know, something that has recured since the begining of lisp

19:10 chouser: there's even a reader for Clojure that does it

19:11 cads: naw, I've studied lisp a bit, built a toy version and such... but I'm also interested in m-expressions as well

19:11 chouser: and, as it has been since the begining of lisp, nobody uses it much

19:11 cads: chouser, I remember reading about something that does something like this which can be used to wrap virtually any lisp

19:11 hiredman: so you will have to prove you have something better/different over the last 100 or so attempts that no one cares about or uses

19:12 _ato: sweet-expressions or some such

19:12 cark: you'll end up with as many brackets either way, they could be curly, begin/end or python style spaces, but they'll be there

19:12 cads: hiredman, I'm just interested in something to make my own coding more fun, I don't really have any ideas :)

19:13 I think I got the idea of using unicode math charachters for function names from someone's code repository here - I love that

19:13 _ato: oh no

19:14 all well and good until someone tries to call you function and can't figure out how to type your crazy character

19:14 hiredman: ,(pl (↕map (replicate 3 (↕apply vector $ (↕map range $ 10 inc · inc · inc) call · ⌽* $ 10 · call · (⌽+ -2) map)) shuffle))))

19:14 clojurebot: ((60 100 70 50 10 30 20 90 40 80) (100 40 20 60 90 70 80 50 30 10) (100 50 90 40 70 20 60 80 30 10))

19:15 cads: oh, it was you hiredman. kudos.

19:15 hiredman: :)

19:15 cads: ato, with a little editor support it's really convenient and mnemonic

19:15 cark: haha hiredman loves to show off his point free skills !

19:16 cads: but I agree that I would at first be inconvenienced using someone else's notation

19:16 _ato: cads: http://www.dwheeler.com/readable/

19:17 cark: spa mal

19:17 _ato: personally I can't really see the point

19:17 it just makes the syntax more complicated

19:17 cark: err ignore that

19:17 cads: I've used Lisp my whole programming life and I still don't find prefix math expressions natural. - Paul Graham

19:19 Chousuke: cads: if you can represent lists, vectors and maps with reduced delimiters while keeping the macro system as powerful and straightforward as it is, that might be interesting

19:19 cads: that mostly hits it on the head, there are more human understandable ways of encoding term trees

19:19 hiredman: only for a subset of trees

19:19 math trees

19:19 cads: Chousuke, that would remind me of the kind of things the mathematica language does

19:20 hiredman: some other kid of tree

19:20 and they might have different representations

19:20 Chousuke: Luckily you often don't need to write big math expressions in lisp :P

19:20 or if you do, you should break them into smaller functions :)

19:21 hiredman: or just write a parser

19:21 chouser: ~infix

19:21 clojurebot: infix is not worth the trouble; see http://groups.google.com/group/clojure/browse_thread/thread/319a1c77ed718ba/3e4be7484b7cbe38

19:21 cads: wish there was a way to turn a mathetical derivation of an algorithm directly into code :/

19:22 liebke: speaking as someone that does write lots of math expressions in clojure, it starts to feel very natural after a while :)

19:22 Chousuke: it's always possible to write a macro like (math [1 + 2])

19:23 funkenblatt: yeah, i usually do that

19:23 cads: hmm

19:23 funkenblatt: i also like to add a macro for reverse polish notation

19:23 Dawgmatix: fwiw - the usual syntax feels pretty normal after a while :)

19:23 cark: time to introduce the notion that remembering precedence rules is a pain

19:24 cads: you mean it's hard to remember whether something has left or right precedence and associativity?

19:24 funkenblatt: it's a lot easier to remember if you get to set precedences yourself

19:24 hence the advantage of writing your own macro for it

19:25 chouser: I have even have a non-macro fn that does infix, but I can never find it.

19:26 ah, there it is http://paste.lisp.org/display/75230

19:26 ask me how often I've used it in actual programs

19:26 go on, ask me

19:26 that's right, never. :-)

19:27 cads: :P

19:27 well yeah

19:28 Chousuke: Hm.

19:28 I found a version of Lord of the Rings written in Northern Finnish dialect. This is amusing.

19:29 hiredman: http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice.html <-- speaking of choice I was just watching this

19:29 (choice of precedence, choice of parens or not, etc)

19:31 cads: I wonder how often people use haskell's quasiquoting... it lets you define a monadic parser for some expression type and then you can use that grammer in your code, but you have to enclose it like this: eval [$expr|1 + 3 * 5|], where the expression inside the || folls your own rules

19:32 hiredman: possibly applies to the choice of currency primitives

19:32 cads: I just don't think I'd often go through the trouble of typing eval [$exprtyp||], and I'd get sick of reading it

19:33 funkenblatt: depends on how complicated your expression is going to be i guess

19:33 cads: is that why you don't use your infix thing, chouser?

19:34 hiredman: cads: embed your expression as a string and write use fnparse

19:34 eopl assumes some scheme parsing package, but when I first gut it I started futzing with fnparse

19:35 and ended with something that spit out valid clojure for the first toy language

19:35 cads: lemme see what this fnparse is about

19:35 hiredman: which defeated the point, because I could just call eval on it instead of interpreting it myself

19:38 something in my irssi freaks out if I try to tab complete a space

19:43 cads: wish it was easier to find papers about hybrid lisp systems, the all seem to be about scheme or cl. But for example mathematica, which is made of pure expressions where each expression, whether it is a form using advanced LaTeX like typesetting or a basic ascii expression, has a lisp like form

19:43 4

19:43 err

19:43 ignore that..

19:44 defn`: best way to convert ("10" "00") to (10 00)?

19:44 cads: map a str -> num function over your list

19:44 Knekk_: Integer.parseInt()?

19:45 defn`: like (apply #(num %) ("10" "00"))?

19:47 chouser: (map #(Integer/parseInt %) ["10" "00"])

19:47 the-kenny: ,(map #(Integer/parseInt %) ["10" "00"])

19:47 clojurebot: (10 0)

19:47 chouser: ding ding ding

19:47 the-kenny: First :)

19:47 defn`: No way to do it with num or int?

19:48 chouser: no

19:48 cads: hired man, it's so cool to write a family of functions represented by a single symbol indexed by a subscript! Even though that's simply seen as a function with an additional parameter, it is useful, maybe I get this from doing math

19:48 defn`: really? no way at all? That seems weird, I feel like I've done this before

19:48 twbray: For your pre-Thanksgiving pleasure, more Clojure I/O grinding: http://www.tbray.org/ongoing/When/200x/2009/11/25/Clojure-grinding

19:49 avital: Good night

19:49 ,(print-str '(""))

19:49 clojurebot: "()"

19:49 avital: ,(print-str '("a"))

19:49 clojurebot: "(a)"

19:49 avital: Is this a bug? Shouldn't it be "(\"\")" and "(\"a\")" respectively?

19:50 Chousuke: print prints for humans

19:50 ,(pr-str '(""))

19:50 clojurebot: "(\"\")"

19:50 avital: Aha I see

19:50 Right

19:51 Suddenly it does make sense... Ok right so the bug I had when using pr-str was because of something _I_ was doing...

19:51 technomancy: twbray: wow, that's a bummer to find so much time is getting wasted on the UTF-16-ness. kind of powerless to do much about that. =\

19:52 twbray: I should go look at the Java library source code; seems like it shouldn't be that expensive.

19:55 defn`: w00t, I just got approval to use Clojure on a massive data set at work which is currently taking 6 hours to parse

19:55 I'm confident I can get it to below an hour

19:56 twbray: nice post, thanks

19:59 chouser: defn`: what's doing it now?

19:59 defn`: perl

19:59 chouser: nice. let us know how it goes

20:00 defn`: It's a hack job -- I've seen some of the code, basically terrible

20:00 chouser: such is the way of perl, down in the trenches, doing its job.

20:00 defn`: but yeah I'm planning on setting up a dedicated clojure blog tonight to start documenting

20:00 chouser: excellent

20:01 defn`: one question i have on twbray's post, if youve had a chance to read it

20:01 chessguy: 'ello

20:01 twbray: defn`: Perl is ugly but fast

20:01 defn`: why use the java.nio.charset.CharsetDecoder?

20:01 hiredman: twbray: what does "erlang bias" mean?

20:01 defn`: simply to demonstrate how it runs in a single threaded loop?

20:02 twbray: hiredman: I've been a fan of Erlang for years. If it weren't for the putrid syntax, lousy file handling, and broken string processing...

20:02 defn`: If I could avoid doing the decoding, I'd be real happy.

20:02 hiredman: ok

20:03 twbray: defn`: At the end of the day I need to pass an ordinary string to the per-line function. I think I have to change from the UTF-8 (ascii actually) in the input to Java chars to do that. Do you have a better idea?

20:04 technomancy: twbray: maybe configure your web server to log in UTF-16? =)

20:05 twbray: technomancy: Ewwwwwwwwwwwwwww

20:05 bitbckt: lol

20:05 technomancy: bonus: 45GB of logs becomes 90GB of logs; much more impressive!

20:05 Chousuke: is it just ASCII?

20:05 * twbray gags and snickers simultaneously

20:05 Chousuke: maybe you could read and compare just byte arrays? :/

20:05 bitbckt: twbray: take a picture of that

20:06 twbray: Chousuke: I'm trying to write something so that a user can create a function that takes a string and do ordinary string stuff with it.

20:06 Also I want to use regexes, which require strings.

20:06 Chousuke: hmm :/

20:07 * twbray is hoping defn` has a magic trick that'll work around the painful expensive decoding

20:07 _ato: are hava strubgs UTF-16? Huh... I never knew that

20:07 Chousuke: I wonder if Java strings are really internally UTF-16, or if just the characters are.

20:07 twbray: Yeah, it's UTF-16 :(

20:08 technomancy: this is due to the JVM predating UTF-8, correct?

20:08 hiredman: that is what the internet tells me

20:08 twbray: Back in the early nineties, the Unicode people thought they could get away with what they called "UCS2" and stuff all the characters in 64K. So adopting 16-bit characters seemed plausible for Java back at the time.

20:09 bitbckt: "seemed like a good idea at the time"...

20:11 twbray: are you using the equiv. of new String(<bytes>, 0, <length>, "UTF-16BE") to convert these byte sequences?

20:12 twbray: bitbckt: but the input isn't UTF-16, it's ASCII, i.e. UTF-8

20:12 bitbckt: In that case, use "US-ASCII" as the final arg.

20:13 * twbray wonders if that would make any difference

20:13 twbray: Well... there could conceivably be some non-ASCII in the user-agent and so on.

20:13 bitbckt: You have these to choose from: http://java.sun.com/j2se/1.3/docs/api/java/lang/package-summary.html#charenc

20:13 * bitbckt is unsure which suits your input best

20:14 bitbckt: 8859-1, perhaps.

20:14 It may use the j.n.c.CharsetDecoder, internally.

20:14 I don't know.

20:14 * twbray is embarrassed to realize he doesn't know how HTTP headers are encoded & logged

20:15 bitbckt: Over the wire, they're UTF-8, most often.

20:15 At least, everything I've done with them lately has been.

20:15 twbray: Anyhow, the decoder still seems WAY too slow.

20:15 bitbckt: Increasingly, everything is UTF-8. So I assume you're right.

20:15 bitbckt: Definitely.

20:16 (re: WAY too slow)

20:16 hiredman: looks like http headers are US-ASCII

20:17 twbray: Anyhow, I'll look at the Java library code. Wouldn't be surprised if there's something int here that's causing bad behavior whenI ask it to do 32M at a time.

20:17 Later

20:22 michaeljaaka: hi

20:22 why we can nest #() ?

20:22 can't

20:22 and how to write own macro characters?

20:23 Chousuke: michaeljaaka: 2) you can't and 1) because #(foo % #(bar %)) is kind of confusing and ambiguous

20:24 michaeljaaka: but we could make something like

20:24 #( a b -> .... )

20:25 so I explicite names the arguments

20:25 Chousuke: that's (fn [a b] ...) :)

20:25 the-kenny: michaeljaaka: (fn [a b] (+ a b))

20:25 michaeljaaka: I knew that you will say that

20:25 * technomancy finds himself almost always replacing #() with fns before committing code.

20:25 technomancy: for everything but the simplest functions, usually for java interop.

20:26 the-kenny: I'm using #() for simple predicate-like functions

20:26 Chousuke: (map #(foo %) ...) seems to be a common anti-idiom :P (where foo is a clojure function)

20:26 michaeljaaka: ;)

20:27 hmmm I often have to make

20:27 (map #(apply foo %) ... )

20:28 Chousuke: that's fine

20:28 though I might use (map (partial apply foo) ...)

20:28 michaeljaaka: I have even one function where I have d(g(f(x))) and some have apply and other not, so I can use (-> .... ) :(

20:29 Chousuke: that would be (comp d g f) wouldn't it? :/

20:29 michaeljaaka: ohhh If it is then thanks!

20:29 I will try

20:30 Chousuke: though that ofcourse requires that the output of f is suitable for g as is, and same for g and d

20:31 (partial apply blah) seems pretty common actually

20:31 michaeljaaka: well I wanted to say taht I can't use (-> .. )

20:31 I said "I can use (-> ... )

20:32 Chousuke: I wonder what would be a good name for a function that does that operation

20:32 michaeljaaka: i mean I can't

20:38 defn`: nested-partial?

20:38 deep-partial?

20:38 notallama: Chousuke: perhaps apply with 1 arg could just do that. i was calling it uncurry, but that doesn't really make a lot of sense since functions aren't curried in clojure.

20:38 Chousuke: I guess you could define succinct names for function transformation operations in another namespace and then just expect it to be used with an abbreviated namespace qualifier

20:40 michaeljaaka: how to quickly generate x long vector by filling its value with a func result?

20:41 the-kenny: iterate, repeat, repeatedly

20:41 or for

20:41 (take 10 (repeatedly (rand-int 10)))

20:41 ,(take 10 (repeatedly (rand-int 10)))

20:41 clojurebot: java.lang.RuntimeException: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

20:41 the-kenny: ,(take 10 (repeatedly #(rand-int 10)))

20:41 clojurebot: (1 9 3 6 2 8 6 5 2 7)

20:41 Chousuke: notallama: that could be good. I guess calling apply with one arg makes no sense otherwise?

20:41 ,(apply *)

20:41 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$apply

20:42 michaeljaaka: the-kenny: ok, thanks!

20:42 Chousuke: notallama: very haskellish though :P

20:42 defn`: chouser: what's your formal education in CS?

20:43 Chousuke: was that for me? :P

20:43 defn`: really for anyone

20:43 Chousuke: I'm still a student.

20:43 defn`: same here

20:44 im trying to get an idea of what sorts of stuff i should be taking (if available) to get better at this stuff (concurrency, lisp)

20:44 notallama: Chousuke: haskellish is usually a good thing, i think.

20:45 defn`: we have a scheme course im going to take next semester but other than that im not sure if i should take compilers, etc. or if there is a better place to put emphasis

20:45 Chousuke: notallama: well, sometimes.

20:45 the-kenny: defn`: For concurrency, there is a presentation available at blip.tb

20:45 s/.tb/.tv/

20:45 defn`: yes ive watched that

20:46 Chousuke: notallama: though my opinion of point-free style in Clojure is that it's sometimes good, but not nearly as often as in haskell :)

20:46 defn`: itd be nice to do some small project work using those techniques in school

20:46 the-kenny: And lisp.. hm.. it's experience. You have to learn to think functional ;)

20:46 defn`: :) im still so new to it, i just wanna get better now!

20:46 Chousuke: point-free stuff is really neat in haskell because of currying and succinct syntax for comp and whatnot, but with lisp it just doesn't quite work :P

20:46 the-kenny: It's important to know the api of clojure. There are so much cool functions :)

20:47 s/clojure/every functional language/

20:47 defn`: yeah that's a good point, im gonna just start documenting a-z the functions of clojure

20:48 the-kenny: And else.. try to do some things. Implement some algorithms, work on projecteuler or something like this

20:48 defn`: yeah ive been doing project euler

20:48 notallama: Chousuke: yeah, that's one place where all the parens can hurt. it works sometimes, but it's rather ugly other times.

20:48 defn`: but i gotta a little bored with it

20:48 i think its time to try and build something tangible i can use

20:48 michaeljaaka: what is wrong with that? http://gist.github.com/243169

20:48 defn`: the build system is a bummer

20:48 hou: rhickey, following agent error queue discussion. don't you think it's also an incidental complexity of inverse of control, lost of continuation point, "don't block thread" yada ..., all due to async modeled api. I know you have doubts on continuation, but I'm still wondering if delimited continuation, like scala's or jvm's, is the right model for user api. In fact, I hate all async api (jms, nio, aio) for the same reason. IMHO, they can

20:48 however async they like at implementation level, but they should all be wrapped in delimited continuations. Just give me back my straight through flow control :-)

20:49 the-kenny: defn`: then do something interesting. Hook yourself into the continuous twitter feed and do some data-crunching

20:49 Chousuke: michaeljaaka: repeatedly takes a function

20:49 hou: link http://weblogs.java.net/blog/forax/archive/2009/11/19/holy-crap-jvm-has-coroutinecontinuationfiber-etc

20:49 Chousuke: michaeljaaka: also, github does have Clojure syntax highlighting :)

20:50 defn`: the-kenny: there's a cool idea, twitter feed time :)

20:50 Chousuke: michaeljaaka: it's just hidden towards the bottom.

20:50 the-kenny: I really like the new continuous feed. You get a stream with one tweet per line :)

20:51 michaeljaaka: The JVM can't optimize tail-calls. Try recur

20:52 michaeljaaka: recur can't be used it says something about not being in a tail

20:52 :(

20:52 the-kenny: hm.. I should go to bed.. I have to get up in appros 4 hours.

20:52 michaeljaaka: Look at an example for a recursive funtion in clojure and modify it to your needs

20:52 michaeljaaka: ok

20:53 Chousuke: that's a lazy seq

20:53 recursion is expected

20:53 defn`: how do you use accessor?

20:53 Chousuke: you *can't* use recur :)

20:53 the-kenny: Chousuke: Oh sorry

20:53 michaeljaaka: uff :)

20:54 nothing to do then ;)

20:54 Chousuke: except for the rand-int thing

20:54 the-kenny: defn`: Here is something to get you started: http://gist.github.com/243175 ;) I'll go off to sleep now... byw and good night.

20:54 michaeljaaka: I have found myself often using seq of diff size for my playing with clojure, so I hvae created that function ;)

20:55 defn`: the-kenny: you're great :) Thanks man

20:55 Chousuke: I think you could do it without an explicit lazy seq though

20:56 michaeljaaka: well I'm going to produce very long data

20:56 Chousuke: ,(take 2 (map vec (partition 5 (repeatedly #(rand-int 100)))))

20:56 clojurebot: ([80 2 2 21 58] [48 84 39 98 0])

20:56 Chousuke: higher-order functions :)

20:57 michaeljaaka: :)

20:57 very long seq are needed

20:57 Chousuke: oh, that's fully lazy too

20:57 michaeljaaka: !

20:57 wow

20:57 Chousuke: repeatedly is lazy, partition is lazy, map is lazy, so the whole thing is lazy

20:58 michaeljaaka: hmm but partition splits it in wrong way

20:58 uhhh maybe not

20:59 i will study it

20:59 notallama: is there a built in way for types to take less arguments than they have fields? i could roll my own, but it seems like it'd be a handy feature.

20:59 Chousuke: notallama: deftype? probably not.

21:00 notallama: yeah, deftype.

21:00 michaeljaaka: Chousuke: it is ok, thanks :)

21:01 Chousuke: notallama: you should suggest it to Rich I guess. deftype isn't finalised yet as far as I know

21:05 zaphar_ps: are there any coverage tools for clojure?

21:11 defn`: hmmm, where did base64/encode-str come from?

21:11 java.lang.Base64?

21:11 hiredman: nope

21:11 there is no "official" base64 in the jre

21:11 there is one in sun.misc somewhere

21:11 defn`: java.lang.Object?

21:12 k thanks

21:12 hiredman: sun.misc.BASE64Encoder

21:14 defn`: no such namespace Base64

21:15 BASE64Encoder is there, but no method encode-str

21:15 ahh this is from clojure contrib

21:24 michaeljaaka: why this outputs 332 instead of 2 332? http://gist.github.com/243190

21:27 hiredman: michaeljaaka: you must put function calls inside parens

21:27 qed: http://gist.github.com/243191 How do I use get-stream now that I have it setup?

21:27 michaeljaaka: ok works

21:28 * somnium just discovered ergoemacs (^o^)

21:28 qed: Like let's say I want to get 10 tweets, how can i turn get-stream into a seq?

21:28 michaeljaaka: I have still problem with that: sometimes parens can change the behaviour

21:28 somnium: michaeljaaka: not sometimes, always

21:28 hiredman: uh

21:28 yeah

21:28 michaeljaaka: yeah

21:28 ;)

21:29 hiredman: parens mean "this is a function call"

21:29 michaeljaaka: but without it too works but not like expected :D

21:29 hiredman: so of course parens change the bahaviour

21:29 michaeljaaka: for various reasons that would be tedious to explain

21:29 michaeljaaka: at least compiles without problems

21:29 qed: i edited the gist so it's readable now

21:30 hiredman: qed: pass the inputstream to clojure.xml/parse

21:30 qed: hiredman: thanks

21:30 notallama: fn returns the result of the last thing in it. which in your case is y, michaeljaaka.

21:31 michaeljaaka: ok

21:31 that explains all

21:32 qed: No matching method found: parse for class com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl

21:32 hmmm

21:33 hiredman: (doc clojure.xml/parse)

21:33 clojurebot: "([s] [s startparse]); Parses and loads the source s, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content. Other parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser"

21:33 hiredman: hmmm

21:34 nroot: [

21:34 hiredman: oh

21:34 qed: some is not right

21:34 qed: hiredman: yeah i went out and got the library, i think i was missing it

21:35 libxerces2?

21:35 hiredman: qed: no

21:35 you are not missing the library

21:35 it says the method+argument type combination doesn't exist

21:36 qed: how exactly are you passing the output of get-stream to clojure.xml/parse ?

21:36 oh

21:36 duh

21:36 this is json

21:36 qed: lol oops

21:36 hiredman: (still the wrong error)

21:36 so use onf of the json parsers

21:36 qed: Thanks hiredman

21:36 hiredman: either clojure-json, or the one from contrib

23:39 KirinDave1: _ato: How long is "a few seconds"?

23:40 _ato: KirinDave1: 2.8s

23:40 just a first run, so not JITed

23:40 KirinDave1: Can't wait to get your version of clojure. :)

23:40 cark: that's an average of 2 record per user ... not much

23:40 KirinDave1: Aww, ran out of heap space.

23:40 _ato: err wait

23:40 maybe I mistyped

23:40 alexyk: when I wrap time around a def, (time (def users (...))), how do I still get users defined at the top level of repl?

23:41 _ato: no I misread

23:41 it said 28000 I read 2800 ms

23:41 :p

23:41 cark: alexyk : def doesn't need to be top level to do its work

23:41 alexyk: cark: how does clojure do scoping then? let?

23:42 and def injects at the top?

23:42 somnium: def creates vars

23:42 alexyk: somnium: in which scope?

23:42 _ato: namespace-scoped

23:43 so def essentially creates global variables

23:43 wherever it is called from

23:44 alexyk: ok, same result with long, 776261 user, and about 700M also eaten. Probably first slow run was a fluke, although scary.

23:45 nroot: I am trying to write a echo server in clojure. I did in java using the one thread per client model but its not very scalable.

23:45 alexyk: this is very sizzling! it means I can use maps to do data mining on twits. Next I'll run it on 100M twits, somnium, we;ll see how congomongo holds up :)

23:45 nroot: But it works fine in Erlang because of low cost of creating a thread

23:45 What is the scalable way to do it in Clojure ?

23:46 somnium: alexyk: let me know, I've mostly been using it for prototyping :)

23:47 _ato: nroot: you need to use non-blocking sockets

23:47 using java's "nio" IO library

23:48 alexyk: somnium: I was wondering, congomongo jar has only one class in it, the rest are .clj files. How does clojure execute them?

23:48 somnium: alexyk: the current assessment seems to be that it's 'not obviously broken'

23:48 alexyk: somnium: I like it!

23:48 somnium: alexyk: clojure compiles .clj files to .class files when you load them

23:48 alexyk: ah, ok.

23:49 nroot: So it will be parallel to NIO implementation of Java. Does clojure as a language provide any advantage in this ?

23:49 alexyk: somnium: if I want to use coerce, is the example in congomongo_test.clj the one to follow?

23:49 I'd read json from stdin and insert

23:49 _ato: nroot: not at the moment as far as I know

23:49 somnium: yeah, its a pretty short function, the source is hopefully readable too

23:50 * alexyk knows how to use actors in Scala to share a thread pool, but now in clojure :)

23:50 _ato: nroot: http://ossareh.wordpress.com/2009/10/12/learning-nio-via-clojure/

23:50 nroot: _ato: Thanks :-)

23:51 _ato: I agree with the author of that post though, nio and (Java IO in general) sucks pretty bad compared to more posixy languages

23:51 somnium: I have a version with deftype and defprotocol thats about 3x faster, but 1.1 isn't even official yet

23:51 alexyk: somnium: if you push it into a branch on github, I'd be happy to test

23:52 _ato: nroot: looks like there's a followup post as well: http://ossareh.wordpress.com/2009/10/13/learning-nio-via-clojure-pt-2/

23:52 alexyk: I'm using 1.1-alpha-snapshot from github anyways

23:52 somnium: ok, you'll need clojure-new branch and recompiled contrib too :p

23:52 I hope deftype and friends makes into 1.1

23:53 alexyk: somnium: so (1) clojure-new then (2) recompile the master of contrib from github?

23:53 somnium: yeah

23:55 qed: hey all

Logging service provided by n01se.net