#clojure log - Jan 08 2010

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

0:01 mebaran151: heh, it's sort of sad that the Internet actually has so little commerce on it

0:01 defn`: i hereby ban everyone from using -> as a way of showing the return value of some function

0:01 use => or die

0:01 mebaran151: what's the difference?

0:01 defn`: -> is in clojure, => isn't

0:02 mebaran151: that's what I figured

0:02 what do you have against the arrow?

0:02 defn`: nothing really, it just looks kind of like it could potentially br part of the source in certain contexts

0:02 be

0:03 mebaran151: oh you mean in comments

0:03 defn`: like (let [var1 flat [[a [b]] c [[[d]]]] tree]) -> ("flat" "one" "two" "three" "four")

0:03 mebaran151: ah yeah

0:03 => is a lot clear

0:03 *more clear

0:04 defn`: or maybe ~>

0:04 something that's not in clojure anyway

0:04 mebaran151: nah ~> looks like a cool dereferencing macro

0:04 defn`: :)

0:04 somnium: maybe >>--> would be better

0:04 mebaran151: -> brings back semi-fond memories of C

0:04 defn`: ooooo i like that somnium

0:04 mebaran151: ++

0:05 defn`: im working on getclojure.org and am trying to standardize on some bits of the example code

0:05 somnium: though it might be better to keep that for macros too :/

0:05 defn`: http://getclojure.org/docs/_accessor

0:05 mebaran151: defn, you should implement a repl like tryruby

0:05 defn`: mebaran151: someone did it already :)

0:06 mebaran151: oh

0:06 where's?

0:06 defn`: http://github.com/weavejester/clojure-over-ajax

0:06 JonSmith: horay!

0:06 mebaran151: yeah it would be him

0:07 defn`: what do you guys think, is ;=> blah

0:07 mebaran151: this looks way old and way overly complex

0:07 defn`: a good way of representing the output

0:07 mebaran151: it is definitely old

0:07 JonSmith: ; is a comment

0:07 defn`: i know JonSmith, see the above link

0:07 mebaran151: somebody should steal clojurebots code and mod that

0:07 defn`: is that readable to you?

0:07 JonSmith: oh

0:08 yeah that looks fine

0:08 looks like a repl output

0:08 mebaran151: => is far clearer

0:08 to me at least

0:08 because it's like the repl told me it

0:08 JonSmith: could even make it user=> or clojure=>

0:08 mebaran151: that or a simple #, like in terminal tutorials

0:08 defn`: i need to edit the css of my code highlighter to treat comments a bit differently

0:08 JonSmith: or whatever the namespace is

0:08 mebaran151: I'd just keep it =>

0:09 JonSmith: yeah i think its readable

0:09 defn`: so it will add a bit of padding around a ;

0:09 JonSmith: to actually answer the question

0:09 mebaran151: parsing clojure is probably pretty simple, just a bunch of s-expressions

0:09 defn`: JonSmith: k

0:09 mebaran151: shouldn't you be using a straight fixed-width font

0:10 and ~ is unquote

0:10 defn`: mebaran151: who me?

0:11 mebaran151: yeah

0:11 so ~> is actually legit clojure

0:11 defn`: mebaran151: sort of

0:11 ,~>

0:11 clojurebot: java.lang.IllegalStateException: Var clojure.core/unquote is unbound.

0:11 mebaran151: it is in a defmacro

0:11 if you wanted to buid some sort of custom comparator

0:12 defn`: nod

0:12 somnium: ,'~>

0:12 clojurebot: (clojure.core/unquote >)

0:12 defn`: indeed

0:13 somnium: ,(let [+ -] (+ 2 2))

0:13 clojurebot: 0

0:14 mebaran151: I'm also trying to think of a good way to wrap netty

0:14 to make it more clojure esque

0:14 somnium: mebaran151: if you do I will be a customer

0:14 mebaran151: ah, you have any ideas

0:14 I want to learn to netty to implement a nice socket server

0:15 I basically get the system now

0:15 I just need to figure out a way to make it pretty

0:15 I have a basic wrapping that looks like bad Java

0:15 (ie make-handler, tie-handler, make-pipeline)

0:16 somnium: hmm

0:16 mebaran151: and I just want to wrap it something dare I say higher order

0:16 for neo4j, it was natural just to use nested maps

0:16 but I haven't found quite as clear a fit

0:17 somnium: ive this impression that clojure maps well to low level interfaces, since its so good at building abstractions

0:17 mebaran151: well they're good when you have key values

0:17 I was thinking of maybe a vector representing a pipeline

0:17 somnium: but it always seems more awkward to plug into a 'middle-level' java-api

0:18 mebaran151: oh maps well as in relates well

0:18 heh

0:18 I read that as Clojure maps work well with

