#clojure log - Aug 27 2009

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

0:07 lowlycoder: this really bit me: are vars created via defn and def dynamically, rather than lexicallys coped?

0:07 are bindings created via let lexically scoped, or are they somehow dynamicallys coped too?

0:20 rathore: let is lexically scoped

0:21 JAS415: uh

0:21 let is lexical

0:21 def and defn are dynamic

0:21 (vars)

0:21 binding form can alter a var's.. binding

0:31 lowlycoder: anyone here running clojure on the mac?

0:46 tomoj: yeah

0:51 durka42: me too

0:59 rathore: me too

1:01 development on mac, all deployments on ubuntu

1:02 durka42: rhickey uses a mac too, doesn't he

1:04 tomoj: I've seen him use a mac in presentations

1:04 and emacs :)

1:10 JAS415: im use ubuntu

1:51 adityo: good morning folks

1:54 why do we use #^ before a form? reading some code, seen it in a couple of places

2:00 okie got it! works as metadata keys

4:15 tomoj_: YEEESSS http://skitch.com/tomoj/bhhw5/terminal-java-80x24

4:15 now to get this working with clojure :D

4:20 Fossi: weird :D

4:23 tomoj_: it's not ideal for my purposes but I think it's better than writing my own ncurses or ansi stuff

4:24 Fossi: it would be fun to port swing to that

4:26 tomoj_: some other implementations I found sortof did that

4:26 swing-like APIs

4:26 couldn't get them to work

4:27 I don't want swing-like anyway really

4:37 :D http://skitch.com/tomoj/bhhsj/terminal-java-80x24

4:39 noidi: cool :)

4:58 lowlycoder: since clojure only provides the ACI in ACID, what should I use for durability?

5:02 dosync: lowlycoder: Have you looked at clojure.contrib.sql for working with sql databases?

5:02 lowlycoder: i don't want to touch sql

5:04 Fossi: lowlycoder: schema free databases work pretty well for us. couchdb, google appengine datastore and such

5:05 lowlycoder: does couchdb actually require erlang to run?

5:05 Fossi: well, as much as apache requires C to run

5:07 tomoj_: I got it running on my mac without much trouble if I remember correctly

5:08 sudo port install couchdb

5:08 lowlycoder: hmm; best solution so far looks like sqljet

5:08 tomoj_: thought you didn't want to touch sql?

5:08 lowlycoder: my bad

5:08 i don't want an external server

5:08 horribly said

5:09 somehoq mentally i group sql with mysql and postgresql and oracle

5:09 but not with sqllite

5:09 my fault definitely

5:09 Fossi: ah, that's another story then

5:09 lowlycoder: oh; explain

5:09 tomoj_: well looks like sqljet actually doesn't have a sql interface..

5:09 :)

5:11 lowlycoder: does clojure have 'builtin' serialization/deserialization?

5:12 tomoj: well.. the basic data structures are readable

5:14 ,(read (java.io.PushbackReader. (java.io.StringReader. "[1 2 3]")))

5:14 clojurebot: [1 2 3]

5:15 lowlycoder: ,(java.io.StringReader. "[1 2 3]")

5:15 clojurebot: #<StringReader java.io.StringReader@111c3f0>

5:15 tomoj: but you can't serialize structmaps that way yet without some extra steps

5:27 lowlycoder: why does def write to the global environment rather than the local environment?

5:27 tomoj: if I understand what you mean, the latter is impossible in clojure

5:28 there are no local assignable variables

5:28 lowlycoder: (defn bar [] (defn foo [] ...))

5:29 tomoj: use let or letfn

5:29 lowlycoder: why can't i have this become (defn bar[] (let [foo fn [] ...] ..))

5:29 as scheme/lisp tends to interpret it as

5:29 what's the motivation behind clojure's def goes to global env?

5:29 tomoj: it looks like imperative programming

5:30 lowlycoder: clojure or scheme?

5:30 tomoj: using def in the way you want

5:30 e.g. a clojure newbie might want to write (def x (inc x))

5:30 where they would write x=x+1 in an imperative language

5:30 lowlycoder: whereas in this way, when I execute bar, it redefiens foo on the fly

5:30 and breaks all my code

5:31 tomoj: I'm not sure the code you wrote above makes sense

5:31 defn returns a function, it doesn't execute the body

