#clojure log - Sep 16 2009

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

3:09 Fossi: hi

3:40 lpetit_: hello all

3:47 LauJensen: Morning gents :)

3:48 arbscht: hey LauJensen

3:48 * arbscht is using clojureql at last

3:49 LauJensen: Weee :)

3:49 How's that working out for you

3:50 arbscht: a few rough edges, but it's doing a fine job of logging my data

3:51 LauJensen: Great - Let me know if there's something we need to have a look at

3:51 hiredman: is clojureql/run really the best way to execute statements?

3:52 LauJensen: hiredman: For now, we're still .... debating.. how to best implement a long lived connection type execution

3:52 hiredman: my main issue is the form of the call

3:52 (cql/run [db results] statement (doall results))

3:53 over and over and over

3:53 LauJensen: Suggestions?

3:53 hiredman: (cql/run db statement)

3:55 I've, of course, only scratched the surface of clojureql I'm sure, likely missing some nuanced something or other

3:56 LauJensen: hiredman: (run *conn* (query table *)) will return the resultset-seq directlyl

3:56 hiredman: orly

3:56 good to know

3:56 LauJensen: (doc run) :)

3:56 clojurebot: "clojure.contrib.repl-utils/run;[[ns-name & args]]; Loads the specified namespace and invokes its \"main\" function with optional args. ns-name is not evaluated."

3:57 hiredman: all my complaints are resolved

3:57 I dunno, it took a lot of work just to find cql/run

3:57 speaking of complaints :P

3:57 LauJensen: ooh :)

3:57 Gotcha

3:57 hiredman: I think I ended up digging through the source

3:58 LauJensen: The demo is a good place to start

3:58 Shows off most features in their primitive forms

3:58 arbscht: what's the status of limit/offset now?

3:59 LauJensen: For limit you simply use (take 10 (run *c* (query foo *)), drop is pending Kotaraks return - He's currently moving

4:00 arbscht: great

4:00 LauJensen: yea, I also thing we still need to debate that a little more

4:00 eevar2: LauJensen: that works, even if your query selects a million rows?

4:00 *efficiently

4:00 LauJensen: Yes

4:01 resultset-seq is fully lazy, so take what you need, then drop the reference and it closes

4:01 you CAN also use drop, but that's a waste of resources

4:01 eevar2: LauJensen: lazy on the server side as well, i mean?

4:02 LauJensen: Yes it should be

4:02 eevar2: oki

4:02 LauJensen: There are a few things where we rely on the jdbc driver, I think this is one of them

4:03 hiredman: erm

4:04 AWizzArd: Moin guys

4:04 hiredman: the lazinesss of result-seq has the same issue of dynamic binding vs. map

4:05 LauJensen: Morning AWizzArd

4:05 hiredman: clarify ?

4:05 hiredman: (binding [*db* some-db-connection] (result-seq-producing-function)) try to use the lazy result-seq outside of the binding *BOOM*

4:06 LauJensen: Oh ok

4:06 hiredman: that's why I have (doall results) everywhere

4:10 LauJensen: But shouldn't the compiler be able to work that stuff out?

4:10 I would feel funny to tailor make CQL to work around it

4:10 hiredman: either work on the compiler, or work on clojureql

4:10 LauJensen: SIR YES SIR

4:10 :)

4:11 hiredman: my personal preference is a simple compiler, sense compiler bugs are bad :(

4:12 LauJensen: Well, I just got through all my messages from the scala community, so I can get to work :)

4:22 AWizzArd: hiredman: yes, I noticed that too

4:23 hiredman: since

4:23 AWizzArd: you mean when I discovered it? It was in the beginning of this year, when I was doing sql

4:24 hiredman: no, I was just correcting my use of sense

4:25 LauJensen: hehe

5:37 Now on the frontpage of DZone :) http://dzone.com/links/scala_vs_clojure_lets_get_down_to_business.html

6:00 magnet: Am I the only one who feel it is biaised?

6:01 LauJensen: No it's biased

6:01 magnet: LauJensen, Clojure isn't pure either

6:01 "pure functional"

6:01 hiredman: http://twitter.com/RichardVowles/statuses/4024290926

6:02 LauJensen: Haha

6:02 Yes he left a comment on the blog also :D

6:02 magnet: It's close enough I'd say

6:02 magnet: LauJensen, look at Haskell and you will see it's pretty far

6:02 LauJensen: I know

6:03 magnet: OK, you are safe from mutable data *if you stay away from Java code*, and clojure prevents you from a lot of pain

6:03 but I felt your Scala examples weren't idiomatic at all

6:03 Anyway it's lunch time

6:03 hiredman: I can't actually bring myself to read the blog post, but my impression is that it is something of a hatchet job

6:04 LauJensen: magnet: The examples we're supplied by Scala programmers - I don't have the chops for it

6:04 hiredman: define hatchet job ?

6:05 hiredman: ~google hatchet job

6:05 clojurebot: First, out of 173000 results is:

6:05 magnet: "Scala does not in anyway discourage it’s users from side-effects and mutable code". Sure it does, thourough the Scala book, with standard data structures (and with the scheduled STM that will probably look a lot like Clojure's)

6:05 clojurebot: hatchet job - definition of hatchet job by the Free Online ...

6:05 http://www.thefreedictionary.com/hatchet+job

6:05 magnet: See you later

6:05 LauJensen: l8r

6:06 hiredman: seriously?

6:06 I re-read it last night, wondering what all the anger was about, and I felt like I gave Scala a pretty good review

6:06 hiredman: seriously

6:07 well, like I said, I haven't read it, but that's been my impression

6:08 LauJensen: ah ok

6:21 G0SUB: what's the recommended way of parsing XML in Clojure?

6:25 hiredman: clojure.xml/parse

6:26 ,(doc clojure.xml/parse)

6:26 clojurebot: "([s] [s startparse]); Parses and loads the source s, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content. Other parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser"

6:28 G0SUB: hiredman: cool. thanks

6:29 hiredman: btw, can you recommend any templating engine? I was thinking about StringTemplate.

6:34 crios: hello

6:42 raphinou_: where can I report in documentation? (see http://clojure.org/api#remove where it should be "predicate returns true")

6:55 crios: does Clojure require a JVM >= 5 ?

7:02 raphinou_: crios: i think so

7:20 crios: Is there an idiomatic Clojure way for a blocking wait ? For example, before send another "ping" message I must first receive a "pong" one

7:21 In java, i'd wait and notify on the same instance (inside a synchronized block)

7:21 jdz: crios: why don't you send the ping message when you receive the pong one?

7:22 crios: jdz: using an Agent?

7:22 jdz: i mean, how do you wait for the pong message?

7:23 crios: in Java?

7:23 jdz: i'm not sure you want agents. (they delay the task until *some* time in the future; the only guarantee is that it will execute before you aske it for the result)

7:24 hiredman: woa

7:24 no

7:24 agents don't guarantee that

7:24 crios: mmm. I'm just trying to understand how a producer/consumer queueu should be implemented in Clojure

7:24 hiredman: they are totally async

7:25 jdz: ,(doc wait-for)

7:25 clojurebot: It's greek to me.

7:25 jdz: ugh, shows how much i've used agents :?

7:25 hiredman: there are futures, promises, BlockingQueues, etc, etc

7:25 crios: ,(doc await-for)

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

7:26 crios: ah ok

7:26 arbscht: what about adding a watch to an agent?

7:29 crios: mmmm. In a chess board game, how would you implement a "player moves after the other's movement"

7:29 ?

7:33 hiredman: depends

7:36 powr-toc: What's the difference between clojure.test and test-is? It seems that test-is was renamed to clojure.test when it moved into core... but is test-is still developed in contrib?

7:37 Fossi: i think it's just there for compatibility

7:38 not sure if there are any differences though

7:38 crios: hiredman: depends of what?

7:39 powr-toc: so test-is is now deprecated in favour of clojure.test?

7:42 crios: await for blocks the current thread, waiting an agent. So the other player should (send something) to the same agent?

7:45 durka42: crios: await waits for the agent to finish the send-off it's currently working on

7:48 crios: I'll try to write a simple ping-pong, just for study purposes.

7:55 by the way, can I read from the standard input stream on the REPL?

7:56 can a *in* rebind work?

8:38 futuranon: .6

9:04 adityo: hello

9:04 cgrand: adityo: hi!

9:05 adityo: how do i define something like StringTemplateGroup group = new StringTemplateGroup("myGroup", "C:\\Tutorials", DefaultTemplateLexer.class) this in clojure

9:05 cgrand: hey

9:05 especially DefaultTemplateLexer.class

9:06 Chouser: (let [group (new StringTemplateGroup "myGroup" "C:\\Tutorials" DefaultTemplateLexer] ...)

9:06 adityo: okie so .class means nothing

9:06 Chouser: right

9:06 LauJensen: Chouser, new ?

9:07 Chouser: unless used like a namespace (FooBar/baz) a class name will resolve to the Class instance (like FooBar.class in java)

9:07 LauJensen: *shrug*

9:08 adityo: cool thanks it works (let [#^StringTemplate group (StringTemplateGroup. "myGroup" "/home/adityo/ib-projects" DefaultTemplateLexer)]

9:14 cant we import all the libraries in a java package, something like org.antlr.stringtemplate.*;

9:15 Fossi: no

9:15 adityo: okie, not a problem but can be a pain sometimes :)

9:16 Fossi: i guess only really with stuff like Swing

9:16 personally, i've never used it in java either

9:16 adityo: ;)

9:16 Fossi: then again eclipse and such do the job pretty well for you

9:17 too bad that there's nothing like it in emacs/slime/clojure-mode

9:18 adityo: just what i was getting to..too bad..but seriously how good is clojure development using Eclipse, i havent used eclipse ever but i would like to try it out

9:20 Fossi: i switched to emacs for clojure

9:20 haven't regret it

9:20 AWizzArd: Is there a vid from rhickeys MS talk yesterday?

9:20 Fossi: editing s-expressions is just so much better when your editor can handle them

9:20 especially with paredit

9:21 adityo: Fossi: that i agree paredit rocks!!

9:21 Fossi: it's more slice and dice than cursor around and type

9:23 AWizzArd: What are your two or three favourite paredit features?

9:23 lisppaste8: raphinou pasted "idea for map utils?" at http://paste.lisp.org/display/87163

9:24 Chouser: I assume paredit uses multiple-key chords for its commands?

9:24 adityo: M-r is nice

9:24 Chouser: two keys. hm.

9:24 raphinou_: chouser: I needed to pasted code for my project. Might be interesting for clojure.contrib.map-utils?

9:25 AWizzArd: adityo: what is M-r doing?

9:25 Fossi: open parenthesis (also closes them), split s-expr, paredit-forward-slurp-sexp and not really paredit but much more useful then: transpose-sexpr

9:26 i rarely use M-r. i guess i should :)

9:27 any time you find yourself using the arrow keys, something is wrong :)

9:28 raphinou_: Chouser: Take your time, but if you don't like the code don't hesitate to tell me as I'm still learning clojure ;)

9:28 Chouser: raphinou_: it seems a little odd to use both key and val in such operations.

9:29 raphinou_: seems to treat a map as a set key/val pairs. You look up these things by key as well?

9:29 raphinou_: Chouser: I need to test the val : {:name "e"\} is a submap of {:name "e" :email "v@v.com"}

9:29 but {:name "e" :email "myemail@name.com"} is not

9:30 Chousuke: raphinou_: I think you should destructure kv to k and v rather than doing (kv 0) and (kv 1) :/

9:30 raphinou_: ha, yes

9:30 Chousuke: hmm

9:30 Chouser: ,(into {} (map (set {:a 1 :b 2 :c 3}) {:b 2 :c 4 :d 5}))

9:31 clojurebot: {:b 2}

9:31 adityo: AWizzArd: M-r (paredit-raise-sexp)

9:31 Chouser: there's another way to write map-intersect

9:31 (though quite possibly less efficient)

9:31 adityo: AwizzArd: raises a single S-expression up the tree, deleting all of its siblings and its enclosing list.

9:32 raphinou_: don't hesitate to anotate the paste

9:32 adityo: AwizzArd: awesome if you want to delete some stuff and have deeply nested S-expr's

9:33 Chousuke: I just use barf, slurp and kill-sexp the most :P

9:33 in fact I don't even remember the keybindings for the rest :)

9:34 Chouser: Chousuke: is that paste/copy/delete of an s-expr?

9:34 Chousuke: Chouser: no

9:34 barf and slurp are something else

9:34 kill-sexp is "cut"

9:35 if I want to copy I usually just kill and yank it twice

9:35 Chouser: what are barf and slurp?

9:35 raphinou_: Chousuke: your map-intersect is much shorter indeed :-) Any suggestions for is-submap? (I don't see how to destructure as I don't know the name of the keys)