0:18 (I've been programming too much today)(

0:19 yeah midlevel java-apis always have a very strong flavor of their own

0:19 but I haven't quite grok'ed java.nio yet

0:20 it's not quite like the event based io I'm used to

0:20 somnium: I was never a java-dev, but Ive been trying to use nio for a tcp-ip client thing

0:20 nettys reviews were great but the annotations and javadocs ...

0:20 mebaran151: netty is pretty powerful

0:21 you can just plugin a handler and make it run

0:21 somnium: hmm

0:21 mebaran151: the first thing I've done is created two gen-class to over the two annotation cases

0:21 *to cover

0:21 I haven't quite gotten everything to work yet

0:22 usually I like to develop a representation and then code to make that work

0:22 somnium: Ill have to look at it again

0:22 or wait for you to make in work

0:22 mebaran151: but it's whole stream model and channelhandler interface is just begging for Clojure functions

0:23 what I want is a performant way to hook a the input of buffer and the output of a buffer into the input of a function and the output of a function

0:23 i think that's the most functional way

0:23 somnium: that sounds cool, would make a very pleasant api

0:23 mebaran151: with special ops :open and :close to represent opening and closing the channel

0:24 (because there isn't any data there)

0:26 should I pass clojure people the raw buffers or should I coerce to string?

0:27 somnium: anyway to parameterize it? raw buffers would be nice for perf in some cases I would guess

0:29 mebaran151: yeah

0:29 I'll think about these sorts of things

0:29 somnium: Ill watch for it

0:30 need to sleep for now

0:30 cheers

0:31 mebaran151: thanks for your input

1:04 tomoj: hmm

1:04 I forsee increased pressure to make clojure happy with dalvik

1:09 chouser: I thought it worked (a bit) already?

1:31 defn: hmm wtf error: java.lang.NoClassDefFoundError: javax/servlet/ServletOutputStream (core.clj:1)

1:31 this was just working on OSX at home, but not here at work

1:32 nvm figured it out

1:59 mebaran151: is there any quick way to turn an inputstream into a ChannelBuffer

2:00 sorry I mean ByteBuffer

2:00 I'd like to read an InputStream into a bytebuffer

2:09 Puzzler: Anyone know whether Java 1.7 will introduce the kinds of numeric features that will allow Rich to speed up Clojure's number handling?

3:41 hiredman: lisppaste8: url

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

3:42 praptak: Is let* different than let?

3:43 lisppaste8: hiredman pasted "inputstream -> bytebuffer" at http://paste.lisp.org/display/93138

3:45 hiredman: praptak: let is actually a macro implemented using let*

3:47 praptak: hm

3:47 Ok, I'll check the source

3:47 hiredman: ,(macroexpand '(let [[a b] [1 2]] [a b]))

3:47 clojurebot: (let* [vec__6245 [1 2] a (clojure.core/nth vec__6245 0 nil) b (clojure.core/nth vec__6245 1 nil)] [a b])

3:47 Chousuke: ~def let

3:47 praptak: Thanks

3:47 hiredman: ,(let [[a b] [1 2]] [a b])

3:47 clojurebot: [1 2]

3:48 Chousuke: the destructure function is quite a monster :P

3:49 hiredman: I've never looked at it, but it would have to be

3:50 kind of scary, it lurks beneath the most innocuous looking code

3:50 Chousuke: heh

3:50 but it works.

3:50 so you can forget that it exists :)

3:51 hiredman: until you get some head holding

3:51 Chousuke: that shouldn't be such of a problem anymore I think

3:52 hiredman: *shurg*

3:52 new isn't even master yet

3:52 Chousuke: since Rich introduced the early locals clearing

3:53 praptak: Ok, so let is basically let* with added support for destructuring assignments?

3:54 ,(let* [[a b] [1 2]] (+ a b))

3:55 clojurebot: java.lang.IllegalArgumentException: Bad binding form, expected symbol, got: [a b]

3:55 praptak: ,(let [[a b] [1 2]] (+ a b))

3:55 clojurebot: 3

3:57 praptak: err, assignments->bindings

4:04 Chousuke: ,(#'clojure.core/destructure '[[a b] [c d]])

4:04 clojurebot: [vec__6261 [c d] a (clojure.core/nth vec__6261 0 nil) b (clojure.core/nth vec__6261 1 nil)]

4:04 Chousuke: basically let just feeds that to let*

4:19 defn: ,(doc let)

4:19 clojurebot: "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

4:26 praptak: ,(doc let*)

4:26 clojurebot: It's greek to me.

4:29 Chousuke: it's a secret :)

4:30 hiredman: let* has no var to hang a docstring on

4:34 Chousuke: you could easily define one, though

4:35 the special form takes precedence though, but it might work for adding a docstring

4:36 hiredman: or you could add some special mechanism to doc, which I think there already is

4:37 of course clojurebot has its own 'doc' so...

4:51 LauJensen: ~source let*

4:51 clojurebot: I don't understand.

4:56 hiredman: let* is in java somewhere

4:57 LauJensen: Strange, I felt I had a memory of seeing it in core once

4:58 hiredman: it's used in core, sure

4:59 LauJensen: I meant the definition

5:01 hiredman: well, it's not, as a special form it must be implemented in the implementation language

5:06 AWizzArd: though after bootstrapping it can be written in Clojure too :)

5:07 hiredman: nope

5:07 Chousuke: why not? :P

5:07 AWizzArd: Why not?

5:07 hiredman: it's almost by definition that special forms are written in the implementation language

5:07 Chousuke: the plan is to do that.

5:07 AWizzArd: Yes, but the implementation language for Clojure will be Clojure.

5:07 Chousuke: since the implementation language will be Clojure :D

5:08 hiredman: sure, but it will be sort of Clojure and Clojure'

5:08 AWizzArd: in some sense yes

5:08 hiredman: the let* in Clojure' will be written in Clojure

5:10 the distinction between implemented lisp and implementing lisp is fairly common

5:10 sicp does it, lisp in small pieces does it, etc

5:11 Chousuke: Clojure might just do it so that any new versions of Clojure are compiled with an earlier version, though.

5:11 hiredman: the main reason I said "nope" was most likely over a different understanding of "bootstrapping"

5:12 Chousuke: sure, the ealier version of Clojure being Clojure, and the version being built would be Clojure'

5:12 Chousuke: bootstrapping is not easy though. I tore many hairs trying to make my reader work :P

5:12 hiredman: I took "after bootstrapping" to mean after the bootstrapping section of core.clj

5:14 * hiredman is still kind of annoyed at the complete lack of interest in his port of LispReader

5:15 Chousuke: heh

5:15 hiredman: I don't think my post to the dev group about it got a single reply

5:15 Chousuke: I should work on mine, too.

5:15 hiredman: *shrug*

5:15 Chousuke: it's a bit hackish right now

5:16 hiredman: yours would undoubtly be more interesting, as it's not just a port

5:17 Chousuke: I'm not sure how to incorporate all the features I want while keeping the definition of reader macros natural AND the design (somewhat) functional. hmmh.

5:17 Should do some reading about Lisp readers I guess.

5:20 hiredman: I dunno, the literature doesn't seem to overflow with reader examples

5:20 which is odd given how much work is sort of off loaded on to them in a modern lisp implementation

5:21 Chousuke: I could go read some scheme implementation for inspiration.

5:22 hiredman: it annoys be sometimes that I can't have a name X'

5:22 Chousuke: heh

5:22 haskellish :P

5:22 hiredman: I need some other way to indicate the successor to X

5:22 Chousuke: I guess that's what the * is for.

5:22 hiredman: :/

5:23 should find some unicode glyph

5:24 Chousuke: ’ <-here's a full width apostrophe

5:24 at least I think that's supposed to be one

5:24 hiredman: ,x’

5:24 clojurebot: java.lang.Exception: Unable to resolve symbol: x’ in this context

5:24 hiredman: ,(let [x 1 x’(inc x)] x’)

5:24 clojurebot: 2

5:24 hiredman: how evil is that

5:25 Chousuke: very

5:25 I need my japanese input method to even type that character.

5:25 ,(let [x 1 x’ (inc x)] x’) this is eviler though

5:25 clojurebot: 2

5:26 hiredman: I wonder if there is some key combo I can do for that

5:27 Chousuke: well, in emacs you could just bind a key to the needed elisp function to produce whatever you want :P

5:38 hiredman: xev-1.0.3.tbz

5:38 er

5:39 gah, I can use the compose key to insert it everywhere except gnome-terminal apparently

6:16 ordnungswidrig: hum, since when exists defprotocol/deftype? in 1.1.0-alpha I cannot find it

6:17 hiredman: only in the 'new' branch

6:19 ordnungswidrig: not in 1.1?

6:20 hiredman: nope

6:20 ordnungswidrig: I see.

6:21 Is it available on clojars?

6:22 hiredman: no idea

6:42 AWizzArd: clojurebot: max people

6:42 clojurebot: max people is 240

7:33 RCampbell: when you type a map literal into the REPL, like {:a 1}, Clojure automatically selects the concrete map impl to use, for example array-map for small maps or hash-map for larger maps. What happens when you do (def x (array-map {a: 1})) but then you add a couple million key/val pairs? will it remain an array-map, or will Clojure somehow convert it automatically to a hash-map?

7:37 AWizzArd: It will become a hashmap

7:38 clojure.lang.PersistentHashMap

7:50 RCampbell: So to be clear, Clojure will monitor a map and when it grows beyond a certain level it will switch its type? that seems wild

7:51 even when it's explicitly instantiated using (array-map

7:56 AWizzArd: RCampbell: yes, the functions that can grow (assoc, conj) a map will check if there are, say, more than 8 elements in the map. If so, it will be a hashmap.

7:56 But dissoc will not do such a check. The reason is that a "big arraymap" performs worse than hashmaps. But small hashmaps can perform a little bit worse than arraymaps.

7:57 RCampbell: AWizzArd: thank you for the explanation. That's pretty cool functionality

7:58 AWizzArd: The developer will always work with the concept of a map, and Clojure will try to ensure under the hood that a useful implementation will be used.

7:59 RCampbell: AWizzArd: then why even have (array-map) and (hash-map) functions? when would you select one of the other? Clojure controls the underlying impl, so it seems a bit misleading

8:00 AWizzArd: ,(class (array-map))

8:00 clojurebot: clojure.lang.PersistentArrayMap

8:00 AWizzArd: ,(class (hash-map))

8:00 clojurebot: clojure.lang.PersistentArrayMap

8:01 AWizzArd: If you understand your data and problem well you may want to have a bigger array-map.

8:02 RCampbell: yeah, but you're saying if I do (array-map ; some massive data here) it will store it as a hash map

8:03 AWizzArd: also: when you type {:a 1, :b 2} into your repl, then Clojure would like to construct a array-map for you. So it is nice to have a function available for that purpose.

8:03 RCampbell: what I mean is, if Clojure is selecting the impl on its own based on the size, why both with array-map and hash-map constructors, and why not just make one (persistant-map)

8:03 AWizzArd: Calling array-map results in a clojure.lang.PersistentArrayMap

8:03 ,(class (apply array-map (range 2000)))

8:03 clojurebot: clojure.lang.PersistentArrayMap

8:04 RCampbell: yeah, but you just showed (hash-map) creates an array map too

8:04 AWizzArd: ,(class (assoc (apply array-map (range 2000)) :a :b))

8:04 clojurebot: clojure.lang.PersistentHashMap

8:04 AWizzArd: RCampbell: because you sometimes know more than the compiler does

8:05 you can safely forget about array-map and just use hash-map to construct your maps

8:05 RCampbell: (class (hash-map)) -> clojure.lang.PersistentArrayMap is saying the opposite: that the compiler knows more than me. It's a lie, isn't it?

8:05 i understand that part - that I can ignore it - but then I don't see why the two constructors exist.

8:05 AWizzArd: hash-map does not guarantee that the returned object will be a PersistentHashMap

8:06 RCampbell: then why itsn't there just (persistent-map)

8:06 since in the end, the compiler decides

8:06 AWizzArd: hash-map may call array-map if only a few elements are added

8:06 RCampbell: the compiler will not decide when you call array-map

8:06 RCampbell: aha

8:06 AWizzArd: see my example above, where I put 2k elements into an ArrayMap

8:06 RCampbell: yes, i see that

8:07 AWizzArd: ,(class clojure.lang.PersistentHashMap/EMPTY

8:07 clojurebot: EOF while reading

8:08 AWizzArd: ,(class clojure.lang.PersistentHashMap/EMPTY)

8:08 clojurebot: clojure.lang.PersistentHashMap

8:08 RCampbell: okay so array-map always returns an array-map, but later additions via assoc, conj, can convert it to a hash-map

8:08 AWizzArd: yes

8:08 RCampbell: hash-map will return an array-map for small stuff or a hash-map for big stuff

8:08 AWizzArd: yes, where "big" is around 8-10 elements

8:08 RCampbell: oh that's not so big. interesting

8:08 okay

8:22 chouser: ,(class (hash-map 1 2 3 4))

8:22 clojurebot: clojure.lang.PersistentHashMap

8:22 chouser: doesn't look like an array-map to me

8:23 I think the important thing is to not rely on the concrete type.

8:33 _fogus_: ,(class {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16})

8:33 clojurebot: clojure.lang.PersistentArrayMap

8:33 _fogus_: ,(class {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18})

8:33 clojurebot: clojure.lang.PersistentHashMap

8:33 _fogus_: But, what chouser dsaid

8:33 chouser: right. for literals.

8:34 there's no promise about the concrete type of literals or of what's returned by assoc, dissoc, etc.

8:34 _fogus_: nor should there be... but people get tripped up on that

8:34 chouser: I do think that when you use a named factory fn like hash-map or array-map, you can rely on getting an object of that type.

8:35 _fogus_: hey good morning. :-)

8:35 _fogus_: chouser: Good morning sir!

8:35 chouser: if we keep this up, they could rename this channel to #joyofclojure

8:36 _fogus_: I think there was a time when I liked snow... but I've sent lost that childhood joy. :(

8:36 That might not be a bad idea anyway. ;)

8:37 RCampbell: chouser: that's what I was talking about. To me it seems a bit misleading

8:37 * chouser fears his attempts at marketing are neither subtle nor effective.

8:37 chouser: RCampbell: what's misleading?

8:37 RCampbell: chouser: when you say (hash-map) you expect a hashmap, no?

8:37 ,(class (hash-map))

8:37 clojurebot: clojure.lang.PersistentArrayMap

8:38 chouser: ah

8:38 well

8:38 RCampbell: I agree that you shouldn't depend on the concrete types, and I love that they're managed for me, but if that's the case I just think (persistant-map) would have been better than these two

8:39 chouser: heh, I hadn't seen that. The thing is, what's the difference between an empty array-map and an empty hash-map?

8:39 RCampbell: chouser: true enough

8:39 chouser: when you actually give it some parameters, each function will return the specific type you request.

8:39 RCampbell: but then my question was, why do we have these two constructors?

8:40 chouser: ,(class (apply array-map (range 2e5)))

8:40 clojurebot: clojure.lang.PersistentArrayMap

8:40 RCampbell: true, but then you risk losing that type whenever you pass it to a assoc, conj, etc

8:40 chouser: so there's an array-map with a hunderd thousand key/value pairs, guaranteed to keep the order I gave them.

8:40 right, yes you do.

8:40 _fogus_: RCampbell: Why does it matter which map class you receive after some op(s)?

8:41 RCampbell: i suppose it doesn't, although it would depend on how you access your map, no?

8:42 I'm sure certain algos would operate faster on one type versus another based on how the data is accessed

8:42 i suppose you could always cast from one to another though

8:44 chouser: RCampbell: I understand what you're saying. I think the most dangerous detail there is that key-matching semantics are slightly different between array-map and hash-map.

8:45 RCampbell: chouser: could you come up with a nice example? I'm going to add it to my stackoverflow answer concerning commons mistakes beginners make in clojure

8:45 * _fogus_ waits anxiously for someone to mention Big-O

8:46 chouser: RCampbell: hm... my attempts at an example are failing. perhaps that's been fixed.

8:47 _fogus_: array-maps are order-n-ouch

8:52 RCampbell: ,(array-map (range 100))

8:52 clojurebot: 1

8:52 RCampbell: ,(hash-map (range 100))

8:52 clojurebot: java.lang.IllegalArgumentException: No value supplied for key: clojure.lang.LazySeq@5c8e6fb3

8:52 RCampbell: why?

8:53 array map uses the index as the key by default?

8:53 _fogus_: RCampbell: Thanks for filling out some of that information on SO... that thread is getting some nice answers

8:54 RCampbell: _fogus_: np. Mostly I'm remembering all the WTF moments I've had along the way

8:54 AWizzArd: Does a lookup in an PAM traverse the full underlying tree until it finds the key?

8:55 RCampbell: I'm trying to compile all the bits from the three books, mailing list, stackoverflow, and this irc channel that help me get past it

8:55 _fogus_: RCampbell: Eventually it would be nice to gather those WTF moments and put them somewhere on the Clojure site... but that's probably just a dream

8:56 RCampbell: fogus: it should be easy enough; the content on StackOverflow is GLP I believe, and Jeff does a content dump every so often

8:57 AWizzArd: that's a good question

9:03 chouser: AWizzArd: there's no underlying tree. Underlying a array-map is an array. And yes, it's walked linearly until a match is found.

9:06 * _fogus_ Is currently reading http://research.sun.com/self/papers/organizing-programs.html

9:06 chouser: RCampbell: array-map and hash-map fns both expect an even number args for the key/value pairs

9:07 RCampbell: so (hash-map x) is an error regardless of the value of x. But array-map doesn't do many extra consistency checks, so you managed to get away with something thre.

9:07 there

9:08 RCampbell: chouser: okay that makes sense

9:08 although (range 100) is even

9:08 ,(count (range 100))

9:08 clojurebot: 100

9:09 chouser: it's a single object

9:09 if you want the contents of the range to be the contents of the map, you have to use 'apply'

9:10 ,(apply hash-map (range 100))

9:10 clojurebot: {0 1, 32 33, 64 65, 96 97, 2 3, 34 35, 66 67, 98 99, 4 5, 36 37, 68 69, 6 7, 38 39, 70 71, 8 9, 40 41, 72 73, 10 11, 42 43, 74 75, 12 13, 44 45, 76 77, 14 15, 46 47, 78 79, 16 17, 48 49, 80 81, 18 19, 50 51, 82 83, 20 21, 52 53, 84 85, 22 23, 54 55, 86 87, 24 25, 56 57, 88 89, 26 27, 58 59, 90 91, 28 29, 60 61, 92 93, 30 31, 62 63, 94 95}

9:11 chouser: I think that once upon a time there were objects that were .equal but their .hashCode was different. Has that been fixed now?

9:12 RCampbell: i dunno, in Java you define your own impls (unlike in clojure) so developers can still screw up

9:13 chouser: i don't know any history of that in clojure

9:14 chouser: well, if that's been fixed then perhaps array-map and hash-map now have sufficiently similar matching semantics.

9:36 AWizzArd: chouser: okay, this is what I guessed from the names

9:44 the-kenny: liebke: Which "incanter" should I use in leiningen?

9:46 liebke: the-kenny: the latest version isn't up on Clojars yet, so use 1.0-master-SNAPSHOT for now

9:47 the-kenny: liebke: "incanter-full" or "incanter"

9:47 If I use incanter, requiring throws an exception :(

9:47 liebke: eventually incanter full, but that didn't get uploaded correctly (apparently), so use incanter

9:48 the-kenny: "No value supplied for key: true"

9:48 liebke: I've been having problems with Clojars lately. Unfortunately, I'd recommend using the github repository

9:48 hmmm

9:48 try the 1.0-SNAPSHOT version then

9:54 rrc7cz: do you guys use letfn a lot? it's generally agreed that keeping declarations close to where you use them is a good thing, as is lowering the scope of something when it's possible

9:54 but I don't see it used a lot

9:56 chouser: I more often use let when defining local functions than letfn.

9:57 rrc7cz: why?

9:57 chouser: with let I can mix fn and other locals

9:57 rrc7cz: okay that makes sense

9:57 chouser: I use letfn when I need mutual recursion and/or have only fns to define

10:15 LauJensen: What the general use-case for mutual recursion ?

10:16 Chousuke: state machines?

10:18 arohner: cause it's cool?

10:24 rrc7cz: fogus: I totally didn't make the connection between your stackoverflow question and my answer

10:24 fogus: I just noticed your name now. Thats pretty funny. I guess it's a small community

10:27 _fogus_: rrc7cz: A small, but growing community. :-)

10:31 rrc7cz: fogus: I like your pre/post article; I had a question about doing design by contract in clojure and I was psyched for this functionality

10:33 Chousuke: pre and post might be a bit problematic with libraries though. they are only checked if *assert* is bound, and the decision is made during compile time

10:33 so if you AOT-compile your library for distribution, you need to decide for the users whether to enforce asserts or not :/

10:34 rrc7cz: Chousuke: so why was assert used as the underlying mechanism? why not switch it to an if or something?

10:35 Chousuke: rrc7cz: I guess it was intended that pre- and postconditions are only checked when debugging, and compiled away for production code.

10:35 rrc7cz: oh

10:35 chouser: I don't like AOT-compiling anyway.

10:36 if you don't AOT-compile, your users can maintain control with *assert*

10:37 _fogus_: rrc7cz: Actually, Devlin's follow-up to my :pre/:post uhhhh post, is much better

10:37 Chousuke: I guess that's the best choice for libraries

10:40 rrc7cz: I was looking for a way of translating some of the AssertionErrors into IllegalArgumentException which makes a lot more sense when validating arguments, but I suppose if :pre/:post were meant for debugging and not prod runtime, there isn't much point

10:42 Chousuke: you can always make an assert-args macro. there actually is one in core, but it's private ;/

10:45 rrc7cz: Chousuke: it seems odd to make something that useful private

10:48 Chousuke: rrc7cz: well, it's just a trivial helper macro in core. I don't think any significant design effort was put into it.

10:51 esbena: I want to apply a side-effect function to every element of a seq, what is the name of that function (not 'map') ??

10:51 chouser: esbena: doseq or dorun

10:52 Chousuke: doseq is a macro, though, and dorun just forces a seq. :)