5:31 (defn bar [] (defn foo [] ...)), even if it "wrote to the local env", wouldn't be equivalent to (defn bar [] (let [foo (fn [] ...)] ...))

5:32 lowlycoder: why ot?

5:32 *not*

5:32 tomoj: the latter executes the body of the let form

5:32 the former just returns a function

5:33 defn doesn't say "define foo to be this function and then do this with it"

5:33 it just says "define foo to be this function and return it"

5:33 you would need (defn bar [] (defn foo [] ...) (<something that uses foo>))

5:33 and that's evil

5:34 defn is supposed to be toplevel, if you want to lexically bind something, use the lexical binding forms :)

5:34 lowlycoder: are there any besides let nad letfn?

5:34 i just don't wnat the following code to be indented

5:35 tomoj: it should be indented imo

5:35 it's in a new context

5:35 lowlycoder: scheme/lisp doesn't do it that way; old habits die hard

5:35 tomoj: loop and for do lexical binding, there may be others

5:36 how does lisp do it?

5:36 lowlycoder: well, I can say things like

5:36 (define (foo ...)

5:36 (define (bar1 ...) .... )

5:36 (define (bar 2 ...) ... )

5:36 ... some code involving bar1 and bar 2 ... )

5:36 without bar1 bar2 becoming global forms

5:36 whereas in clojure I have to do

5:37 (define foo [...]

5:37 (letfn [[bar1 [] ....]

5:37 [bar2 [] ....]

5:37 ]

5:37 ... more code ... ))

5:37 the identing just looks more uglier and mucm more to the right

5:38 _mst: common lisp is the same--you would have to use flet/labels to get the effect you're after (as in clojure)

5:38 lowlycoder: okay; scheme then :-)

5:38 tomoj: that seems evil to me

5:38 Chousuke: I suppose defn could be made context-aware.

5:38 but it'd be weird.

5:39 lowlycoder: why?

5:39 tomoj: I don't think it's the defn equivalent that's special in scheme, just guessing

5:39 because apparently those defines can only come at the beginning of the body

5:40 Chousuke: hmm :/

5:40 tomoj: let would need to be made aware that defs at the beginning of its body are really lexical bindings

5:40 well, let and defn and etc

5:40 but I think a form that's using lexical bindings should be contained in the forms that set up those bindings

5:40 lowlycoder: you could always write a macro

5:41 Chousuke: well, defn could just check a bound var and emit a letfn instead of def if it is bound to true, and bind it to true if it's false

5:41 lowlycoder: i can't express this as a macro

5:41 tomoj: how would this macro look like? macros have to 'contain' the parts in them

5:41 the define i want needs to run to the end of the currnt environment

5:41 tomoj: you would need to use the macro at the toplevel

5:41 e.g. use silly-defn instead of defn

5:42 which goes through and replaces defs with lexical bindings

5:42 lowlycoder: hmm; this could be interesting

5:43 looks like the keyword define isn't taken up either :-)

5:43 Chousuke: clojure has a peculiar feature btw.

5:43 lowlycoder: what's that?

5:44 binding to vars rather than values?

5:44 Chousuke: user=> (def def 1) -> #'user/def, user=> def -> 1, user=> (def foo 1) -> #'user/foo

5:44 lowlycoder: wt

5:44 f ... isn't clojure a lisp 1?

5:45 Chousuke: yes

5:45 tomoj: I guess you would have to go through the forms in the body and macroexpand, and take-while the car is def, then convert those into a let that you wrap around the rest of the body

5:45 lowlycoder: how does this work?

5:45 Chousuke: special forms are special only in operator position

5:45 otherwise, they're just symbols

5:45 ,let*

5:45 clojurebot: java.lang.Exception: Unable to resolve symbol: let* in this context

5:46 Chousuke: this is probably a half-bug, but rather harmless anyway

5:46 lowlycoder: (def def (fn [x] (println x))) (def 20)

5:46 Chousuke: lowlycoder: that will give an error :)

5:47 lowlycoder: not the definition, but the (def 20)

5:47 Chousuke: yeah

5:47 lowlycoder: i feel like clojure has great ideas

5:47 but has some ugly hacks

5:47 Chousuke: can't avoid them sometimes.

5:50 purity is sacrificed for practicality if it's more beneficial than maintaining purity.

5:51 lowlycoder: why is this defn more practical?

5:51 Chousuke: well, it's easier for one.

5:51 to implement.

5:52 but also easier to use, because it doesn't have context-dependent effects.