9:36 Chouser: raphinou_: working on it...

9:36 Chousuke: barf "extracts" an s-expr from inside another and slurp, well, slurps it :P

9:36 raphinou_: ha, ok :-)

9:37 adityo: A good link to understanding barf and slurp http://www.cliki.net/Editing%20Lisp%20Code%20with%20Emacs

9:37 Chousuke: (every? identity (for [[k v] submap] (= v (mainmap k)))) ?

9:38 hmm

9:38 Chouser: (defn is-submap? [big sml] (every? (fn [[k v]] (= (big k) v)) sml))

9:40 lisppaste8: Chouser annotated #87163 "smaller map-as-set fns" at http://paste.lisp.org/display/87163#1

9:41 Chouser: raphinou_: I'd be curious if anyone else has needed these. Doing set operations on maps key/val pairs strikes me as unusual.

9:41 * raphinou_ thinks he still has a lot to learn after seeing the annotations :-)

9:42 Chousuke: raphinou_: to begin with, in a functional language an explicit loop is rarely the best option :)

9:42 so if you find yourself writing (loop ...) then stop and consider if it's possible to use higher-order functions instead.

9:43 raphinou_: Chousuke: I need it to remove elements from a list of maps, and want to be able to specify a possible submap. Kind of a sql delete: where name="r" will delete more than where name="r" and status=1

9:44 ehm, shuffling Chousuke and Chouser.....

9:44 Chousuke: heh

9:44 Chouser: raphinou_: clojure.set has several functions that work on sets of maps -- you may find much of what you're looking for there.

9:45 raphinou_: Chousuke: will remember that about the loops!

9:45 will look, thx for the pointer Chouser

9:46 and thanks to both of you for your feedback, even if I now may throw away those functions I was so proud of :-D

9:46 Chouser: raphinou_: yeah, sorry. it's how it goes. :-/

9:47 other little tips -- conj onto a map can actually take a vector

9:47 raphinou_: Chouser: no problem, that's learing ;) I'd rather throw away and learn than keep and stay ignorant!

9:47 Chouser: ,(conj {} [:a :b])

9:47 clojurebot: {:a :b}

9:47 Chouser: so (conj result {(kv 0) (kv 1)}) could just be (conj result kv)

9:48 raphinou_: ok!

9:48 Chouser: use == instead of = when comparing numbers, but be suspicious of checking the size of things with 'count'

9:48 raphinou_: why this caution about count?

9:48 Chouser: the idiomatic way to check for an empty collection is (seq coll) or (empty? coll)

9:49 so (if (empty? test-map) result ...)

9:50 raphinou_: ok!

9:51 Chouser: otherwise, use destructuring more and your code looked fine.

9:52 raphinou_: thanks for the encouragements Chouser. I can see the direction to take, now I have to get used to that way of doing!

9:52 Chouser: I suspect my is-submap is roughly as fast as yours. my map-instersect does an O(n) walk of map1 (building the set) that yours doesn't

9:53 so mine might be slower. you could change filter's predicate to be more like 'is-submap?' if you find it's too slow as-is.

9:54 conversely is-submap? could be more compact: (defn is-submap? [big sml] (every? (set big) sml))

9:56 raphinou_: yes, I see

10:00 about arguments order, is is-submap? [big sml] better than [sml big]?

10:00 Chouser: raphinou_: I just used the same order as you, I think.

10:01 crios: stupid question: I'm trying to emulate:

10:01 for (int i=1; i<= 10; i++ ) println i+"";

10:01 but (apply println (range 1 10) )

10:01 is not correct: it seems concat all parameters

10:01 raphinou_: Chouser: yes, but I wondered if I had taken the usual order of arguments

10:01 crios: then printing just one \n

10:01 Chouser: crios: for side-effectful loops, use 'do'-something. doseq, dotimes

10:03 raphinou_: there's always some debate about that. (conj coll item) vs. (cons item coll) for example