10:52 but those will do what you want.

10:52 chouser: Chousuke: ok then, what's you're answer? :-P

10:53 * Chousuke is just feeling unnecessarily pedantic

10:53 Chousuke: but the answer of course is (comp dorun map)

10:53 ordnungswidrig: Is there a way to quickly fail in clojure. Like throw new Exception("message")

10:53 chouser: Chousuke: :-)

10:53 Chousuke: ordnungswidrig: (throw (Exception. "message"))

10:53 ordnungswidrig: Chousuke: *g* something more idiomatic?

10:54 Chousuke: return nil?

10:54 an exception is the only way to have a non-tail exit though.

10:54 ordnungswidrig: (defn fail [] (throw Exception. "message")

10:55 Chousuke: some parens missing, but yeah.

10:55 you could also use error-kit from contrib if you want fancy errors :P

11:12 defn: I have a question about paths

11:13 (System/getProperty "user.dir")

11:13 mebaran151: paths?

11:13 defn: so let's say i have a .clj file that's nested in a lein project

11:14 If (System/getProperty "user.dir") is called from that file, i assume it will get the path that the file is living in, yes?

11:17 mebaran151: I'm actually not quite sure

11:17 user.dir is tricky

11:18 sometimes it gets where the jvm is stored

11:18 I find it unreliable

11:20 chouser: I think user.dir is usually the cwd when the jvm was started. And you can't change it.

11:22 defn: chouser: that's correct, just tested it

11:22 it's where you run the jar from

11:22 mebaran151: what else would you use?

11:23 I don't want to force people to use absolute paths and edit a config file just to run this

11:23 mebaran151: I tend to rely on user.home very heavily

11:23 and I copy lots of things there

11:24 defn: hmmmm, i dont like mucking with a user's home dir if it's not necessary

11:24 and in this case im sure it's not

11:24 it's not like im writing a utility or an application they will want to store a local config file for

11:24 it's something which needs to just be contained by itself

11:26 me needs a java version of pygments

11:27 mebaran151: oh then what do you need user.dir for?

11:27 defn: to get the project root

11:27 which is where the jar is built

11:28 mebaran151: are you on unix?

11:28 defn: yes

11:28 but not everyone will be

11:28 chouser: surely you can be in some other directory when you launch the thing, which might mess up your user.dir

11:28 defn: chouser: yeah, but im okay with that as I suspect most will run it from it's build directory

11:28 if they dont, well, too bad for them

11:29 mebaran151: hmmm I'm trying to consider if some env variable will help you

11:29 defn: in unix it might, but idk, i think this is fine for now

11:29 it's better than the absolute path

11:30 mebaran151: you probably could wrap it in a small shell script

11:30 defn: someone just msg'd me on github asking why they couldnt run it, and it's because of the absolute path

11:30 mebaran151: that would either pass the cwd as an argument to your proram

11:30 defn: i told them to edit it, but it seems like a stupid step to force people into

11:31 anyway, now im on the hunt for a way to do markdown + code highlighting

11:31 specifically clojure code syntax highlighting

11:32 pygments + markdown.py and the codehilite extension which is bundled with it do a wonderful job, but that means people have to get friggen python deps for a clojure project, which is lame as hell

11:32 hiredman: defn: I think user.dir will be fine

11:32 defn: hiredman: i agree

11:33 hiredman: any ideas for clojure syntax highlighting which outputs as HTML?

11:33 something java?

11:33 hiredman: none

11:33 defn: bummer

11:34 hiredman: can't you just use some kind of javascript deal?

11:34 isn't that the latest and greatest in web syntax hilighting?

11:34 LauJensen: defn: htmlize :)