5:53 though the scheme-style define is rather nice.

5:53 liwp: I find the current semantics confusing after scheme, but I guess that's cause I'm used to the scheme semantics

5:54 like lowlycoder I find the letfn forms noisy

5:54 lowlycoder: i actually thougth i had a race condition ....

5:55 liwp: I wrote a toy scheme once and I don't remember enclosed defines being any more difficult to implement than the top-level define...

5:55 lowlycoder: until I learned the real semantifs of defn today

5:55 Chousuke: I usually just do (let [foo (fn ...)] ...)

5:55 liwp: yeah, denf can really bite you

5:55 s/denf/defn

5:55 Chousuke: hmm, I don't have a scheme background so I can't relate to that. :/

5:55 I just use defn on the toplevel

5:56 never occurred to me to use it elsewhere.

5:56 liwp: in the end it's not a big deal after you realize what the semantics are, I was just surprised

5:56 lowlycoder: (defn foo [] 3) (defn bar [] (defn foo [] 4)) ... (bar) ... (foo) -> 4 ... WTF??? :-)

5:56 liwp: Chousuke: if you have a look at SICP they use inner defines all over the place

5:57 Chousuke: I suppose common lisp people would be equally surprised by nesting defines if they had no knowledge of scheme :)

5:57 tomoj: I was

5:57 liwp: yep :)

5:59 tomoj: it would be very weird to me for defn to mean something different when it's at the beginning of a let/defn/etc body

6:00 liwp: I just think it's a really nice way to define helper functions that are not used anywhere else

6:00 lowlycoder: liwp: so how do you handle this now? just using let and letfn?

6:00 liwp: yep

6:01 to be honest I haven't really had to deal with it much

6:01 so it's not really a problem at all, just an observation

6:03 Chousuke: I suppose the extra indentation caused by letfn is unnecessary in a way, but I don't think it's that bad otherwise :)

6:06 lowlycoder used vectors earlier to contain the function bodies but I use the form (letfn [(foo [x y z] ...) (bar [] ...)])

6:07 I like the scheme define for one other reason though, which is that the function definition looks like you're defining the value of a function call :)

6:09 eg. (define (f x) whatever) looks like it's defining (f x)

6:09 clojurebot: x is w

6:10 AWizzArd: xhatever?

6:18 tomoj: I like the body of letfn indented

6:19 it shows me visually that that body is being executed within a special context

6:22 Fossi: how do i get the class for a Class? as in String.class

6:22 clojurebot: for is not used enough

6:22 Fossi: (class String) says java.lang.Class

6:22 clojurebot:

6:23 febeling: is there a way a know the name of the function that currently executes?

6:24 liwp: ,(.getClass "foo")

6:24 clojurebot: java.lang.String

6:24 liwp: is that what you want?

6:24 Fossi: liwp: i can't create the object

6:24 liwp: ,(type "foo")

6:24 clojurebot: java.lang.String

6:24 Fossi: as in, i don't have an instance

6:24 liwp: ahh

6:24 what do you have?

6:24 Fossi: a name ;D

6:24 liwp: you have to use Java's classForName magic

6:25 give me a minute

6:25 Fossi: i need to pass (DocumentListFeed.class) to an api

6:26 liwp: ,(Class/forName "java.lang.String")

6:26 clojurebot: java.lang.String

6:26 liwp: that can possibly throw all kinds of evil exceptions <http://java.sun.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String, boolean, java.lang.ClassLoader)>

6:27 Fossi: does that help?

6:27 Fossi: it's evil (tm) ;)

6:28 liwp: indeed

6:28 tomoj: so there's no way to get from a literal classname to a class object?

6:28 liwp: I have no idea if Clojure gives you some nicer way to get the class

6:28 tomoj: (without instantiating)

6:29 liwp: tomoj: Class.forName gives you the class, no instance required

6:29 tomoj: ,(class Math)

6:29 clojurebot: java.lang.Class

6:29 tomoj: liwp: yeah, but you have to use a string

6:29 liwp: oh yeah

6:29 missed dthat

6:29 tomoj: Fossi: I guess you already tried just passing DocumentListFeed?

6:35 liwp: ,(.newInstance String)

6:35 clojurebot: ""

6:36 liwp: so it seems that class names work as class literals in clojure, cool

6:36 tomoj: seems to work fine to me