10:03 Chousuke: crios: the apply means calling println once with 10 arguments, while the for loop calls it twn times with one argument :)

10:03 or actually, (range 1 10) only produces numbers up to 9

10:04 ,(doseq [i (range 1 11)] (println i))

10:04 grigna-ak: crios: something more like this (doall (map println (range 1 11)))

10:04 clojurebot: 1 2 3 4 5 6 7 8 9 10

10:04 Chouser: raphinou_: I guess for 'is-submap?' feels a bit like a predicate/collection fn, in which case I'd expect [sml big]. *shrug*

10:04 Chousuke: clojurebot: hello?

10:04 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline Chousuke

10:04 Chousuke: hmm /:

10:04 wow

10:04 some lag :P

10:05 raphinou_: Chouser: yes, or keep arguments order and rename function has-submap?

10:07 crios: what is wrong with: (dotimes [count 10] println (count) ) ?

10:08 http://clojure.org/api#toc226

10:08 Chouser: ,(dotimes [i 10] (println i))

10:08 clojurebot: 0 1 2 3 4 5 6 7 8 9

10:09 crios: ah pardon

10:09 Chouser: crios: parens around 'count' would try to invoke a number. won't work.

10:09 crios: no parens around (println ...) meant it wouldn't be called.

10:09 crios: yes, you're right

10:09 Chouser: and 'count' is a builtin name, so I'd recommend avoiding using it for your own locals.

10:10 crios: ok

10:20 '(dotimes [i 11] (fn [] ( (Thread/sleep 1000) println i) ))

10:20 ,(dotimes [i 11] (fn [] ( (Thread/sleep 1000) println i) ))

10:20 clojurebot: nil

10:21 crios: ,(dotimes [i 11] (fn [] ( (Thread/sleep 1000) println i) ))

10:21 clojurebot: nil

10:22 crios: ,(dotimes [i 11] (fn [] (Thread/sleep 1000) (println i) )

10:22 clojurebot: EOF while reading

10:22 crios: mm I don't understand

10:23 trying ;for (int i=1; i<= 10; i++ ) { Thread.sleep(1000); println i+""; }

10:26 raphinou_: crios: this works for me: (dotimes [i 11] ((fn [] (Thread/sleep 1000) (println i) )))

10:26 note the extra paren around fn

10:26 you only defined the function without calling it

10:30 crios: and this should do what you expected: (dotimes [i 11] (.start (Thread. (fn [] (Thread/sleep 1000) (println i)))))

10:31 Chouser: dotimes takes a block, not just a single expression.

10:32 ,(dotimes [i 4] (Thread/sleep 1000) (println i))

10:32 clojurebot: 0 1 2 3

10:32 adityo: i have created code with two diff namespaces e,g foo.bar and abc.def..now how do i call foo.bar in abc.def?

10:33 raphinou_: yes chouser, even better

10:34 Chouser: adityo: once both have been loaded, foo.bar/your-var-name

10:35 crios: thanks raphinou_, never thought on that more parens!

10:35 using Thread/sleep sleeps the current thread

10:35 your .start etc sleeps a new thread

10:36 Chouser: adityo: you can use 'alias' or 'refer' to use a different name or no name at all for the foreign namespace.

10:36 adityo: you can use 'use' or 'require' to load and alias a namespace all at once.

10:36 adityo: Chouser: and how will i load both of them..sorry for stupid questions but i am a bit confused

10:37 Chouser: so in abc.def: (ns abc.def (:use [foo.bar :only [a b c]]))

10:37 adityo: then you can call foo.bar's a b and c functions directly: (a 1 2)

10:38 crios: by the way, this should start 10 threads? (dotimes [i 11] (.start (Thread. (fn [] (Thread/sleep 1000) (println i)))))

10:38 Chouser: crios: 11

10:38 ,(count (range 11))

10:38 clojurebot: 11

10:38 adityo: Chouser: thanks :)

10:38 crios: thanks by me too :)

10:44 Fossi: is there a way to get a macro/backquote to not do the namespacing for me?