11:35 defn: LauJensen: in clojure?

11:35 LauJensen: oh, no thats Emacs

11:35 defn: yessir :)

11:35 hiredman: nice! i think you pointed me in the right direction with your comment: http://alexgorbatchev.com/wiki/SyntaxHighlighter

11:37 LauJensen: defn: I think a cocktail between compojure's html function and then just doing some kind of .replaceAll with the functions in core would get you quite far

11:38 defn: LauJensen: could you be more specific about what you're replacing?

11:38 LauJensen: as in writing my own markdown processor?

11:38 LauJensen: With the above approach, you'd be highlighting functions and macros

11:39 defn you're writing a Clojure program which reads clojure code and emits highlighted html right ?

11:40 defn: LauJensen: close -- it reads markdown which contains code blocks, which need to be highlighted as clojure

11:40 LauJensen: Yea, almost the same

11:40 Gotta boot

11:41 defn: markdown.py does a slick thing wherein it let's you specify at the top of a code block: :::clojure\n (defn omg [arg1 arg2]\n (+ arg1 arg2))

11:42 hiredman: you might even be able to use scriptjure to write custom js highlighting stuff in clojure and translate it to javascript

11:42 Licenser: aloa

11:42 defn: hiredman: not a bad idea at all

11:42 mebaran151: that would be way meta

11:42 hiredman: so I would forget about generating hilighted html

11:42 mebaran151: then you could highlight the scriptjure source in js

11:44 defn: http://attacklab.net/showdown/

11:44 maybe?

11:47 hiredman: the markdown renders to html right?

11:48 so you just have the javascript highlight the code blocks in the html

11:48 defn: how do i know im highlighting a code block though?

11:49 hiredman: magic

11:49 by magic I mean <code></code>

11:49 or whatever markdown dumps the code into

11:49 defn: is that what markdown renders?

11:50 hiredman: I don't know, you should check

11:50 defn: lol

11:51 djork: wow, Enlive looks very nice

11:52 I assume cgrand-rec in here is the dev?

11:55 chouser: I think -rec is his bot.

12:35 nuttycom1: Does anyone have a good reference for how to embed a Clojure interpreter (or compiler that can be dynamically invoked and return something callable) in a Scala (or Java) app?

12:36 kotarak: nuttycom1: import clojure.lang.RT; import clojure.lang.Var; Var pr = RT.var("clojure.core", "println"); pr.invoke("Hello, World!");

12:38 nuttycom1: kotarak: thanks

12:47 Hmmm... are there any javadocs for jvm.clojure.lang.* or do folks just consult the sources on github?

12:47 chouser: there are no official docs for the .java code. So yes, the sources.

12:48 they're all going away eventually anyway. ;-)

12:48 nuttycom1: ah, I think I heard about that - what's the timeframe on self-hosting?

12:49 Chousuke: will deftype/reify be the last piece needed before the actual compiler work can begin? :/

12:49 nuttycom1: moreover, what can I expect with respect to my goal of having an embedded interpreter (or runtime compiler) for use from within another app?

12:49 Chousuke: or is there still something

12:50 nuttycom1: I've been using Groovy for this purpose up until now, but clojure is much more appealing.

12:50 Chousuke: nuttycom1: but the compiler *is* a runtime one? what do you mean :/

12:50 chouser: clojure's got a runtime compiler built right in. read-string, eval.

12:50 Chousuke: there is no interpreter though :)

12:51 chouser: Chousuke: I think a way of doing volatile fields is still missing.

12:51 defn: Chousuke: do you have the ability to add members to the assembla project

12:51 Chousuke: I don't think so. hmm.

12:51 defn: i gave rich my signed agreement and am listed on the contributers page

12:51 err i meant chouser

12:51 but my account on assembla is still Watcher

12:52 Chousuke: did you post to the dev group asking for a bump?

12:52 defn: I didn't -- I thought I'd just need to get the agreement signed and he'd handle getting me added

12:52 but I can do that