6:36 liwp: this is probably obvious if I think about it a bit...

6:36 tomoj: ,(.isAssignableFrom Number Integer)

6:36 clojurebot: true

6:37 tomoj: I don't like this idea that there's a separate class object which isn't the class itself

6:39 I wonder how clojure gets the class object

6:41 liwp: what is (cast) good for?

6:42 tomoj: throwing exceptions I guess

6:42 liwp: yeah, that's what I think as well...

6:42 ,(source cast)

6:42 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

6:43 liwp: urgh

6:43 achim: hmm, as far as i know, all classes are Class objects in java, there's not really a distinction. class names evaluate to Class objects in clojure

6:44 ,(instance? Class Number)

6:44 clojurebot: true

6:45 tomoj: right, but class names don't evaluate to class objects in java

6:45 that's what I don't like

6:45 liwp: tomoj: you don't like that in Java?

6:45 tomoj: calling a static method should just be calling a method on the class object

6:45 liwp: rubyist..

6:46 liwp: tomoj: ahh, got it

6:59 Chousuke: java has primitives in addition to classes too, which complicates things :/

7:00 AWizzArd: Is there something like a lazy slurp in Clojure?

7:00 For reading/parsing huge files?

7:00 Chousuke: well, there's line-seq

7:01 AWizzArd: but if the line separator is not \n but instead a more complex regex?

7:01 Chousuke: hmm

7:02 maybe you'll need your own sequence then :/

7:02 AWizzArd: yup, oki

7:30 cschreiner: Any work done on integrating Clojure with cocoa?

7:30 and if not, is this interesting?

7:45 achim: cschreiner: are you thinking about a clojure port or a cocoa bridge?

7:45 cschreiner: achim: yes

7:45 both

7:45 but first, a bridge

7:47 achim: well, there's rococoa, but no clojure-specific project i know of

7:47 https://rococoa.dev.java.net/

7:52 Fossi: clojures error messages are so not helping if you have an outdated api documentation

7:53 is there an easy way to get a classes' inherited methods?

7:55 tomoj: I think show from c.c.repl-utils might do what you want

7:57 count is constant time on vectors, right?

7:59 Fossi: ah, excellent

7:59 i also discovered that reading helps

7:59 achim: tomoj: yes, constant time for everything "counted?"

8:00 tomoj: achim: ah, thanks

8:04 achim: rhickey: the docs of clojure.zip/down promise to return nil if there are no children, but that doesn't seem to be guaranteed, actually

8:05 ,(-> [1] clojure.zip/vector-zip clojure.zip/down clojure.zip/down)

8:05 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer

8:05 achim: rhickey: may i create issue + patch for this?

8:06 Chouser: achim: is that the same as http://www.assembla.com/spaces/clojure/tickets/135

8:08 achim: Chouser: ah, yes, this patch will fix it

8:09 Fossi: how do you read a simple string from the repl while running a program?

8:13 Chouser: achim: is that causing you an actual problem, or is it just a discrepency with the docstring?

8:16 AWizzArd: For big files (do (def x (lazy-seq (slurp "/big.file"))) (count x)) gives me a stack overflow, while the same thing without lazy-seq doesn't. Can anyone confirm/explain that please?

8:21 Instead of confirming this it would also be good to know if it works for you without stack overflows.

8:30 achim: Chouser: well, it's not something i can't work around, but yes, it would make things simpler if it just returned nil on leaves

8:37 Chouser: but that patch doesn't return nil, it throws an exception.

8:40 rhickey: this was discussed here previously

8:42 Chouser: achim: http://clojure-log.n01se.net/date/2009-06-23.html#16:27b

8:42 there you go. go for it.

8:44 rhickey: don't neglect: http://clojure-log.n01se.net/date/2009-06-23.html#17:00

8:45 rhickey: children could check if node is branch and throw if not

8:45 kotarak: rhickey: should it throw or return nil?

8:45 rhickey: throw

8:45 Chouser: thanks for pulling that up so fast!

8:46 achim: Chouser: thanks!

8:46 Chouser: the throw is #135 which has a patch. achim's seeing the earlier issue, which the log seems to claim is #134, but that doesn't match.

8:49 Fossi: a

9:15 saml: ==> (+ 1 2)

9:15 !bot

9:16 Chouser: ,(apply str (reverse "lmas"))

9:16 clojurebot: "saml"