10:46 Chouser: ,`(namespacing is ~'usually good)

10:46 clojurebot: (sandbox/namespacing sandbox/is usually sandbox/good)

11:00 crios: why this get a nullpointer?

11:00 ,(let [tPing (Thread. (fn [] (dotimes [i 11] ((Thread/sleep 500) (println "ping"))))) ] (. tPing start) )

11:00 clojurebot: nil

11:00 crios: [well in the REPL goes in NullPointer]

11:02 shoover: crios: looks like too many parens inside the dotimes

11:03 Chouser: ,(Thread/sleep 1)

11:03 clojurebot: nil

11:03 Chouser: Thread/sleep returns nil. You then have that at the front of a list, so Clojure tries to call nil as a function.

11:03 ,((Thread/sleep 1) 'anything 'here)

11:03 crios: ok

11:03 clojurebot: java.lang.NullPointerException

11:05 crios: I think this is my problem: any time I see a API which expect a body/form, I tend to wrap that into two parens

11:05 that is, I'm still new to the "executablity" of parens

11:06 raphinou_: when writing tests with clojure.test, I thought to use fixture functions to set up a ref that is manipulated by functions. Am I right to think that this ref should be put ina binding for it to be available to actual test functions?

11:08 crios: by the way, how could I access to the current thread instance? a sort of: ,(let [tPing (Thread. (fn [] (dotimes [i 11] (( this.sleep 500) (println "ping"))))) ] (. tPing start) )

11:08 see this.sleep

11:10 stuartsierra: raphinou_; yes, bindings are how fixtures pass information to tests

11:10 Chouser: sleep is not an instance method

11:11 raphinou_: thx stuartsierra

11:12 crios: yes, Chouser. But in general? I'd like to call countStackFrames for example

11:12 in that new thread

11:12 Chouser: ,(Thread/currentThread)

11:12 clojurebot: #<Thread Thread[Thread-178,5,main]>

11:14 crios: that is, I know I can write (. tPing start)

11:16 raphinou_: this must be a stupid question: how do a remove an element of an arry by its key?

11:16 crios: but how could I write something as ( THIS countStackFrames )

11:16 raphinou_: kind of (remove 5 [1 2 3 4 5 6 7 8])

11:16 Chouser: ,(.countStackFrames (Thread/currentThread))

11:16 clojurebot: java.lang.IllegalThreadStateException: this thread is not suspended

11:17 Chouser: raphinou_: neither Java arrays nor Clojure vectors can remove items from the middle efficiently

11:18 raphinou_: Chouser: hmm... what do you advise?

11:18 Chouser: raphinou_: about the best you can do is:

11:18 ,(let [v '[a b c d e f]] (into (subvec v 0 2) (subvec v 3)))

11:18 clojurebot: [a b d e f]

11:19 Chouser: raphinou_: sets and maps are good at removing arbitrary items

11:20 crios: Chouser, I mean: inside the anonymous function wich implements Runnable (dotimes [i 11] (. countStackFrames ) (println "ping")) can I call countStackFrames?

11:21 I think no, because I've no symbol associated to the new Thread instance

11:21 Chouser: raphinou_: that subvec example is O(n) on the second subvec

11:21 raphinou_: Chouser: I don't think maps and sets correspond to what I need. I was already using split-at for inserting elements in the vector (with destructuring btw ;-) . I guess I'll do like you say for removal

11:21 Chouser: crios: yes, I keep giving you examples. (Thread/currentThread) returns the current thread object. you may call any methods you'd like on it, including countStackFrames.

11:23 raphinou_: my finger trees still have high constant costs, but they're O(log n) for removal.

11:25 raphinou_: Chouser: bookmarking them for later, will use vector for now

11:26 crios: ah ok Chouser, I didn't notice that currentThread returns "this" thread

11:31 If currentThread didn't exist, it would be not possible to call that instance method? "this" is not allowed, correct?

11:36 Chouser: even in Java 'this' doesn't mean "this thread"

11:37 but yes, in Clojure 'this' is only special inside 'proxy' forms, otherwise it's just another identifier like i or foo

11:39 crios: about "this" I know it :), I was meaning that without the currentThread reference, I cannot access any instance method inside an anonymous function which is given as Runnable argument to the Thread constructor

11:40 "any instance method" of the current thread

11:40 raphinou_: is this the best way to insert into an array at a certain index? (let [ [pre post] (split-at index sections)] (vec (concat pre [new-item] post))))

11:41 I need a vector returned, hence the call to vec

11:41 Chouser: right, again it's the same as Java. The Thread class could pass its own instance as an parameter to the method it calls, but it doesn't and Runnable doesn't even have a signature to allow it. So in both Clojure and Java you must use the currentThread static method.

11:42 raphinou_: no, you can use assoc on a vector. it's fast. And be careful not to call them arrays -- array implies Java array.

11:42 crios: ok

11:42 Chouser: ,(assoc '[a b c d e] 2 'X)

11:42 clojurebot: [a b X d e]

11:43 raphinou_: ok, thx! I meant vector, really :-)

11:45 Chouser: actually I need to insert, not replace ;)

11:46 Chouser: raphinou_: oh. :-( indeed. what you wrote is fine.

11:46 raphinou_: it might be slightly faster to conj onto a subvec.

11:47 raphinou_: but I need to concat anyway, no?

11:47 Chouser: (apply conj (subvec v 0 i) new-item (subvec v i))

11:47 raphinou_: so I would have a conj + a concat

11:48 lisppaste8: crios pasted "untitled" at http://paste.lisp.org/display/87168

11:49 Chouser: hm, conj doesn't use transients yet.

11:49 raphinou_: are we concerned about speed here? how large are these vectors?

11:49 raphinou_: no concern for speed

11:50 small vectors, to be used in a web application

11:50 Chouser: then vec and concat is fine, or apply conj

11:50 raphinou_: apply conj I didn't think of!

11:50 Chouser: your vec/concat is probably clearer in its meaning

11:51 crios: about the code in http://paste.lisp.org/display/87168, it does not work correctly, I think it is related with the evaluation time of sendMsgFor ?

11:53 Chouser: crios: the Thread constructor expects a Runnable. Instead you're calling sendMsgFor and passing its return value (I'm guessing nil) to Thread.

11:53 crios: try (Thread. #(sendMsgFor 11 500 "ping"))

11:55 crios: that works. mmm I'm was sure of having read that a clojure function implements Runnable

11:55 Chouser: it does

11:55 crios: ah I was passing its return value

11:55 Chouser: yes

11:56 crios: time to check the # escape :)

11:57 Fossi: i though LazyPersistentVector etc implement Collection?

11:58 Chouser: Fossi: huh! that might be bug.

11:59 Fossi: how do i get a collection from them?

11:59 Chousuke: ,(ancestors clojure.lang.LazilyPersistentVector)

11:59 clojurebot: #{java.lang.Iterable java.lang.Runnable clojure.lang.IPersistentVector java.util.Collection clojure.lang.AFn clojure.lang.Indexed clojure.lang.Seqable clojure.lang.IFn clojure.lang.APersistentVector java.util.List clojure.lang.IMeta clojure.lang.Streamable java.lang.Object java.util.concurrent.Callable clojure.lang.IObj clojure.lang.Counted java.util.RandomAccess clojure.lang.Obj clojure.lang.Sequential :clojure.contrib.g

11:59 Chousuke: it is a Collection. :/

12:00 Chouser: Chousuke: what's wrong with my clojure!? (supers clojure.lang.LazilyPersistentVector) ==> #{java.lang.Object}

12:00 Chousuke: Chouser: try ancestors? :P

12:00 ,(supers clojure.lang.LazilyPersistentVector)

12:00 clojurebot: #{java.lang.Iterable java.lang.Runnable clojure.lang.IPersistentVector java.util.Collection clojure.lang.AFn clojure.lang.Indexed clojure.lang.Seqable clojure.lang.IFn clojure.lang.APersistentVector java.util.List clojure.lang.IMeta clojure.lang.Streamable java.lang.Object java.util.concurrent.Callable clojure.lang.IObj clojure.lang.Counted java.util.RandomAccess clojure.lang.Obj clojure.lang.Sequential clojure.lang.Rever

12:00 Chousuke: hm

12:01 okay, something is wrong with your clojure :)

12:01 Chouser: same

12:01 yeah

12:01 Chousuke: I'll check mine.

12:01 hm. it's broken too

12:04 Chouser: oh!

12:04 it's gone

12:04 ,(class [1 2 3])

12:04 Chousuke: oh. haha

12:04 clojurebot: clojure.lang.LazilyPersistentVector

12:04 Chouser: I just get a PersistentVector here

12:04 Chousuke: Clojurebot must be running an old version

12:04 ,(doc transient)

12:04 clojurebot: Gabh mo leithscéal?

12:04 Chousuke: I think it went away with transients.

12:04 Chouser: yeah

12:06 crios: Chouser so by adding a # I warn the clojure reader that I'm creating a (anonymous) function, so it must not evaluate and execute the next parentheses... correct?

12:07 Chouser: crios: yes

12:07 Chousuke: crios: that's a bit contrived way of putting it.

12:08 crios: the reader doesn't evaluate anything in the first place (except #=(foo) forms)

12:09 crios: what happens is that #( is reader magick and instead of outputting just the list '(yourfunc args here), the reader instead outputs the list '(fn [] (yourfunc args here))

12:10 and when the program gets around to evaluating that, it of course produces an anonymous function

12:10 -it

12:10 er

12:11 never mind :D

12:11 crios: it now makes much more sense, thank you

12:12 Chousuke: the actual implementation of # is a bit more complicated because it has to handle %1 %& etc.

12:12 #( I mean.

12:14 I think my #() implementation is still a bit buggy.

12:14 crios: ?

12:14 Chousuke: I think it discards any metadata you attach to the % parameters :/

12:15 crios: I have a mostly-working reader written in Clojure and should find the time to finish it :P

12:15 crios: :)

12:15 come on ;)

12:15 Chousuke: but most of the fun work is over and suddently I'm feeling much less motivated

12:15 crios: just for my stupid question?

12:15 questions?

12:16 Chousuke: hm?

12:17 crios: [ ehm - what does it mean 'hm' ? ]

12:18 Chousuke: I mean I didn't quite understand you :P

12:20 crios: ah :) - I was thinking that my stupid questions make you "feeling much less motivated" eheh

12:21 by the way do you use some ANTLR grammar in your reader?

12:22 Chousuke: no.

12:22 it's the simplest possible reader :P

12:22 raphinou_: I need to go. Bye!

12:23 Chousuke: crios: http://github.com/Chousuke/clojure/commits/clojure-reader ... I cleaned up the commit history a bit some days ago :)

12:25 crios: by raphinou_

12:25 bye

12:30 Is reader.clj currently used by the REPL?

12:31 Chousuke: no.

12:31 the current reader is written in java

12:32 crios: are you thinking of replace it?

12:33 Chousuke: maybe.

12:33 If I can make this reader good enough :)

12:34 crios: and why should be better a Clojure reader, instead of a Java one? (besides the former is written by you ;-)

12:35 Chousuke: crios: because it's in Clojure :)

12:37 crios: :)

12:37 well, good job.

12:37 i have to go

12:37 bye

12:56 grigna-ak: where can I find documentation for what was once clojure.contrib.template ? (btw github has been down, so I couldn't find it in there)

13:04 danlarkin: cgrand: ping

13:06 cgrand: danlarkin: pong!

13:06 danlarkin: I have a question about PersistentHashMap2 -- your commit from august 10th

13:07 august 10th was when it replaced PersistentHashMap, anyway

13:07 cgrand: yes?

13:07 danlarkin: what was the impetus behind that refactor?

13:09 cgrand: better memory usage and better "transient" perfs -- regular perfs are slightly better

13:12 danlarkin: clojure-json didn't pass its tests on master so I did a git bisect on clojure and it was that commit that breaks it

13:13 cgrand: which test(s)?

13:16 danlarkin: cgrand: the "pass1" test in clojure-json's test.clj directory. It's a big complex json file from json.org

13:25 cgrand: danlarkin: ok, looking at it

13:26 danlarkin: cgrand: thanks

13:38 stuartsierra: grigna-ak: clojure.contrib.template became clojure.template, but most of its functionality was removed.

13:38 The clojure.template sources are at src/clj/clojure/template.clj in the Clojure distribution.

13:39 Chousuke: hmm, this looks promising. I changed my reader to use a character sequence instead of a line sequence, and it still works.

13:39 grigna-ak: stuartsierra: thanks

13:40 blast github still under ddos

13:40 Chousuke: I should be able to use a PushbackReader as the source now without worrying about consuming stuff than necessary :/

13:40 +more

13:53 ericthorsen: Is this a bug?

13:53 (def m {:a 1 :a 2 :a 45})

13:53 has 3 items in it

13:53 I would have thought it would just have 1 :a ?

13:54 Chousuke: hm

13:54 ,(count {:a 1 :a 2 :a 3})

13:54 clojurebot: 3

13:54 Chousuke: oops

13:54 stuartsierra: That's been ruled not-a-bug, it's an artifact of how ArrayMaps are implemented.

13:55 Chousuke: then again, I think such a literal is illegal anyway :P

13:55 stuartsierra: The compiler accepts it, but the result is undefined.

13:55 triyo: java.util.HashMap implements java.io.Serializable interface. How come, as far as I can tell, Clojure's map doesn't implement java.io.Serializable?

13:56 hiredman: ,(ancestors (class (hash-map)))

13:56 clojurebot: #{java.lang.Iterable clojure.lang.APersistentMap java.lang.Runnable clojure.lang.AFn clojure.lang.Seqable clojure.lang.IFn clojure.lang.IMeta java.lang.Object clojure.lang.IPersistentMap java.util.concurrent.Callable clojure.lang.IObj clojure.lang.Counted clojure.lang.Obj java.util.Map :clojure.contrib.generic/any java.io.Serializable clojure.lang.Associative clojure.lang.IPersistentCollection}

13:56 hiredman: ^- no HashMap

13:56 triyo: hmm

13:56 ericthorsen: stuartsierra: I see...hash-map and the like do the right thing when there are key dups...just surprised me

13:56 stuartsierra: me too, first time I discovered it

13:57 ericthorsen: stuartsierra: do you have a link to that discussion by any change? It still feels wrong

13:57 chance

13:58 stuartsierra: don't remember

13:58 I think it was on IRC

13:58 ericthorsen: stuartsierra: I'll fish around for it...thanks

14:02 triyo: hiredman: thanks I see now that hash-map does implement the Serializable interface however I still have a problem. I am trying to use memcached to cache a hashmap. It should work if it is a serializable object however I still get an IllegalArgumentException "Non-serializable object".

14:03 hiredman: ~ticket search Serializable

14:03 clojurebot: ("#174: Make c.l.Keyword Serializable" "#64: GC Issue 61: \t Make Clojure datatype Java Serializable" "#174: Make c.l.Keyword Serializable" "#64: GC Issue 61: \t Make Clojure datatype Java Serializable" "#98: GC Issue 94: \t (ancestors ClassName) does not include tag ancestors of ClassName's superclasses ")

14:04 hiredman: ~ticket #64

14:04 clojurebot: {:url http://tinyurl.com/kv5v3t, :summary "GC Issue 61: Make Clojure datatype Java Serializable", :status :new, :priority :low, :created-on "2009-06-17T19:38:52+00:00"}

14:17 technomancy: it doesn't look like there's a way to shut down a single agent, is there?

14:17 just the whole thread pool

14:18 do they get shut down when GC'd?

14:19 hiredman: eh?

14:20 technomancy: say you've got a rogue agent that's busy doing something you don't want it to do anymore.

14:20 hiredman: are you asking if they continue to run after they have been deallocated?

14:20 technomancy: I guess a running agent would never get GC'd; that doesn't make sense

14:21 hiredman: well, the running action does have a reference to the agent

14:21 technomancy: I'd like to stop it from the sending context

14:21 I could stop the whole agent thread pool too, but it doesn't look like there's a way to start it back up again once you do.

14:21 which is weird

14:22 hiredman: you can cancel a future, I believe

14:23 ,(map #(.getName %) (.getMethods (class (future nil))))

14:23 clojurebot: ("__initClojureFnMappings" "__updateClojureFnMappings" "__getClojureFnMappings" "get" "get" "hashCode" "clone" "equals" "toString" "deref" "isDone" "cancel" "isCancelled" "wait" "wait" "wait" "getClass" "notify" "notifyAll")

14:30 technomancy: so even with the ability to get at *agent* from within the running action, you can't stop it.

14:33 triyo: hiredman: patch in #174 fixes the problem. Now that Keyword implements Serializable, I can serialize maps that have keyword objects. thx for link

14:41 I am trying to understand when exactly I should use the set! . What I understand is that set! changes mutable state. But then I see this example in the docs: (doto (new java.util.HashMap) (put "a" 1) (put "b" 2)) that also change mutable state yet it doesn't use the set! ?

14:44 wtetzner: set! is for changing thread-locally bound vars

14:44 that example is just calling java

14:44 not clojure functions

14:47 triyo: ok, now I get it. asp. the thread local part. thx

15:11 LauJensen: What do you guys consider the main advantage of Clojure non-distributed approach to concurrency ?

15:13 * Chouser declines to write LauJensen's next blog post for him.

15:13 Chouser: :-)

15:14 LauJensen: hehe :)

15:14 ...but I promised them :)

15:16 stuartsierra: LauJensen: multi-core is the future

15:16 LauJensen: stuartsierra: so? the distributed model is also well suited for mc

15:17 stuartsierra: but less efficient than share-memory multi-threading

15:17 LauJensen: Isn't that theoretically, it's basically the same stuff under the hood isn't it ?

15:18 stuartsierra: well, it's all theoretical now, since no one's building 1000-core machines yet

15:19 Chousuke: reality often gets in the way of theory :/

15:20 LauJensen: hehe

15:20 stuartsierra: yeah, it's going to depend a lot on the hardware/software implementations

15:20 LauJensen: You guys should get into making t-shirts :)

15:20 Chousuke: mostly because the theories fail to take into account everything that happens not directly related to the phenomenon one is theorising about.

15:25 LauJensen: I think I'll do the Sleeping barber problem in Scala + Clojure, that should be grounds for comparison

15:34 Anniepoo: just on for a moment, but had to laugh - Amazon's spam 'you might also like' email to me features 'programming scala'

15:34 Chouser: well... you might!

15:34 :-)

15:34 Anniepoo: LOL

15:35 Chouser: once clojure-in-clojure is done, we can have a back end that emits Scala code.

15:35 Anniepoo: lol

15:35 LauJensen: Chouser, did you know that Scala is already implemented in Scala?

15:36 Chouser: I didn't.

15:36 LauJensen: They beat you to it man

15:36 Chouser: so why do they only have the one back-end?

15:36 I know they sorta support CLR

15:37 LauJensen: I don't know. And also... I should say, most of the info I got from IRC was pulled as soon as I posted the article

15:37 So, some people may have spoke too soon, I don't know

15:37 Chouser: pulled?

15:38 LauJensen: 'retracted'

15:38 Chouser: how do you retract something from IRC?

15:38 LauJensen: You don't, but they asked me to remove it from the website

15:39 Chouser: huh

15:54 technomancy: Anniepoo: which "Programming Scala", that's the question?

15:54 Anniepoo: some new one from Oreilly. That was it's name

15:54 (title)

15:58 cgrand: danlarkin: ok, fixed

15:59 danlarkin: cgrand: wow, nice!

15:59 cgrand: where can I see it?

16:01 hiredman: LauJensen: that blog post just seems to sow enmity between scala and clojure

16:01 cgrand: ,(count (reduce conj (hash-map) (for [i (range 30)] [i nil])))

16:01 clojurebot: 30

16:01 LauJensen: hiredman: Which one?

16:02 cgrand: danlarkin: here http://github.com/cgrand/clojure/commit/40a0cd947b6eb03396756566683841878f480e8a I'll create an issue later

16:03 hiredman: LauJensen: there is another one?

16:03 danlarkin: cgrand: and a test case too I hope :-)

16:03 LauJensen: hiredman: There's one brewing

16:03 But let's take this in private

16:03 hiredman:

16:03 I'd rather not

16:06 danlarkin: cgrand: well that's awesome, I'm glad you were able to fix it, thanks again

16:21 cgrand: ,*clojure-version*

16:21 clojurebot: {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "alpha"}

16:22 lpetit: ,(clojure-version)

16:22 clojurebot: "1.1.0-alpha-SNAPSHOT"

16:22 Chouser: it wouldn't always be completely useless to include the git SHA1 in that

16:23 oh, nm. :-/

16:23 lpetit: :)

16:23 would be an interesting exercise :)

16:23 cgrand: ,(resolve 'transient)

16:23 clojurebot: nil

16:24 Chouser: well, you'd have to be careful to never include the SHA1 if the working copy were dirty

16:24 otherwise you might have a version claiming to be something it's not, which would be worse than useless.

16:25 lpetit: You mean the SHA1 of the future commit object ,

16:25 clojurebot: lpetit: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff

16:25 lpetit: ?

16:25 cgrand: 1.1 pre transient that's why (count (reduce conj (hash-map) (for [i (range 30)] [i nil]))) returns 30...

16:25 danlarkin: this is my test case (= (count (reduce conj (hash-map) (for [i (range 30)] [i nil]))) 30)

16:26 Chouser: even if that were easy at 'ant' time, it would still be rediculously hard -- what if someone tweaked their core.clj and re-loaded it? still misleading without any build process getting a chance to turn off the SHA1

16:26 ridiculously

16:28 lpetit: Not sure. Either you trust the source of what you're getting, either you don't trust. Having the wrong SHA1 in a lib you get from 3rd party may be the less dangerous security hole :)

16:30 triyo: I used elpa to install latest ver of clojure in my emacs env. How do I go about keeping that latest ver of clojure up to date?

16:44 hmm never mind :)

18:13 something: I'm opening up a clojure repl in my clojure app, I want the repl to change the namespace like execute in-ns, is there a way to do that?

18:36 hiredman: hmmm

19:55 technomancy: (:use [clojure.test]) ; <= feels good to finally be able to type that

20:02 (doc with-ns)

20:02 clojurebot: "clojure.contrib.with-ns/with-ns;[[ns & body]]; Evaluates body in another namespace. ns is either a namespace object or a symbol. This makes it possible to define functions in namespaces other than the current one."

20:04 technomancy: I'm kind of tired of copying my delete-file-recursively function around to all my different projects... should it go in contrib?

20:09 obviously it belongs in the JDK, but I don't think that's going to fly

20:25 Chouser: technomancy: sounds reasonable to me. is there a namespace already where it would fit?

20:26 technomancy: Chouser: that's the problem really

20:26 there's a bunch of file-related stuff under java-utils that could be spun out into file-utils, but I feel uncomfortable about moving stuff like that

20:34 kanak: has anyone here tried doing Norvig's PAIP in clojure?

20:37 kunjan: that is an awesome project. why dont you write a blog about it?

20:37 clojurebot: http://clojure.org/rationale

23:52 jamesp: Hi guys, Could you by chance help me out with a java interop question? I'm afraid I not written much java.

23:52 hiredman: ask away

23:53 jamesp: I'm attempting to use a library for handling asynchronous events. The last call in the example java code is:

23:53 Object object = new Object(); synchronized (object) { object.wait(); }

23:54 hiredman: :(

23:54 jamesp: How on earth do I replicate that in clojure code?

23:54 hiredman: where is the example?

23:57 jamesp: Let me see if there is an example online

Logging service provided by n01se.net