12:52 nuttycom1: Chousuke: basically, I've got an app written in Scala running on Glassfish. I need to provide a small scripting language for part of that app. I can go the parser-combinator route in Scala, but that seems like a bit heavyweight for my situation - so instead I want to use clojure, where the resulting artifact can be executed in the current classloader (or a child, of course)

12:53 chouser: defn: I think you need to ask. I think only rhickey can do it.

12:53 defn: chouser: Chousuke: thanks

12:54 hiredman: I don't know much about classloaders, but my impression is clojure still has some modularity issues on that front

12:54 (no direct experience, just sort of half rememebered stuff on the internet)

12:56 chouser: nuttycom1: so you may have to play with the classloaders a bit, but the raw materials should all be there. 'read' to convert text to a tree of clojure objects, 'eval' to run it.

13:37 mebaran151: hey somnium, so I've got some basic proxy netty stuff working if you want to play with it

13:38 somnium: mebaran151: cool, sure. on github?

13:38 mebaran151: not yet

13:38 it's just a gist so far

13:38 somnium: url?

13:38 mebaran151: turns out the annotations in netty are simply documentation

13:39 http://gist.github.com/272271

13:39 it basically works the way I described

13:40 takes the output of a function and writes it to the buffer, either an array of ints or a good ol' fashion bytestring

13:41 I keep around the context vars in bindings in case you wanted to do something fancy with them

13:42 somnium: mebaran151: should I use 3.15?

13:42 mebaran151: I was going against 3.2 alpha

13:42 but I don't do anything particularly adventurous

13:43 somnium: ok

13:45 mebaran151: I was looking for good protobuffers in clojure, but the design doesn't seem to fit the clojure mentality well

13:47 it works as a basic telnet echo, but I haven't done much more with it yet

13:48 the-kenny: mebaran151: Maybe write a nice wrapper about the java version of the protobufs?

13:48 mebaran151: but protobufs is so classy

13:48 like heavily classy

13:48 it's probably a bad binary fit for clojure at the moment

13:49 chouser: google protobufs, or something else?

13:49 mebaran151: google protobufs

13:49 chouser: I use them a lot at work, from Clojure and C++

13:49 the-kenny: In fact, I have never really needed a binary protocol. I always use simple json

13:50 chouser: so I've got fns to convert back and forth between clojure nested maps and protobufs

13:50 mebaran151: there's a certain mechanical elegance to a good binary protocol

13:51 chouser: I need them to iterop with other services. The choice to use protobufs was not mine. :-)

13:54 mebaran151: but if clojure itself were to have a nice easy binary protocol that handled vectors, maps, strings, and numbers, I think that might be useful, actually even outside the clojure community

13:54 I wonder if a protocol with that much flexibility though would be anymore efficient than regular ol' JSON

14:00 somnium: mebaran151: the pet project I want to use netty for is a BSON client (http://www.mongodb.org/display/DOCS/BSON), which seems to be an attempt at being more efficient than regular 'ol JSON (or maybe just a mild case of NIHS, cant be sure)

14:01 mebaran151: oh I was looking into BSON as well

14:01 it seemed like it would be cool to switch between JSON and BSON

14:17 somnium: hmm, how do you add a repository in a project.clj? (cant seem to find an example and Im maven challenged :/)

14:19 knuckolls: i'm just learning clojure and i'm having a real hard time conceptualizing this. I have a file with records separated into sets of three lines, then an empty line. I want to load these into memory but I can't figure out how to pull from the seq 4 lines at a time and store them in a map. any pointers to the functions i should be using?

14:20 chouser: ,(parition 4 (range 12))

14:20 clojurebot: java.lang.Exception: Unable to resolve symbol: parition in this context

14:20 chouser: ,(partition 4 (range 12))

14:20 clojurebot: ((0 1 2 3) (4 5 6 7) (8 9 10 11))

14:20 chouser: that might help

14:20 the-kenny: knuckolls: (partition 4) will partition a seq in seqs of 4 items

14:20 knuckolls: yes. that helps quite a bit. this is the first i've seen partition

14:20 wonderful.

14:21 yep that does the trick. thanks.

14:25 robwolfe: somnium: IIRC it's something like this: ":repositories [["rep name" "url"]]"

14:25 somnium: robwolfe: ah thanks

14:27 hiredman: somnium: I am pretty sure it's a map

14:28 {"google" "url"}

14:28 somnium: hiredman: I found a gist with a map, and that worked, then just tried the vector, and that seemed to work too (though maybe it already added the repo?)

14:28 hiredman: but it must get walked via the seq functions which sees it as the same thing as [["name" "url"]]

14:29 ,(seq {"google" "url"})

14:29 clojurebot: (["google" "url"])

14:29 robwolfe: hiredman: there is "concat" and it works for vector and map

14:31 hiredman: robwolfe: I am just hypothesizing on why a map and a nest set of vectors both work for :repos

14:31 robwolfe: hiredman: in Leingen there is used "concat" for joining "default repos" with defined

14:32 that's why it works I guess

14:32 somnium: presumably a map would work for :dependencies too? ah, maybe not?

14:32 *shrug* whatever works is fine with me

14:32 robwolfe: somnium: we can try ;)

14:34 hiredman: http://gist.github.com/272330 <-- makes me sad

14:40 arj: I have a very imperative part of my program. More or less a state machine. Any hints as to code this in clojure?

14:45 stuartsierra: arj: loop/recur

14:48 arj: hmm interesting

14:48 I'll have a look

14:48 thanks

14:48 _fogus_: arj: mutual recursion might map well also, but it takes some practice to get right

15:01 ynniv: is there an elegant way to break a hash map apart and reconstruct it?

15:01 kotarak: ynniv: breaking apart in which way?

15:01 ynniv: i'm using mongo, and my DBObject acts like a hash map, but isn't close enough to work with some of the api

15:02 i'd like to convert it to a real hash-map elegantly

15:02 kotarak: ynniv: does it support seq? (into {} your-object)

15:02 ynniv: hah! perfect :)

15:03 i haven't used "into" yet

15:05 i probably write the worst clojure code, but even that works out better for me than great code in other languages

15:09 {newbie}: ,(into {} [:foo "bar"])

15:09 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword

15:10 somnium: ynniv: if you don't mind a shameless suggestion, congomongo on github might make the mongo-java-driver somewhat more pleasant to work with

15:10 ynniv: ,(into {} [[:foo "bar"]])

15:10 clojurebot: {:foo "bar"}

15:11 {newbie}: :\ okay :D

15:11 ynniv: somnium: I considered it, but I'm doing so little interaction with mongo that I'm not ready to switch libs yet

15:11 i have a couple of .find's :)

15:16 somnium: ynniv: just a shameless suggestion :)

15:16 ynniv: I have considered it, and will keep it in mind ;)

15:17 i'm working in a mongo - clojure - REST - SproutCore stack, and i've been spending all my recent time on the right side of that

15:17 but i'll revisit the left sometime soon

15:20 somnium: ynniv: cool, Ive had my eye on Sproutcore, but the docs are worse that dojo's (which Im reasonably familiar with)

15:20 hiredman: http://andialbrecht.wordpress.com/2009/05/09/when-merging-fails/ <-- hah!

15:22 the-kenny: hiredman: I want this for git!

15:24 robwolfe: hiredman: I want it for missing jars on classpath ;)

15:24 AlexS_: I seem to be getting an java.util.concurrent.RejectedExecutionException when trying to use a very simple agent in the slime/swank repl. Everything works fine from a non-swank repl. Anyone else encountered this? Or be willing to try an reproduce?

15:26 hiredman: AlexS_: most likely means you shutdown the agent threadpools

15:27 AlexS_: hiredman: This was a brand new session started with the lein swank command.

15:35 ynniv: somnium: SC is a tough framework to get involved with. I have the benefit of a 9 month head start learning, but even so, a lot has changed in that time.

15:44 I314159: hi

15:44 I have a struct which looks like this: (defstruct book :title :author)

15:44 I also have a list which looks like this: (let mybook [("my title" "my author")])

15:44 I want to turn this into a book struct, but doing this: (struct book mybook) gets this:

15:44 (:title ("my title" "my author") :author nil)

15:44 any tips on on what I'm doing wrong?

15:45 the-kenny: (apply struct book (first mybook))

15:45 struct doesn't exspect a list but single arguments

15:45 I314159: ahh -- thanks

15:46 Chousuke: also you would need to quote the lists like that :P

15:46 more idiomatic in clojure is to use a vector

15:49 dataangel: Is there a paper or site somewhere that describes how clojure implements persistent data structures? I know from Hickey's presentations that there's some hashing going on, that somehow affects indexing into some multilayer tree, and that CAS lets you quickly swap out elements, but I haven't seen a real description of the algorithm anywhere. I'm not a Java dev so the source code has a high barrier to entry for me ;p

15:51 chouser: dataangel: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