9:17 AWizzArd: does anyone else also get an exception for counting the chars in big files that were slurped in a lazy-seq body? See my example above, from one hour ago.

9:17 saml: ,(apply str (interleave ["nicely, "] ["done"]))

9:17 clojurebot: "nicely, done"

9:28 Chouser: ,(class (first (lazy-seq "abc")))

9:28 clojurebot: java.lang.Character

9:28 Chouser: ,(class (second (lazy-seq "abc")))

9:28 clojurebot: java.lang.Character

9:28 Chouser: ,(class (next (lazy-seq "abc")))

9:28 clojurebot: clojure.lang.StringSeq

9:30 Chouser: ,(class (lazy-seq "abc"))

9:30 clojurebot: clojure.lang.LazySeq

9:30 Chouser: ,(counted? (lazy-seq "abc"))

9:30 clojurebot: false

9:31 Chouser: AWizzArd: there's your problem. LazySeqs and StringSeqs are not counted, so require

9:32 hm

9:33 liwp: is there a zip function in clojure that produces tuples?

9:34 or vectors I guess would be more appropriate

9:34 Chouser: ,(map vector '(a b c) '(d e f))

9:34 clojurebot: ([a d] [b e] [c f])

9:34 liwp: ah yes

9:34 why didn't i think of that...

9:34 Chouser: AWizzArd: counting a seq like that will at least be O(n), so you should do that. But I think it ought not overflow the stack.

9:35 AWizzArd: I am also surprised that it overflows.

9:35 Chouser: liwp: in clojure, map is _the_ way to walk more than one collection in lockstep.

9:36 liwp: AWizzArd: I thought that the problem might be holding on to the head of the seq with the def, but again that should cause an OOM error rather than overflow the stack

9:36 Chouser: fair enough

9:37 Chouser: I quite like the way how you can give map more than one seq to walk, unlike haskell and friends that only do one seq at a time

9:37 Chouser: liwp: I guess there are others, but it's certainly the one to reach for first. The other is loop/recur and things built on one or the other (zipmap, contrib indexed)

9:37 lpetit_: hello

9:38 liwp: Chouser: I'm just used to looking for zip and couldn't find it so I used map, but didn't think of using vector as the map operation

9:38 Chouser: lpetit_: g'morning.

9:40 lpetit_: brainstorming : is the general problem of coupling STM with a database transaction solved?

9:40 cemerick: Chouser: any take on this: http://groups.google.com/group/clojure/browse_frm/thread/a0f30c25122cd232

9:43 Chouser: ,(count (lazy-seq (apply str (range 1e5))))

9:43 clojurebot: java.lang.StackOverflowError

9:44 cgrand: AWizzArd: looks like a bug StringSeq is counted but doesn't implements count() so ASeq/count() causes the stack overflow

9:45 Chouser: same pb if you use seq instead of lazy-seq

9:45 AWizzArd: Sounds plausible.

9:45 Chouser: cemerick: I imagine zip was writen before ::foo worked.

9:46 rhickey: Chouser: right

9:47 dmix: does anyone know of any good open source clojure apps with a command-line interface?

9:47 Chouser: cgrand: yep, you nailed it. anything that implements IndexedSeq should provide a count() method.

9:48 rhickey: patch welcome

9:48 cemerick: rhickey: seems like that should get fixed?

9:48 oh, sure :-)

9:48 rhickey: I didn't know if you wanted to keep those slots the way they are for compatibility purposes.

9:49 rhickey: cemerick: I meant patch welcome for StringSeq, let me look at your thing...

9:50 cemerick: ah :-)

9:50 it's not a problem really, just a slight inconsistency

9:50 rhickey: cemerick: so you just want to use ns-ed keywords in zip?

9:50 cemerick: makes sense to me *shrug*

9:51 cgrand: rhickey: patch ready for StringSeq, I'm checking all classes implementing Counted

9:51 cemerick: there is no 'zip' ns, after all

9:51 rhickey: that's fine by me, definitely predated ::

9:51 cemerick: OK, I'll set up a ticket and patch

9:52 AWizzArd: cgrand: very nice, thanks. Good good, another bug eliminated :)

9:53 Chouser: cgrand: probably in 1.0 as well

9:55 * Chouser could use when-peek

10:05 AWizzArd: regexperts: how can i split a string on a comma when the comma is not between the markers ( and )? Example: "1,2,3,(4,5),6" should result in ["1" "2" "3" "(4,5)" "6"].