15:52 dataangel: but don't just into that until you're ready -- it'll just destory the magic for you. :-)

15:52 don't jump

16:32 leafw: any fn to flatten a list of lists ?

16:32 I am sure there is one ...

16:32 chouser: one level, or recursive?

16:32 kotarak: leafw: flatten?

16:32 leafw: one level

16:32 chouser: (apply concat x)

16:33 leafw: chouser: although recursive would be nice too.

16:33 kotarak: c.c.seq-utils/flatten

16:33 chouser: ,(apply concat [[1 2 3] [4 5 6] [7] [8 9]])

16:33 clojurebot: (1 2 3 4 5 6 7 8 9)

16:33 leafw: clojure.contrib, that unknown treasure pit

16:33 thanks

16:33 chouser: heh

16:33 "treasure pit

16:33 kotarak: I hope my memory doesn't play bad tricks on me, though...

16:34 chouser: "treasure pit" seems more accurate that "standard lib"

16:34 than

16:34 treasures, sure. Also, a pit.

16:34 ohpauleez: haha

16:35 leafw: it's just too hard to ever get a general idea of what is where and how did it change recently

16:35 ohpauleez: That's why I hang out in #clojure

16:36 Chousuke: We have contrib excavators here.

16:36 Some people also occasionally go ahead and deepen the pit, hiding more treasures.

16:37 ohpauleez: it's all in the name of bringing game theory to clojure development

16:37 :)

16:37 leafw: xD

16:38 technomancy: now that clojars exists it might be worth thinking about spinning libraries back out of contrib if they aren't intended for future inclusion in core

16:38 Chousuke: All is okay as long as complexity does not approach that of Go

16:38 technomancy: at least, that's what I would be considering if I had authored a library that had been included in contrib

16:38 hiredman: technomancy: I was just thinkging that

16:38 technomancy: clojure.contrib.logging would benefit from that IMHO

16:38 kotarak: Ah! Go. :D Hmmm...

16:39 Whatever happens with contrib, I'd like to see a more modular build.

16:40 3.5Megs for c.c.def.... bleh.

16:40 technomancy: hiredman: we analyzed our codebase at work, and 60% of contrib usage was IO (duck-streams/java-utils) and 25% was logging.

16:41 hiredman: is clojure.io still in motion?

16:41 technomancy: then a handful of shell-out and str/seq-utils invocations

16:42 hiredman: stuart S seemed to think rich had some plans up his sleeve

16:42 hiredman: *shrug*

16:42 technomancy: I was waiting to hear more about that, but it sounds like that's not going to happen

16:43 hiredman: there is a lot of chum in the water

16:43 chouser: one of the values of contrib is the low barrier for bug fixes from people other than the original author

16:44 technomancy: chouser: maybe, but stuff outside contrib doesn't have to go through the ticket+patch dance

16:44 authors can pull directly from others' git repos, which is much more convenient

16:44 chouser: neither does stuff inside contrib when the patch is written by a committer.

16:45 technomancy: it's true that having multiple committers solves some problems

16:45 chouser: do I have to clone someone else's repo on my dev machine before doing a pull?

16:45 technomancy: but with clojars if you've got a bug fix you want to use, it's easy to push your own version with the fix if you can't wait for inclusion

16:45 chouser: not at all

16:45 ordnungswidrig: is there a pendant to reduce where you provide a single initial value and a list of functions f1 f2 f3 so that is returns (f3 (f2 (f1 x)))

16:46 technomancy: chouser: just add them as a remote, fetch from them, and create a branch based on theirs. then review changes and merge if you like 'em.

16:46 chouser: technomancy: ok, thanks.

16:46 kotarak: ordnungswidrig: (reduce #(%2 %1) 0 [inc inc dec dec])

16:47 ordnungswidrig: kotarak: ah fine

16:47 ohpauleez: ordnungswidrig: it sounds like you want to do monadic functions or composition (comp)

16:47 technomancy: you don't even need to create a branch based on theirs actually, you can check theirs out directly if you don't think you'll need to modify it at all.

16:47 chouser: ordnungswidrig: (-> x f1 f2 f3)

16:47 ohpauleez: or that, lacing is a good way too

16:48 kotarak: ... if f1 and friends are known at compile time.

16:48 ordnungswidrig: ohpauleez: ((reduce comp [f1 f2 f3]) x) ?

16:48 chouser: ordnungswidrig: or what ohpauleez said. ((apply comp [inc inc inc]) 2)

16:48 kotarak: ordnungswidrig: ((apply comp [f1 f2 f3]) x)

16:49 chouser: actually [f3 f2 f1]

16:50 ordnungswidrig: ok, I see why it didn't work for me. f is not f :: A -> A but f :: A -> B -> b where B shall be passed through. I think I can throw in some currying

16:51 somnium: ~haskell

16:51 clojurebot: haskell is Yo dawg, I heard you like Haskell, so I put a lazy thunk inside a lazy thunk so you don't have to compute while you don't compute.

16:55 knuckolls: ,((apply comp [inc inc inc]) 2)

16:55 clojurebot: 5

16:55 knuckolls: ,((reduce comp [inc inc inc]) 2)

16:55 clojurebot: 5

16:55 knuckolls: what is the difference?

16:55 hiredman: reduce generates more functions

16:56 knuckolls: how so?

16:56 hiredman: reduce is (comp (comp inc inc) inc)

16:56 knuckolls: ah

16:56 mebaran151_: what's the best way to get clojureql

16:57 clojars have the right version?

16:57 hiredman: lein!

16:57 kotarak: mebaran151_: from clojars.

16:57 chouser: comp has some unrolling that makes up to three args a bit faster

16:57 hiredman: I bet clojars has like five versions

16:57 kotarak: or gradle :P

16:57 mebaran151_: clojars actually only has 2

16:57 hiredman: chouser: eh>

16:57 mebaran151_: one a coworker patched of an older version

16:57 and this unofficial snuxoll package

16:58 kotarak: mebaran151_: http://gitorious.org/clojureql/clojureql for the adventurous

16:58 hiredman: (people who can be bothered installing yet another build system)

16:58 ordnungswidrig: pff, is there a cheap way to reverse the seq of fs?

16:58 chouser: ordnungswidrig: 'reverse' :-)

16:59 kotarak: ordnungswidrig: reverse ;p

16:59 hiredman: hardly cheap

16:59 ordnungswidrig: (apply comp (reverse (map #(partial g %) fs)))

16:59 kotarak: Or rseq if you have a vector

16:59 ordnungswidrig: atm the list is rather short.

17:00 so if the list of functions is long I think I'll do it with a reduce

17:00 mebaran151: I wish the dependencies for clojars didn't pull down the world of sql

17:00 seems as though you should get to choose which jdbc adapter you want to compile in

17:00 kotarak: mebaran151: I working on that.

17:00 I'm

17:01 There will be finer dependencies in the future.

17:01 mebaran151: while I put out my wishlist, have you guys considered adding h2

17:01 it's like a nicer version of derby, with builtin lucene integration

17:02 I'd be willing to help contribute an adapter if the process were simple enough

17:02 kotarak: Is that HSQL? patches welcome. ;)

17:03 ordnungswidrig: nice: (reduce #(exe %2 %1) fs) works in my case.

17:03 hiredman: mebaran151: there is some kind of exclude option for lein

17:03 mebaran151: it's more hsql2

17:03 I'm not sure how you guys would want to integrate the fulltext search option

17:04 it's something I've always thought an SQL db shoudl have

17:05 leafw: a simple question: a fn to update a value in a map, without knowing f the key already exists?

17:06 kotarak: (update the-map [the-key] (fnil f the-default))

17:06 leafw: cool

17:06 kotarak: leafw: fnil was on the google group, posted by Rich

17:06 Just a sec

17:07 leafw: http://groups.google.com/group/clojure/msg/f251cfd9baab440a

17:07 hiredman: depending on the implementation of fnil you might getaway with (update the-map [the-key] fnil f the-default)

17:08 knuckolls: say i'm loading a huge file in slime but i want to stop the load and get back to the repl, how would i do that in slime?

17:08 the-kenny: C-c C-c

17:08 knuckolls: or really, kill any currently running s-exp. like ctrl-c

17:08 aha, tricky

17:09 the-kenny: Maybe you can also kill a possible-existing worker-thread

18:07 mebaran151: how do you insert in ClojureQL?

18:08 kotarak: with insert.

18:08 Just a sec

18:09 mebaran151: http://gitorious.org/clojureql/clojureql/blobs/master/src/clojureql/demos/common.clj

18:09 mebaran151: there are some examples

18:10 mebaran151: okay

18:10 thanks!

18:11 what namespace does sql refer to?

18:13 hiredman: http://github.com/hiredman/clojurebot/blob/master/hiredman/triples.clj

18:14 kotarak: mebaran151: clojureql

18:21 mebaran151: hiredman, have you looked at neo4j's triple support?

18:21 I'm planning on wrapping it when I get the chance

18:24 hiredman: mebaran151: I just through a rock and hit derby, I didn't look at anything else for clojurebot

18:28 KirinDave: Does anyone here have experience with compojure?

18:28 Specifically, trying to get sessions to work but the docs are kinda sketchy on what they actually want here.

18:29 ctdean: I used an earlier version of compojure w/ sessions, what are you trying to do?

18:32 KirinDave: ctdean: Just save some values in a dang session

18:32 ctdean: Let me see if I can paste a quick example

18:32 KirinDave: https://gist.github.com/bcac547ff8ebfde2c982

18:33 ctdean: wrap the routes in with-session

18:33 KirinDave: All of them?

18:34 There is only 1 where I am trying to get it to work.

18:34 And also

18:34 Do you see I wrap main-app with (with-session) ?

18:34 ctdean: Ah, I see. I missed that

18:34 mebaran151: hiredman, it might be interesting to play with

18:34 what's the best way to create table if not exists in clojureql

18:35 kotarak: mebaran151: there are also examples for create table in the previously posted link. However create-table is currently in flux. Just a sec.

18:35 ctdean: one sec

18:36 kotarak: mebaran151: http://gitorious.org/clojureql/pages/CreateTableSyntax

18:38 ctdean: The only thing I can see different is that I used {:type :memory :expires (* 60 5)}) instead if the default

18:38 KirinDave: Where?

18:38 ctdean: So, (with-session thing {:type :memory :expires (* 60 5)})

18:39 KirinDave: How are you supposed to set it?

18:39 somnium: KirinDave: I think you need to return a map with a session key so the session middleware sees it, like {:session {:user "some-guy"} :body "..."}

18:39 KirinDave: Ahah

18:39 I didn't realize I had to assoc onto their session

18:40 mebaran151: kotarak, how do I get the if not exists behavior?

18:41 also any easy way to create index on a table?

18:41 kotarak: mebaran151: no indexes, yet.

18:42 ctdean: Ah yes there is a (session-assoc :x 1) call you need to do

18:42 mebaran151: but what about if not exists, or what would be the best way to check if a table existed?

18:43 kotarak: mebaran151: you have to do (drop-table foo :if-exists) (create-table foo)

18:43 mebaran151: what if I don't want to drop the table

18:43 I just want to create it if not exist

18:43 can create-table have an :if-not-exists option?

18:44 kotarak: mebaran151: if the backends support it... Nicolas is currently working on create-table.

18:44 mebaran151: ah

18:45 kotarak: eg. Derby does not support drop-table if-exists, so no support there.

18:45 eg. Postgres does, so the support is available.

18:46 Licenser: I've some seriouse problems with swank clojure and os x it just refuses to connect to the projects repl :/

18:46 I get 'Polling "/var/folders/b5/b5QOdd5jGfmy7oTg2xxwEU+++TI/-Tmp-/slime.2875".. (Abort with `M-x slime-abort-connection'.)' and a few thousand attempts but it kind of just keeps doing that

18:49 mebaran151: kotarak, do you guys supply any mechanism to query the schema?

18:59 joshua-choi: Question: What is the purpose of separating the array-map and hash-map functions? Is there a time when I should use one and not the other?

19:04 mebaran151: kotarak, how does one open a db transaction?

19:04 technomancy: joshua-choi: I get the feeling that's an implementation detail leaking; I don't think you ever want to call array-map

19:05 array-maps have the odd property of allowing duplicate keys, which you really don't want.

19:05 joshua-choi: technomancy: Well, the {...} syntax creates array maps or hash maps, depending on the number of elements inside, right?

19:06 I'm not sure how it decides, though

19:06 technomancy: if it's 8+ entries, it's a hash map

19:06 ,{:a "A" :b "B" :a "C"}

19:06 clojurebot: {:a "A", :b "B", :a "C"}

19:06 joshua-choi: ,(type {:a 3})

19:06 clojurebot: clojure.lang.PersistentArrayMap

19:07 joshua-choi: ,(type {1 2 3 4 5 6 7 8 9 0 123 529 59 293 12 32 98 10})

19:07 clojurebot: clojure.lang.PersistentHashMap

19:08 joshua-choi: Is there any function that imitates the {...} notation?

19:08 Something like the vec or set functions for maps

19:08 technomancy: ,(type (hash-map))

19:08 clojurebot: clojure.lang.PersistentArrayMap

19:08 technomancy: not sure what to think of that

19:09 I guess just use hash-map and be sure not to have any duplicate values in your literals.

19:09 joshua-choi: That's so weird

19:09 Okay, thanks for the advice

19:09 technomancy: as long as you don't have duplicate keys in your literals, you'll never notice the difference

19:09 joshua-choi: ,(type (array-map 1 2 3 4 5 6 7 8 9 0 123 529 59 293 12 32 98 10))

19:09 clojurebot: clojure.lang.PersistentArrayMap

19:09 joshua-choi: Hmm

19:10 technomancy: assoc and friends won't allow duplicates even on array-maps

19:10 it's only the constructors that do

19:10 mebaran151: also, I'm getting a strange error, java.sql.SQLException, Resultset not open

19:11 somnium: ,(type (assoc (array-map 1 2 3 4 5 6 7 8 9 0 123 529 59 293 12 32 98

19:11 10) :a :a))

19:11 clojurebot: EOF while reading

19:11 joshua-choi: And it seems like array-map always returns array maps, while hash-map may return either array or hash maps

19:12 technomancy: I don't think it's ever an issue in real life, but it's interesting to peek under the covers

19:12 somnium: bah, array-maps automatically get made to hash-maps as they grow

19:12 technomancy: the only time it bites people is when you're using transients incorrectly (bashing in place) and an array-map grows into a hash-map

19:13 joshua-choi: Oh, can that happen? I haven't tried map transients yet

19:14 technomancy: which is actually a feature! since it gives you an opportunity to learn what transients are actually all about. =)

19:23 dysinger: skeptomai: I come to see opscode again in jan 25-29 timeframe :) I'll have to infect opscode with some clojure

19:23 we should actually get some chef recipes going in clojure ;)

19:24 skeptomai: dysinger: totally

19:24 I have it running with slime, et al, but haven't had time to do anything cool

19:40 ctdean: what dep should I use in lein to get the compojure jars ?

19:42 tomoj: as far as I know there isn't a good one yet

19:43 all the ones I saw didn't include all the deps, as far as I could tell

19:45 I made my own, org.clojars.tomo/compojure

19:45 but I can't remember if I've gotten it working perfectly yet

19:46 ctdean: ok thanks

19:46 tomoj: eventually the compojure people will provide one, I would hope

19:51 erikcw: M-x swank-clojure-project doesn't seem to do anything. I setup that path with a lib directory with my extra jars, but "(println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))" doesn't seem to change. Am I missing something?

19:53 tomoj: erikcw: do you use leiningen?

19:53 erikcw: tomoj: not yet

19:53 I'm just getting started

19:54 tomoj: oh, I think I remember having a problem where lein tricked swank-clojure-project into not finding my jars

19:54 but I'm not sure

19:54 erikcw: is lein the recommended "method"

19:56 tomoj: it is getting there

19:56 but I still use swank-clojure project sometimes

19:56 (and it still picks up my jars)

19:57 what version of swank-clojure are you using?

19:57 erikcw: do I need any directories other than lib?

19:57 tomoj: src/ and lib/ are all I usually use

19:58 erikcw: I'm 1.1.0

19:58 tomoj: oh, mine is outdated

19:58 erikcw: out of package-list-packages...

19:58 tomoj: now my package-list-packages isn't even working

20:09 * mebaran151 is getting frustrated with ClojureQL

20:15 tomoj: mebaran151: why?

20:24 mebaran151: getting errors like

20:25 no multimethod for integer embedconn

20:25 resultset not open

20:25 I can't get it to do anything basic

20:25 JonSmith: what is the it that is broken

20:27 mebaran151: query

20:28 so I think the table gets created (it returns an EmbedStatement)

20:28 #<EmbedSQLException java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is OFF.>

20:28 that's the error

20:28 sure there should be no rows

20:28 but I have no idea how to fix it

20:30 tomoj: maybe if the owner comes around he will have an idea

20:38 JonSmith: is there a good explanation of how the 'shared structure' works in clojure

20:40 mebaran151: http://gist.github.com/272648 << if anybody knows clojureql, maybe I'm just doing it wrong so to speak

20:40 JonSmith: I'm thinking about using a vector of hash-maps to represent state changes, where each is incrementally changed version of the next