10:06 Chouser: AWizzArd: need to handle nested parens?

10:06 AWizzArd: no

10:09 Chouser: ,(re-seq #"(?:\(.+\)|[^,]+)+" "1,2,3,(4,5),6")

10:09 clojurebot: ("1" "2" "3" "(4,5)" "6")

10:09 Chouser: that won't include an empty string if you have ,, in the input

10:10 AWizzArd: uh, thanks. Funny write-only regex

10:11 Chouser: ,(re-seq #"\(.+\)|[^,]+" "1,2,3,,(4,5),6")

10:11 clojurebot: ("1" "2" "3" "(4,5)" "6")

10:11 Chouser: that's the same, just shorter.

10:11 bah, also broken.

10:11 ,(re-seq #"\(.+\)|[^,]+" "1,(2,3),,(4,5),6")

10:11 clojurebot: ("1" "(2,3),,(4,5)" "6")

10:12 Chouser: ,(re-seq #"\(.*?\)|[^,]+" "1,(2,3),,4,(5,6),7,8")

10:12 clojurebot: ("1" "(2,3)" "4" "(5,6)" "7" "8")

10:12 Chouser: there

10:12 AWizzArd: danke

10:12 durka42: "\(.*?\)" match anything between two parens, but non-greedily, so you get the shortest match possible instead of the longest. "[^,]+" match a string of things that aren't commas. "|" allow either of them.

10:14 liwp: ,(re-seq #"\(.*?\)|[^,]+" "1,(2,3),,4,(5,6)foo,7,8")

10:14 clojurebot: ("1" "(2,3)" "4" "(5,6)" "foo" "7" "8")

10:14 liwp: is that desired? (see foo)

10:16 so the first pattern should probably be something like \(.*?\)[^,]*

10:16 ,(re-seq #"\(.*?\)[^,]*|[^,]+" "1,(2,3),,4,(5,6)foo,7,8")

10:16 clojurebot: ("1" "(2,3)" "4" "(5,6)foo" "7" "8")

10:17 liwp: ,(re-seq #"\(.*?\)[^,]*|[^,]+" "1,(2,3),,4,bar(5,6)foo,7,8")

10:17 clojurebot: ("1" "(2,3)" "4" "bar(5" "6)foo" "7" "8")

10:18 Chouser: ,(re-seq #"(?:\(.*?\)|[^,()]+)+" "1,(2,3),,4,bar(5,6)foo,7,8")

10:18 clojurebot: ("1" "(2,3)" "4" "bar(5,6)foo" "7" "8")

10:20 liwp: Chouser: hmph, now I have to try to understand what that actually does ;-)

10:20 what's the ?: in the beginning? Something to do with Java's regexp support?

10:20 Chouser: hehe

10:21 (?: ) is a non-capturing group

10:21 liwp: ah, ok

10:21 Chouser: perlism, if I had to guess.

10:21 liwp: why do you care in this case? or do you?

10:21 isn't everything related to regexps a perlism...

10:22 Chouser: I need to group so that I can say + at the end, that is any number of paren or non-comma-nor-paren sections, alternating 1 or more times

10:22 liwp: but do you care whether it captures or not?

10:23 I mean wouldn't (...) work just as well?

10:23 Chouser: I need to avoid capture because re-seq will emit seqs instead of strings if there are any captures.

10:23 liwp: ah, got it

10:23 Chouser: ,(re-seq #"(.)." "12345")

10:23 clojurebot: (["12" "1"] ["34" "3"])

10:23 Chouser: I mean vectors. :-)

10:23 liwp: makes sense, thanks

10:24 so the regexp mathes everything that is in parens or that is not a comma or a paren

10:24 just verbalising it for myself

10:46 Chouser: (aget #^bytes buffer 0) ; will 0 be unboxed for each call? that is, would (int 0) be any better?

10:48 my guess is that (int 0) would indeed be better.

10:50 stuartsierra: I thought all Clojure functions receive boxed argument.

10:50 Chouser: aget is inlineable

10:52 so when called directly (not passed as an arg to something), it acts like a macro, expanding in-place to a java static method call

10:52 stuartsierra: Then I would assume the arguments to the static method call are boxed.

10:52 Chouser: in this case (clojure.lang.RT/aget #^bytes buffer 0)

10:53 the aget method has several overloads, all of which take a primitive int as the second arg

10:54 so that int must be unboxed before being passed to the java method. My question is whether 0 gets unboxed once at compile time, or once per call at runtime.

10:59 liwp: Chouser: IIRC people have been reporting that they get better performance with (int i) in agets

11:00 e.g. http://groups.google.co.uk/group/clojure/msg/59161c122a29233e?hl=en

11:00 danlarkin: I seem to remember a while ago there was talk of an abstract representation of a queue, with a producer & consumer, does anyone remember/know what became of that?

11:03 Chouser: liwp: ah, very good. thanks.

11:07 liwp: Chouser: there was some blog post which was a bit more informative (can't find it now), but in any case it seems that coercing indices when dealing with arrays is a good thing at the moment

12:39 ping

12:39 ~ping

12:39 clojurebot: PONG!

12:49 liwp: mock objects

12:49 piffle

12:49 ~mock objects

12:49 clojurebot: Your mock object is a joke; that object is mocking you. For needing it. -- rhickey

12:49 liwp: maybe expect should not be renamed mock after all ;-)

12:50 rhickey: Is that name under consideration? - ick

12:50 liwp: I think Stu renamed it already in contrib

12:51 cemerick: har har

12:51 rhickey: when did you throw off that gem?

12:52 rhickey: cemerick: I don't recall - at a talk a while ago

12:52 cemerick: I've never gotten into the deep waters of testing. Seems like a *lot* of work.

13:54 maacl_: Does anyone have example code that uses clojure-couchdb ?

14:15 wtetzner_: if i want to use clojure code the way you would use json, can i just use the (print ...) function, or do i need to use some special printer to ensure i can read it back in?

14:16 Chousuke: I think you need to use pr

14:16 (doc pr)

14:16 clojurebot: "([] [x] [x & more]); Prints the object(s) to the output stream that is the current value of *out*. Prints the object(s), separated by spaces if there is more than one. By default, pr and prn print in a way that objects can be read by the reader"

14:17 wtetzner_: ok

14:17 thanks

14:17 (doc prn)

14:17 clojurebot: "([& more]); Same as pr followed by (newline). Observes *flush-on-newline*"

14:27 wtetzner_: (doc pr-str)

14:27 clojurebot: "([& xs]); pr to a string, returning it"

14:30 wtetzner_: being able to print and read clojure data structures is really nice

14:30 rathore_: do you guys think its OK to send a clojure job posting on the google-mailing-list?

14:30 wtetzner_: it's perfect for use as a data format in a client-server application

14:32 rathore_: wtetzner_: i use exactly that in swarmiji - to send job information back and forth between requesters & workers

14:32 ,(doc pr-str)

14:32 clojurebot: "([& xs]); pr to a string, returning it"

14:41 Chouser: rathore_: there has been one or two before. I would guess it's ok.

14:44 rhickey: rathore: yes, fine by me

14:46 cemerick: heh, I didn't notice the prior job postings. Good to see :-)

14:52 rathore_: rhickey: thanks

14:56 rhickey: rathore_: sure, glad to see it!

15:27 cemerick: are there any recommended idioms for implicit bindings established by macros?

15:28 Chousuke: other than "don't" and "document"? :P

15:28 cemerick: heh

15:28 Chousuke: I just knew that was going to be the response. :-D

15:30 Chousuke: I'm not aware of any idioms

15:30 Chouser: do you mean dynamic bindings, like the with-* macros?

15:32 cemerick: no, implicit bindings, like 'this' in proxy method impls.

16:13 jensli: I had a job writing C# for a big, evil corporation. Now that has ended and I have placed an order for "Programming Clojure", Im going to spend my time hanging in cafes with my laptop, learning to lisp functionlly.

16:15 arbscht: good luck. perhaps you can contribute to the clojure-clr project, too :)

16:19 jensli: Im going to keep far away from clr.

16:25 Chouser: ha! delaying the middle of each finger tree also removes the threat of stack overflow.

16:25 * Chouser crosses that one off the todo

16:33 wavister: ... so if you want to give someone the middle finger, it might take a while?

18:13 hiredman: http://www.thelastcitadel.com/images/clojurebot.png

18:15 wavister: not sure why i'm looking at your inbox...

18:15 danlarkin: it's a _wave_

18:15 durka42: lower right corner

18:16 danlarkin: maybe?

18:16 no

18:16 nevermind

18:16 wavister: ... xmpp transport from wave to the irc clojurebot?

18:16 danlarkin: I redact my wave comment

18:20 hiredman: no

18:20 just clojurebot via xmpp

18:22 wavister: spiffin!

18:25 why is this so:

18:25 ,(= (long 1) 1)

18:25 clojurebot: true

18:25 wavister: ,(clojure.set/union #{(long 1)} #{1})

18:25 clojurebot: #{1 1}

18:26 rhickey: ,(.equals (long 1) 1)

18:26 clojurebot: false

18:26 wavister: ack. is there a way to do sets using = instead of .equals?

18:26 rhickey: in order for Clojure sets to be java.util.Sets, they need to use .equals

18:26 wavister: oh

18:59 tomoj: huh?

18:59 I don't get it

18:59 ,(= #{1 2 3} #{3 2 1})

18:59 clojurebot: true

18:59 tomoj: oh, you mean the elements I guess

19:16 wtetzner_: so is java.util.Set an interface?

19:17 hiredman: ~jdoc java.util.Set

19:22 wavister: hiredman: can I add clojurebot to my friends list?

19:23 hiredman: clojurebot@thelastcitadel.com

19:23 wavister: spiff

20:22 * Chouser grumbles about Haskell's apparent willingness have things defined in random order.

20:23 Chouser: why people think it would be better to allow similar out-of-order definitions in .clj files is beyond me.

20:29 krumholt__: i would like that :)

20:31 i program a function than i think of some helper function i might need and then i have to write that function above the the one i am writing. i like to order my code so that i see the main functions first and can read up on the helper function when i need to

20:33 wavister: i've thought about that... you'd have to have a future pointing to a perhaps never defined function in the ns, and in parallel def your functions later to fulfill that future

20:35 krumholt__: wavister, load-file could just order the functions before evaluating them?

20:35 cemerick: Chouser: is the haskell just masochism or something justifiable? ;-)

20:35 Chouser: it's solvable technically, but you'll end up with big ol' jumble

20:35 wavister: what if there was a with-futures function similar to the with-local-vars, which just took a list of symbols to define within the clojure

20:35 clojurebot: function is <Chouser> there is one class per fn, one instance of it per closure

20:36 Chouser: wavister: 'declare'?

20:36 wavister: in with-futures, each line would be evaluated in parallel rather than sequentially

20:36 Chouser: cemerick: trying to understand the finger-tree paper.

20:37 cemerick: ah

20:37 I can read ML and its kin, but haskell is just unintelligible to me.

20:37 wavister: Chouser: i haven't messed with declare. maybe...

20:43 cemerick: whoa, I just typed 'disclosure' as 'disclojure'

20:45 wavister: muahaha

23:37 technomancy`: I've got a macro that generates a proxy form, but it's complaining "Caused by: java.lang.Exception: No such var: sketchbook.applet/this" when I try to bind this

23:37 http://p.hagelb.org/applet.clj.html

23:38 what's the trick to writing a macro that can do that?

23:43 hmm... (declare this) fixes it... but now I get an error running the macro even though running the macroexpansion works fine. I didn't think that was possible.

23:44 "Can't refer to qualified var that doesn't exist" when I try to run the macro. =\

23:45 cark: did you try ~'this ?

23:45 in the macro definition

23:46 technomancy`: cark: that solves the first problem; thanks

23:46 I think the second problem is due to the fact that my macro first defs a var and then tries to refer to the var in a defn inside the same macro

23:47 on second thought I don't really need the second defn to be inside the macro.

23:47 cark: i'm not sure you're right

23:48 mhh

23:50 the macro produces the code, then the defs are avaluated in order

23:51 so that's exactly the same as having the macroexpansion in your source file

23:52 technomancy`: that's what I thought except... well... it's not the same.

23:52 cark: did you try evaluating the macro-expansion ?

23:53 technomancy`: cark: that's what I mean, the macro-expansion works

23:54 cark: mhh i would call this a bug then ... though that seems hardly possible on such common stuff

23:56 technomancy`: actually my alternate approach breaks since proxies can't have metadata. boo.

23:56 hiredman: uh

23:56 if they proxy IMeta


23:57 technomancy`: hiredman: oh, doh.

23:57 good call

23:57 cark: ~paste?

23:57 clojurebot: lisppaste8, url

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

23:58 cark pasted "well that works" at http://paste.lisp.org/display/86170

Logging service provided by n01se.net