20:40 wondering if that will be hugely memory intensive

20:41 mebaran151: each hash-map?

20:41 that shouldn't be

20:41 only hash-map modifications are recorded

20:41 the vectors still point to the same basic structures

20:42 JonSmith: yeah each hash map

20:42 i was thinking it would be a good way to represent user state in a web app

20:43 mebaran151: hmmm

20:43 interesting

20:51 JonSmith: yeah i was thinking of it as a hybrid between rest and cps frameworks

20:51 hiredman: mebaran151: the results from clojureql are in a lazy seq that is closed when you leave the scope of whatever form that is

20:51 cql/run

20:52 or the result of the query that is used to generate the lazy-seq is closed

20:52 basically you have to use doall everywhere

20:52 very much a pain

21:10 mebaran151: hmmm?

21:10 do hiredman, is my createtable statement okay?

21:11 LordMetroid: hm clojure seems very tempting, why are no one adopting it?

21:12 *why are so few adopting it?

21:12 JonSmith: seems like a lot are?

21:13 #clojure pop is only 100 less than #lisp pop

21:14 LordMetroid: mmm, but I don't see the popularization of the language on such scale as Erlang for example.

21:19 JonSmith: oh

21:19 idk its pretty young so we'll see

21:21 LordMetroid: mmm, it sure seems to have a well progressing early adopters rate

21:22 mebaran151: http://gist.github.com/272668

21:22 that's my create-table method

21:22 hiredman: erlang has been around *forever*

21:22 mebaran151: is it technically correct?

21:23 erlang hails from the late 80's doesn't it

21:25 hiredman: erlang also is used to address a current problem (distributed systems) while clojure is aimed at a still developing problem (leveraging multicore)

21:25 mebaran151: as far as I can tell

21:26 mebaran151: I should be able to run (query users *) afterwards

21:26 however when I try to run it

21:26 I get ... brokenness

21:27 Resultset has no next ('cause there are no results)

21:27 hiredman: most likely because you are try to examine the resultset after it has been closed

21:28 mebaran151: (doall (dosql (query users *)))

21:28 that doesn't work

21:28 I can't figure out a single construct that does

21:28 hiredman: you have to put the doall inside

21:29 the resultset is closed after leaveing the 'run' macro

21:29 mebaran151: order doesn't matter

21:29 hiredman: are you sure?

21:29 mebaran151: putting the doall inside the dosql doesn't do anything

21:30 (run *conn-info* (doall (query users *))) << this doesn't work

21:30 hiredman: *shrug*

21:35 cark: (run *conn-info* (doall (dosql (query users *)))) not working either ?

21:35 ctdean: What are folks using for Amazon S3 access these days?

21:35 hiredman: dosql expands into a call to run

21:35 mebaran151: yeah

21:36 just embeds *conn-info*

21:40 do I have to do something special with the embedpreparedstatement the statement creator returns?

21:42 LordMetroid: hiredman: Erlang was constructed to solve concurrency and reliability

21:43 hiredman: It was developed by the company Ericsson AB to run their telephone systems, which demands reliability and concurrency

21:43 mebaran151: cark, no matter where I put the doall I get an error

21:43 and I can't insert

21:43 I'm gonna try building from source

21:44 LordMetroid: hiredman: as a side effect of them solving concurrency using hyper-lightweight processes and message passing rather than shared state Erlang is well suited for multicore deployment as well

21:45 hiredman: as of lately the Erlang VM development has been focusing on optimizing multicore executions

21:56 mebaran151: I'm gonna try to run the demos

22:01 JonSmith: erlang is a little slower distributed because of tcp connections and message passing and stuff

22:03 hiredman: LordMetroid: sure, because everyone can seen it on the horizon, but clojure is targeted at it right now

22:03 LordMetroid: well, it is running on the JVM so I wouldn't exactly say it is developed for multicore deployment

22:17 mebaran151: this ResultSet not open is beginning to annoy me to hell

22:26 hiredman: LordMetroid: have you seen the specially built jvm boxes?

22:26 LordMetroid: hiredman: no, what do you mean?

22:26 hiredman: azul

22:27 the jvm can do multicore just fine

22:27 LordMetroid: I see

22:27 mebaran151: now I got inserts working, I just can't get queries to ... stay open

22:28 LordMetroid: okay time to get some sleep before the sun rises

22:28 JonSmith: you have to do everything in the dosql right?

22:28 its like a transaction or something?

22:28 or am i wrong

22:29 just kind of wondering

22:31 hiredman: it's a macro he wrote

22:31 JonSmith: oh that isn't native to the library

22:32 mebaran151: I've tried it with run

22:32 and I get the same results

22:33 (doall (sql/run *conn-info* (sql/query users * (= username "mebaran"))))

22:33 this too fails

22:34 as with the doall in front for the query

22:34 this resultset refuses to stay open

22:34 hiredman: did you look at the examples from clojurebot?

22:34 mebaran151: yep

22:34 hiredman: well, you must not have been paying attention :P

22:34 JonSmith: (sql/run *conn-info* (doall (sql/query users * (= username "mebaran"))))

22:34 did you try that?

22:35 mebaran151: same beans

22:35 hiredman: http://github.com/hiredman/clojurebot/blob/master/hiredman/triples.clj#L50 <-- what is different in this call to run?

22:35 mebaran151: {:jdbc-url "jdbc:derby:.gate/db;create=true", :username nil, :password nil} << mode string

22:35 ah ha

22:36 JonSmith: hiredman wrote it?

22:36 mebaran151: oh

22:36 I just have to bind it to something in scope

22:36 let's try this huzzah

22:36 JonSmith: that's interesting

22:37 i guess its like a with-open macro

22:37 mebaran151: oh my

22:37 it worked

22:37 yay

22:38 hiredman: it's rather distateful

22:38 it looks like a binding form, but isn't

22:38 if you just want to use the result seq you have to call doall everywhere

22:38 etc

22:39 there was a blog post criticizing the use (abuse?) of syntax quote and unquote

22:40 but it works, I guess, which is good...

22:40 mebaran151: I thought syntax quote was okay

22:40 it made me realize that it was quoting the sql

22:40 I read the post

22:43 hiredman: I have a query api I was working on for the appengine datastore, which is much simpler than sql, but i think I did a nicer job of looking like clojure

22:43 (qfilter (= 1 :count) (query :counter-things))

22:48 mebaran151: it looks almost rubyish

22:48 you have to check the result to be a seq

22:48 (defmacro dosql

22:48 [& forms]

22:48 `(sql/run [*conn-info* results#] ~@forms (if (seq? results#) (doall results#) results#)))

22:48 I think it should run somewhat like that

22:49 call doall for you

22:49 hiredman: anyway, we need scopes

22:50 mebaran151: I ran into this problem with my neo4j bindings (I want to close the resultset of nodes but I can't)

22:51 do scopes have to be built into clojure proper or could sufficiently advanced macro fu emulate them?

22:51 hiredman: I have such a macro

22:51 http://github.com/hiredman/clojurebot/blob/master/hiredman/horizon.clj

22:52 ~scopes

22:52 clojurebot: I don't understand.

22:52 hiredman: ~scope

22:52 clojurebot: scope is at http://paste.lisp.org/display/73838

22:54 mebaran151: but you'd have to stay within and explicit scoping construct

22:54 it seems like a more general with-open

22:54 hiredman: sure

22:54 exactly

22:55 mebaran151: I'd love to be able to give a lazy-seq to some caller, and then when they are done with it, have something like IDispose get called

22:55 hiredman: that is the idea behind scopes

22:56 if F produces a lazy seq one some resource that needs to be closed, it can register a thunk to do the closing

22:57 and then just return the lazy-seq and not worry about it

22:57 mebaran151: but you still have to act within the scope

22:57 as in the caller has to setup the scope right?

22:57 hiredman: sure

22:57 mebaran151: I would like a super finally

22:58 finally that gets called after a variable goes out of scope permanently

22:58 hiredman: no variables

22:58 names bound to values

22:59 when a name goes out of scope

22:59 mebaran151: yeah

23:00 it seems like something I'd almost want a :post on functions to handle

23:00 hiredman: but the called function can't know what (or if) it's result will be bound to

23:00 mebaran151: yeah

23:00 I guess it's like transactions for refs: if you want to work with a construct, you have to be prepared to inform the construct where you're working with it

23:06 so I guess inside that scope you'd like say, read all the nodes you want, copy them to the outside scope space and get to close the iterator

23:35 couldn't a sufficiently smart compiler know?

23:35 when a name would no longer be applicable, and therein dispose of the resource

23:39 hiredman: for some subset of cases

23:40 it would have to be really really smart

23:43 mebaran151: this is true

Logging service provided by n01se.net