#clojure log - Dec 18 2008

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

0:00 triddell: ok, I'll try that

0:01 arohner: triddell: the html function in compojure is very simple. (html [:foo [:bar 3]]) => <foo><bar>3</bar></foo>

0:01 it only returns strings

0:01 you can easily call it multiple times

0:02 triddell: yes, but inside the function you can run other functions right?

0:02 arohner: definitely

0:03 (html [:body (foo) (bar)])

0:29 bradbev: Is LispPaste working?

0:30 I'm trying to use JNA & gen-interface. I am compiling using ANT. My code basically boils down to

0:31 (gen-interface

0:31 :name libwinmm

0:31 :extends [Library]

0:31 :methods [['waveOutSetVolume [Integer Integer] Integer]])

0:31 (def winmm (. Native (loadLibrary "winmm" libwinmm)))

0:31 however, at compile time libwinmm is not defined

0:33 how do I get the Class object that gen-interface created?

0:35 arohner: my familiarity with JNA comes only from reading examples, but how does libwinmm get defined?

0:35 bradbev: in is the :name option to gen-interface

0:35 I have a libwinmm.class file in my classes dir

0:36 arohner: oh, sorry

0:36 bradbev: np

0:38 ah - after I gen-interface I need to then import that class :)

0:38 arohner: that makes sense :-)

0:39 bradbev: er, forget that - compiled in the wrong window :(

0:50 arohner: bradbev: did you try using load rather than import?

0:50 bradbev: um, no

0:51 load is looking for Clojure code - foo.clj or foo__init.class

0:52 Nafai: Has anyone tried to use the new AOT compiler to use code to run on the Android platform?

0:56 arohner: bradbev: is your classes directory in your class path?

0:56 bradbev: arohner: yes

0:56 arohner: sorry, I've only played with gen-class, and that was a little while ago

0:58 bradbev: were you using the gen'd classes from java or from Clojure?

1:00 arohner: from clojure

1:01 I was loading them without the original source

1:02 what is the error you are getting?

1:04 bradbev: import is failing to find the class. [java] java.lang.NoClassDefFoundError: java/lang/Library (server.clj:35) I'm building with ANT, so the callstack is silly

1:08 arohner: try using the fully qualified name for Library

1:09 bradbev: arohner: that's the funny thing. what should the fully qualified library name be?

1:10 I'm a bit of a neophyte

1:10 arohner: well, you say :extends [Library]. That's looking for a specific java class name

1:11 similar to saying in java

1:11 class libwinmm : Library

1:11 bradbev: yes, Library's full name is com.sun.jna.Library

1:12 arohner: so use that in the extends line

1:12 I think I remember seeing a bug that gen-class does not pay attention to imports yet

1:12 bradbev: oh crap, forgot that needed to be fully qualed

1:12 woohoo

1:12 that's it - awesome

1:12 arohner: great

1:13 bradbev: well - it compiles at least :)

1:13 arohner: a good start :-)

2:59 Lau_of_DK: Top of the morning gents

3:00 fffej: hi - quick question - am I going mad or is there no function is the standard library to get the length of a sequence?

3:00 Lau_of_DK: (doc count)

3:00 clojurebot: Returns the number of items in the collection. (count nil) returns 0. Also works on strings, arrays, and Java Collections and Maps; arglists ([coll])

3:00 Lau_of_DK: fffej: How about count ?

3:01 fffej: count looks good to me, was expecting to see it on the sequences api page on the web :)

3:01 and I've been searching for size / length etc!

3:01 thanks!

3:03 Lau_of_DK: Youre not the first one to ask that question... this week :)

3:10 hiredman: ,(count "foo")

3:10 clojurebot: 3

3:10 hiredman: ,(println "hello world")

3:10 clojurebot: hello world

3:10 hiredman: *tada*

3:11 don't break it

3:28 what is the best way to control which namespace (eval ...) evals in

3:42 ,(println *ns*)

3:42 clojurebot: #<Namespace foo>

3:42 hiredman: guess that works

3:52 Lau_of_DK: ,(println "/part #clojure")

3:52 clojurebot: /part #clojure

3:52 Lau_of_DK: :)

3:52 One of these days I'll get it :)

3:52 hiredman: *snort*

3:52 yeah

3:52 I bet you will, I am pretty sloppy

3:52 Lau_of_DK: Is it running on a hosted system somewhere, or you got it at home?

3:53 hiredman: it is running on a webserver somewhere in sumner, wa

3:53 Lau_of_DK: ok, s� crashing it is not really a good idea

3:54 hiredman: *shrug*

3:54 the webserver has a tendency to crash any time it rains anyway

3:54 Lau_of_DK: not good

3:55 I actually found a pretty great hosting service where you could get a virtual server for next to no money

3:55 hiredman: *shrug*

3:55 Lau_of_DK: ,(doseq [i (range 5)] (println i))

3:55 clojurebot: 0 1 2 3 4

3:56 Lau_of_DK: ,(println (System/getProperty "java.class.path"))

3:56 hiredman: right now it is just running in a jvm sandbox

3:56 I should do some filtering of "naughty" forms

3:56 Lau_of_DK: How did you set it up ?

3:57 hiredman: clojurebot: sandbox?

3:57 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

3:57 Lau_of_DK: perfect

3:58 ,(println (iterate inc 1))

3:58 hiredman: hmm

3:58 Lau_of_DK: ,(println "still here")

3:58 clojurebot: still here

3:58 hiredman: cool, I kind of expected that to break it

3:59 whoop

3:59 s

3:59 hah

4:00 that does run in the sandbox, but it blows the heap, so nothing gets sent to the channel

4:01 the latest clojurebot, with the sandbox stuff is pushed out

4:01 clojurebot: where are you?

4:01 clojurebot: http://gist.github.com/27733

4:02 Lau_of_DK: hiredman: So it blows the heap but the Bot still runs ?

4:02 hiredman: yeah

4:02 Lau_of_DK: It threads out the evals ?

4:03 hiredman: guess so

4:03 Lau_of_DK: hehe

4:03 pretty robust

4:03 hiredman: OutOfMemoryError: Java heap space

4:04 Lau_of_DK: ,(map #(println (iterate inc %)) (iterate inc 3))

4:04 ,(println "still here")

4:04 clojurebot: still here

4:04 Lau_of_DK: hehe, thats cool

4:04 and he even held the tension there for about 10 secs

4:05 hiredman: blew the heap again

4:06 ,(.getContents (java.io.URL. "http://google.com"))

4:07 I guess I should catch exceptions and throw an error

4:08 Lau_of_DK: Which class does getContents belong do ?

4:08 Here the URL is in Java.net

4:08 hiredman: I maybe misremebering

4:08 yeah

4:08 net

4:09 Lau_of_DK: Where did you find getContents ?

4:09 hiredman: java.net.URL

4:10 getContent

4:10 no s

4:11 Lau_of_DK: ,(.getContent (java.net.URL. "http://www.google.dk"))

4:11 ,(println (.getContent (java.net.URL. "http://www.google.dk")))

4:12 ,(print (/ 2 0))

4:12 clojurebot: where are you?

4:12 clojurebot: http://gist.github.com/27733

4:24 hiredman: ,(java.util.Date.)

4:24 clojurebot: Thu Dec 18 01:24:10 PST 2008

4:29 tsdh: Hi. I'm pretty new to clorjure and play a bit with it now. I want to access a java class, so I did "(ns jg (:import (de.uni_koblenz.jgralab JGraLab)))" and am now in namespace jg at the REPL. What's the correct way to access the static member JGraLab.version now? I tried "JGraLab/version" but got "java.lang.Exception: No such namespace: JGraLab (NO_SOURCE_FILE:0)".

4:29 hiredman: what does JGraLab return at the repl?

4:31 tsdh: de.uni_koblenz.jgralab.JGraLab

4:31 hiredman: hmmm

4:31 nagnals: can I see the implementation of a function from the interactive prompt?

4:32 hiredman: nagnals: there is a function in contrib somewhere for that

4:32 never used it, not sure where it is

4:32 repl utils or something

4:32 nagnals: when writing a function like sort or reversed, do i have to use multimethods if i want them to return the same sort as they were passed?

4:32 hiredman: tsdh: what exactly did you type at the prompt to get the no such namespace error?

4:32 nagnals: and is it possible to cons to a vector and keep it a vector?

4:33 hiredman: nagnals: use conj

4:33 ,(conj [] :a :b)

4:33 clojurebot: [:a :b]

4:33 hiredman: ,(conj [:a] :b)

4:33 clojurebot: [:a :b]

4:33 hiredman: etc

4:33 tsdh: hiredman: JGraLab/version RET (and version is a public static String in JGraLab)

4:33 hiredman: tsdh: parens

4:33 maybe

4:34 tsdh: hiredman: No parens

4:34 hiredman: that wasn't a question

4:34 are you running a recent svn?

4:35 tsdh: hiredman: Sorry. ;-) With parens I get "java.lang.NoSuchFieldException: version (NO_SOURCE_FILE:1)" and now I see that the error sits in front of the monitor. version is private...

4:35 nagnals: hiredman: yes but i want to cons to the beginning of the list/vector, not the end

4:35 hiredman: nagnals: vectors grow at the end

4:35 lists at the begining

4:36 ,(conj `(:a) :b)

4:36 clojurebot: (:b :a)

4:36 nagnals: yes

4:37 hiredman: ,(println "Yes.")

4:37 clojurebot: Yes.

4:39 hiredman: http://clojure.org/sequences <-- the text blob at the beginning

4:47 tsdh: Is it possible to redirect System.out to the repl?

4:48 hiredman: uh

4:48 do you mean out -> in

4:48 because System.out should print out at the repl

4:49 (println "foo")

4:51 tsdh: That works, but (JGraLab/main (make-array String 0)), which only prints the version and some other infos using System.out.println() didn't produce any visible output.

4:51 nagnals: can I hide a function in a file or namespace?

4:52 hiredman: (doc defn-)

4:52 clojurebot: same as defn, yielding non-public def; arglists ([name & decls])

4:53 hiredman: tsdh: are you sure it is outputing anything?

4:54 tsdh: hiredman: Yes, at least when run with java.

4:55 hiredman: With (JGraLab/main (make-array String 0)) it returns nil, but no output.

4:56 nagnals: is slurp a common name to use to read in files, ie not just on Clojure but it is a general saying in programming?

4:56 hiredman: *shrug*

4:57 dhaya: tsdh: are you using the repl in emacs?

4:58 tsdh: dhaya: Yes, with slime and swank-clojure.

4:58 nagnals: hiredman: ok but defn- defs so i can call it from the prompt but I cant call it if i import a file o use load-file?

4:58 dhaya: tsdh: check the *inferior-lisp* buffer.

4:59 tsdh: dhaya: Oh, indeed, there it is.

4:59 hiredman: slangan: I believe it stops you from calling the function from outside the namespace it is defined in

5:00 I have yet to use it for anything

5:00 clojurebot: hiredman is also lazy

5:00 clojurebot: You don't have to tell me twice.

5:02 slangan: yeah because if i put it in user.clj i can still call it

5:05 hiredman: namespaces ~= java pacakages, defn- is like a private method

5:08 er

5:08 not private

5:08 protected

5:16 slangan: would it be possible to run clojure on a cellphone that can run the JVM? or would the dynamicy create to much overhead at runtime? or does AOT-compilation solve that so I can create execs from clojure-scripts?

5:17 Android use the Dalvik Vm, that means Cloure can't be run on it right?

5:17 hiredman: it depends

5:17 it is a topic of on going interest

5:18 a lot of java phones really have the j2me not full java

5:19 I think scala is running on android

5:19 clojure uses a dynamic class loader deal (sometimes) which the phones and also applets don't like

5:27 slangan: hmm, oh well im writing a web/mobile app i can have the webapp in clojure and write the mobile part in java. no biggie.

5:28 if i want to host a webapp for free, where should i do it?

5:29 hiredman: uh

5:29 there are at least two frameworks for doing web stuff in clojure

5:30 clojurebot: webjure

5:30 clojurebot: webjure is http://code.google.com/p/webjure/

5:30 hiredman: clojurebot: compojure

5:30 clojurebot: compojure is http://github.com/weavejester/compojure/tree/master

5:31 AWizzArd: Moin moin

5:32 hiredman: ,(println "Hello")

5:32 clojurebot: Hello

5:35 AWizzArd: clojurebot: max people

5:35 clojurebot: max people is 113

5:35 AWizzArd: uh, yesterday it was 116

5:35 hiredman: yeah, stuff happened

5:35 AWizzArd: clojurebot: max people is 116

5:35 clojurebot: Ik begrijp

5:35 hiredman: the dumpdicts agent was running

5:35 are

5:35 was not running

5:36 so some data was lost when I restarted the bot

5:36 AWizzArd: ic

5:36 clojurebot: max people

5:36 clojurebot: max people is 116

5:36 AWizzArd: danke

5:36 hiredman: but now the dumpdicts agent starts its self

5:36 so I won't forget to run it

5:36 but sandboxing works now!

5:37 ,(conj {:a} :b)

5:37 er

5:37 it was

5:37 damn it

5:37 AWizzArd: ,(format "C:\")

5:39 hiredman: something broke it

5:41 ,(println :foo)

5:41 clojurebot: :foo

5:42 hiredman: ,(format)

5:42 clojurebot: :DENIED

5:45 Lau_of_DK: ,(map #(print %) (range 5000))

5:45 clojurebot: (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil

5:45 AWizzArd: ,(eval 1)

5:45 clojurebot: 1

5:46 hiredman: btw

5:47 ,(println *ns*)

5:47 clojurebot: #<Namespace foo>

5:47 AWizzArd: ,((resolve (symbol "format")) "Hello Moon")

5:47 clojurebot: Hello Moon

5:47 AWizzArd: (format "Hello World")

5:48 hiredman: (doc format)

5:48 clojurebot: Formats a string using java.lang.String.format, see java.util.Formatter for format string syntax; arglists ([fmt & args])

5:48 AWizzArd: ,(format "Hello World")

5:48 clojurebot: Hello World

5:48 hiredman: says :DENIED for an exception

5:49 AWizzArd: ,(Thread/sleep 5000)

5:49 ,(format "Hello World")

5:49 clojurebot: Hello World

5:50 hiredman: I need to filter out stuff like Thread, recur, etc

5:51 AWizzArd: ,(.getCanonicalPath (java.io.File. "."))

5:51 clojurebot: :DENIED

5:51 hiredman: no io

5:51 AWizzArd: good

5:51 hiredman: clojurebot: sandbox

5:51 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

5:54 hiredman: ,(def bedtime (Date.))

5:54 clojurebot: #'foo/bedtime

5:54 hiredman: ,bedtime

5:55 hmm

5:55 ,(str bedtime)

5:55 clojurebot: Thu Dec 18 02:54:46 PST 2008

6:08 Chousuke: hiredman: maybe you should disallow def; it should be rather easy to cause clojurebot to run out of memory if I can def arbitrary stuff.

6:09 AWizzArd: Could would be to (send-off) every form entered here in chat into its own thread, with a timeout of max 5 secs.

6:09 So, small calculations would be allowed.

6:11 and every 3 minutes without any def should clear the namespace

6:11 Chousuke: ,(defn hello [name] (println "Hi " (str name) ", welcome to #clojure!"))

6:11 clojurebot: #'foo/hello

6:11 Chousuke: ,(hello 'test-person)

6:11 clojurebot: Hi test-person , welcome to #clojure!

6:11 Chousuke: hm. too manu spaces.

6:12 AWizzArd: this hello could be auto-deleted after 3 minutes without input

6:12 Chousuke: sometimes you want to keep the stuff though

6:14 leafw: is there any built-in efficient way to get a list of repeated entries in a vector?

6:15 Chousuke: ,(defn hello [name] (println "Hi" (str name ",") "welcome to #clojure!"))

6:15 clojurebot: #'foo/hello

6:15 AWizzArd: hiredman: something like (doseq [obj (ns-interns 'your.namespace)] (ns-unmap obj))

6:15 ,*ns*

6:15 Chousuke: leafw: not into a vector, but you can get a sequence.

6:15 leafw: that would do

6:15 AWizzArd: ,(print *ns*)

6:15 clojurebot: #<Namespace foo>

6:15 leafw: can only think of this: (reduce #(conj %1 %2) #{} [1 2 3 4 4 4 3 3])

6:15 AWizzArd: ,(ns-interns 'foo)

6:15 leafw: which gives me the non-repeated ...

6:15 clojurebot: {bedtime #'foo/bedtime, g #'foo/g, hello #'foo/hello}

6:16 AWizzArd: ,(ns-unmap 'foo 'hello)

6:16 ,(ns-interns 'foo)

6:16 clojurebot: {bedtime #'foo/bedtime, g #'foo/g}

6:17 AWizzArd: hiredman: in my above suggestion I forgot the namespace argument to (ns-unmap ...)

6:18 Chousuke: leafw: oh, I misunderstood your question. hmm

6:19 leafw: I would like to count the repeated entries, really

6:21 AWizzArd: leafw: what do you know about the structure of this vector? Is it sorted?

6:21 or could it be [1 2 3 1 2 3 1 2 3]?

6:21 hiredman: Chousuke: *shrug*

6:22 I can just restart it

6:22 leafw: not sorted

6:22 a list of random integers

6:22 AWizzArd: leafw: maybe then simply (- (count coll) (count (set coll)))

6:23 leafw: aha, turning a collection into a set ..

6:23 AWizzArd: obviously it's not a highly performant solution

6:23 Chousuke: ,g

6:23 hiredman: Chousuke: needs ,(

6:23 leafw: thanks AWizzArd

6:24 Chousuke: ,(eval g)

6:24 clojurebot: foo$g__718@a6cbf7

6:24 Chousuke: well that doesn't tell me much :p

6:24 ,(g)

6:24 clojurebot: :DENIED

6:24 hiredman: ,(meta g)

6:24 ,(meta #'g)

6:24 clojurebot: {:ns #<Namespace foo>, :name g, :file "NO_SOURCE_FILE", :arglists ([x]), :line 0}

6:24 Chousuke: ,(doc prn)

6:24 clojurebot: ------------------------- clojure.core/prn ([& more]) Same as pr followed by (newline). Observes *flush-on-newline*

6:24 Chousuke: hmm :)

6:25 hiredman: g is identity

6:25 ,(g :x)

6:25 clojurebot: :x

6:29 AWizzArd: ,(in-ns 'user)

6:29 clojurebot: user

6:29 AWizzArd: ,(print *ns*)

6:29 clojurebot: #<Namespace foo>

6:30 AWizzArd: :-)

6:30 hiredman: it is subvertable

6:30 lisppaste8: leafw pasted "no locks" at http://paste.lisp.org/display/72339

6:30 AWizzArd: phat h@ck

6:31 leafw: that paste: some of the results indicate it worked fine, but the count of repeated entries suggests that it didn't

6:31 .. which is puzzling: dosync calls should prevent it.

6:32 if there were any repeated entries, the next available id wouldn't be 1000000.

6:33 Chousuke: hm

6:33 maybe they're skipping IDs.

6:33 leafw: the length is 1000000 as well.

6:35 it was a simple test for synchronization ... and I don't understand the contradictory results.

6:37 AWizzArd: leafw: you set next-id to the result of what the commute produces

6:37 You must not read the direct result of commute.

6:37 leafw: AWizzArd: true

6:38 AWizzArd: If you want to do this you should use alter

6:38 Chousuke: commute may return a different value than what commute eventually sets the id to it seems.

6:38 leafw: aha

6:38 ok, this makes sense

6:39 so alter would work in the same sense as commute, but return the newly added value?

6:40 AWizzArd: leafw: you want to read this thread: http://groups.google.com/group/clojure/browse_frm/thread/e575db4718c1f85/c2cb536f9500d31f?tvc=1&fwc=1

6:40 leafw: the doc says it returns the in-transaction-value of ref ...

6:41 AWizzArd: just run your code again with (let (alter ..

6:42 leafw: I'm reading the thread. I am not sure that alter garantees continuous ids ... will try now

6:42 AWizzArd: alter guarantees continous ids

6:43 leafw: great

6:43 it does. Thanks AWizzArd

6:43 AWizzArd: yup

6:43 just never read the direct result of commute

6:45 leafw: well: sometimes it may be useful. But I see that it has no place here.

6:54 AWizzArd: if you want the direct result use alter

7:00 leafw: do vectors have structural sharing?

7:31 nagnals: clojurebot: git is http://www.github.com

7:31 clojurebot: Roger.

7:31 nagnals: clojurebot: git

7:31 clojurebot: git is http://www.github.com

7:41 Chouser: leafw: yes

7:55 leafw: Chouser: I guess that was a 'yes' to "do vectors have structural sharing" ?

7:56 Chouser: yes, vectors have structural sharing.

7:59 leafw: thanks

8:01 AWizzArd: Chouser: Good morning. Do you always scroll up and read what was said since you went to bed? Or was it just an "accident" that you saw leafws question? ;-)

8:03 nagnals: how do I get the string from running time?

8:04 i playa round with geentic programming and i want to include execution in the fitnessfunction.

8:04 AWizzArd: You mean the (time) macro?

8:05 nagnals: do you do GP or GA?

8:08 If you want to catch what (time ..) reported you will have to bind *out* to your own output string stream. This is trivially done by using (with-out-str (time (+ 1 2)))

8:09 jdz: why not use the difference between start time and end time instead?

8:09 Lau_of_DK: AWizzArd: I think he usually skims the logs

8:19 nagnals: why cant errors return what row IN MY PROGRAM the error happened? it makes debugging hell

8:19 not getting that infp

8:49 slangan: hmm, perhaps a dumb question but if i have a lets say 10 variables and sometime si pass 5 of them to a function and sometimes 10, does it amke sense to use a hashmap and store them there and just pass that around instead? it just means i can pass around less variables which perhaps is a pointless win? is there any runtimepenaly of looking up stuff ina hashmap compared to just referring to a passed var?

8:49 Why can't errors return what row IN MY PROGRAM the error happened? It makes debugging hell not getting that info.

8:50 rhickey: slangan: they can

8:52 slangan: but not always?

8:52 rhickey: (.printStackTrace *e)

8:53 duck1123: slangan: if you're using the REPL, that'll mess things up

8:54 slangan: Are you doing this from the command line, or using an editor? (ie. emacs+slime)

8:54 slangan: rhickey: thats what i mean already get that but it doesnt say where in MY PROGRAM it happened?

8:55 rhickey: slangan: how did you load your program?

8:55 slangan: emacs+clojure-mode

8:55 C-c C-l

8:57 rhickey: it might have to do with the specific error, most times you'll get the line in your file, can you paste your stack trace?

8:58 lisppaste8: url

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

9:19 acieroid: ow, functions must be defined before calling it into another function

9:20 rhickey: acieroid: you can (declare foo) (defn bar [] ... foo) (defn foo [] ...)

9:20 acieroid: 'kay rhickey

9:30 Chouser: AWizzArd: most of the time I scroll back and read the log from overnight.

9:30 AWizzArd: nice :-)

9:30 Chouser: AWizzArd: ...unless I find it to be an overwhelming amount of traffic.

9:35 RSchulz: FWIW, I usually go back over the night's exchange in the morning, too. It seems traffic is picking up.

9:40 Chouser: indeed.

9:40 but I have trouble shaking the compulsion to hunt down and root out misinformation.

9:41 ...so I skim growing logs.

9:43 Chousuke: hmm

9:44 ,(def *persistent-defs* #{})

9:44 clojurebot: #'foo/*persistent-defs*

9:44 Chousuke: ,(defn clear-defs [] (binding [*persistent-defs* (into #{'clear-defs '*persistent-defs*} *persistent-defs*)] (doseq [obj (ns-interns *ns*)] (when-not (*persistent-defs* (first obj)) (ns-unmap *ns* (first obj))))))

9:44 clojurebot: #'foo/clear-defs

9:45 Chousuke: ,(ns-interns *ns*)

9:45 clojurebot: {bedtime #'foo/bedtime, status #'foo/status, clear-defs #'foo/clear-defs, g #'foo/g, *persistent-defs* #'foo/*persistent-defs*}

9:45 Chousuke: ,(clear-defs)

9:45 ,(ns-interns *ns*)

9:45 clojurebot: {clear-defs #'foo/clear-defs, *persistent-defs* #'foo/*persistent-defs*}

9:47 Chousuke: now there's at least a way to reset clojurebot if it accumulates too many global defs.

9:48 AWizzArd: exactly, good good

10:02 lisppaste8: triddell pasted "Compojure Error" at http://paste.lisp.org/display/72345

10:02 Chousuke: ,(do (defn make-persistent [sym] (assert (symbol? sym)) (def *persistent-defs* (into *persistent-defs* #{sym}))) (make-persistent 'make-persistent)

10:03 oops

10:03 hmm

10:03 ,(do (defn make-persistent [sym] (assert (symbol? sym)) (def *persistent-defs* (into *persistent-defs* #{sym}))) (make-persistent 'make-persistent))

10:03 clojurebot: #'foo/*persistent-defs*

10:03 triddell: Anyone know why I'd get "java.lang.IllegalArgumentException: Wrong number of args passed to: LazilyPersistentVector" in the above paste?

10:04 Chousuke: why is your vector wrapped in parentheses?

10:04 (doseq [value '(a b c)] ([:record value])) here, around [:record value]

10:06 triddell: ok, I can see how that isn't necessary

10:06 Chousuke: I don't think doseq is what you want, since it returns nil.

10:06 mibu: triddell: doseq is good for side-effects

10:06 Chousuke: you might want to use for

10:07 mibu: triddell: not for the functional style you're (rightly) using.

10:07 RSchulz: hiredman: Did you consider implicitly switching to a namespace equal to (or derived from to make valid) the poster's IRC nick?

10:07 triddell: ah, ok, that's the issue, I need the vectors returned to the outer function

10:07 Chousuke: or map: (map (fn [val] [:record val]) '(a b c))

10:09 mibu: or (map #(vector :record %) '(a b c))

10:10 map is so much fun.

10:11 triddell: Chousuke and mibu: this is a simplified version of what I really need to do, what I need to do is open a file for value in the seq, get a value, and then return the vector with the value... any suggestions for approaches based on that?

10:11 Chouser: ,(for [x '(a b c)] [:record val]) ; or this

10:12 clojurebot: ([:record #<core$val__3238 clojure.core$val__3238@152bdc7>] [:record #<core$val__3238 clojure.core$val__3238@152bdc7>] [:record #<core$val__3238 clojure.core$val__3238@152bdc7>])

10:12 Chouser: hm.

10:12 oh

10:12 ,(for [x '(a b c)] [:record x]) ; or this

10:12 clojurebot: ([:record a] [:record b] [:record c])

10:12 Chousuke: is for lazy?

10:12 mibu: triddell: the values are on separate lines?

10:12 Chouser: Chousuke: yes

10:13 Chousuke: triddell: you can use map or whatever with side-effects too; you'll just have to force the calculation with (doall)

10:14 mibu: triddell: I think chouser's version with for is more idiomatic than map. you should use the for version

10:14 Chousuke: I wonder how clojurebot handles infinite loops :/

10:15 triddell: actually I have to generate an xml/html block with about 3 elements (2 of them nested) for a variable amount of files

10:15 Chousuke: something like (defn foo [] (recur))

10:15 and then (foo)

10:16 Chouser: just (loop [] (recur)) should do it. poor clojurebot.

10:16 mibu: triddell: you can use line-seq for sequencing a file, if the values are on separate lines.

10:16 triddell: The files are in YAML format and I'm using jyaml

10:16 Chousuke: Chouser: I dare not try :P

10:16 Lau_of_DK: ,(loop [] (recur))

10:17 Chouser: Lau_of_DK!

10:17 Lau_of_DK: Yes sir?

10:17 That wont kill it

10:17 triddell: mibu: but I'm new to clojure too

10:17 Lau_of_DK: clojurebot: where are you ?

10:17 mibu: Lau_of_DK: thanks for satisfying our curiousity. ;-)

10:17 Chousuke: ,(prn "It's alive!")

10:17 ... it's not :)

10:17 Lau_of_DK: hmm..

10:17 Chouser: Lau_of_DK: seriously, what did you think would happen?

10:17 Lau_of_DK: I tried a few of those earlier today, and although the heap blew, it lived through it

10:18 Chouser: you've now pegged hiredman's server.

10:18 Chousuke: Lau_of_DK: recur doesn't blow the heap

10:18 Lau_of_DK: I thought it would thread it, see that the thread was gone bad and kill it

10:18 Oh thats true

10:18 Guess I made an oppsie :(

10:18 Appologies to all who loved the bot

10:19 Chousuke: well, obviously hiredman will want to protect against this somehow.

10:19 Chouser: yes.

10:19 mibu: triddell: does jyaml returns some sort of a collection?

10:19 Chousuke: I guess AWizzArd's proposition about running in a separate thread with a timeout should do.

10:19 Lau_of_DK: easy (if (not (= @name "Lau_of_DK") ...

10:19 AWizzArd: Yes

10:20 Lau_of_DK: btw shouldnt Clojure have a "!=" operator?

10:20 mibu: chousuke: he should simply write a function to check whether code terminates or not. :-)

10:20 Chousuke: mibu: yeah, simply.

10:20 Chouser: (doc not=)

10:20 duck1123: is that possible?

10:20 Lau_of_DK: Chouser: You dare taunt the bot ?

10:20 RSchulz: duck1123: No. That's the joke. It's the "Halting Problem."

10:20 mibu: duck1123: no.

10:21 Chouser: but starting a new Thread for each expression and killing it after a few seconds ought to work.

10:21 RSchulz: If this thing is going to run in the wild, here on IRC, then it's going to have to be made a lot more robust, naturally.

10:21 But it's a good start.

10:22 Chouser: You're our FP expert. Are there not some purely functional programs for which the Halting Problem is deciable?

10:22 "decidable."

10:22 duck1123: didn't think so... (require 'clojure.contrib.prescience)

10:22 RSchulz: By "some" I mean a categorical subset of arbitrary programs.

10:23 That's one of the thing ACL2 can do (for restricted or annotated Applicative Common Lisp programs, of course)

10:23 Chouser: I'm not an FP expert. I imagine some programs provably terminate.

10:23 programs with no looping or recursion, for example.

10:23 mibu: RSchulz, Chouser: only a trivial uninteresting subset.

10:23 RSchulz: I'm not so sure that's really true.

10:24 Look into ACL2.

10:24 slangan: how do I raise a specific java-exception?

10:24 RSchulz: (throw (new SpecificJavaException ...))

10:24 slangan: what is the idiomtic wya to ahndle exceptions in clojure anyway? return nil if failing?

10:25 RSchulz: If you're going to catch an exception, it's because you know how to handle it, even if you end up re-throwing when you're done with that handling.

10:25 If you don't know what to do with an exception, don't catch it.

10:25 duck1123: triddell: how well has jyaml been working for you in clojure? Looks like it might be useful when I get around to porting from my ruby code.

10:25 mibu: I think exceptions are not idiomatic to clojure. they are just a java interop mechanism.

10:25 RSchulz: Clojure renders all exceptions the equivalent of Java's "unchecked" exceptions, so you never _have_ to catch an exception.

10:26 mibu: Exception handling is something all programs potentially have to do. They're part of software, not Java or C++, though different languages call them different things and support them in different ways, of course.

10:26 Chouser: there are some places in clojure where exceptions are specifically called for.

10:26 validators, for example.

10:26 mibu: chouser: you consider FP and exceptions to be compatible?

10:27 RSchulz: I do. What would the conflict be?

10:27 slangan: what is the appropriate exception to throw for a dsl where the typre pssed doesnt match?

10:27 AWizzArd: mibu: why not?

10:27 The only thing that is not very lispy is that there are no restarts.

10:27 slangan: like :of should be passd and soemthing else is passed instead

10:27 RSchulz: One way to think of them, at least some of them, is that they reflect the response to the application of a partial function to a value outside its domain.

10:28 AWizzArd: Exceptions know only one direction: up the stack. CL can go back if needed, and Exceptions are only a subset of its Condition System.

10:28 mibu: exceptions shutter the computation. I think they're essentially a side-effect. am I wrong?

10:28 RSchulz: No. They're not side-effects.

10:29 In fact, I'd say that if your language is dynamically typed, like Clojure, then you're going to make _more_ use of exceptions if you want a robust system.

10:29 What if Clojurebot didn't catch exceptions at its top loop? It would die the first time someone submitted something erroneous.

10:29 AWizzArd: mibu: if we want to take it seriously then we must find that it is impossible to do something in computers without sideeffects. All function calls consume time. This is not true for mathematics.

10:30 mibu: Awizzard: I'm also not for pure functional programming, but I do think the side effects should be kept to the front-end of computations and not for the core.

10:30 AWizzArd: yes, sounds fair

10:31 mibu: I see java in clojure as a gateway to the real world. you use it at the edges, and completely avoid it in the middle.

10:32 Chouser: I don't think it's necessary to stand off from Java that much

10:32 slangan: if i want: (if x (do-thise) else (do-a) (do-b)), how do i do that?

10:33 arent there just a way to branch ifs with several statements for each branch?

10:33 Chouser: There are good parts of java that can and should be used in the core of an app

10:33 mibu: slangan: use do

10:33 AWizzArd: like arrays

10:33 Chousuke: slangan: (if x (foo) (do (this) (and-that)))

10:33 slangan: or you can use cond

10:34 Chouser: mibu: a couple examples off the top of my head: BlockingQueues and String

10:34 duck1123: it's too bad that many of the java libraries just don't "feel right" in clojure. Working with them is easy, but they were designed with a completely different mindset

10:34 mibu: chouser: I'm not shunning java completely as a code base. but I do try to avoid it because it's not compatible with FP and the immutability notions of clojure.

10:34 AWizzArd: duck1123: yes

10:35 Chousuke: String is, though :)

10:35 Chouser: mibu: good enough.

10:35 it's common to want to completely wrap all Java calls -- banish dots as much as possible -- but I don't think that's actually useful.

10:37 for the parts of Java that are indeed thread-safe or immutable, with sufficiently convenient APIs, why not just use them? Less code, easier to understand, better.

10:37 * mibu is not a purist. maybe an idealist.

10:37 RSchulz: slangan: Put your two (or more) else forms in a (do ...) form.

10:37 duck1123: does wrapping them cause much overhead?

10:38 RSchulz: Oops. I see you already got that answer.

10:38 duck1123: I would guess none at all. Why would there be?

10:38 (do ...) is a special form, so the compiler is handling it.

10:38 Another oops? You were referring to "wrapping" Java libraries for Clojure?

10:38 Chouser: duck1123: wrapping a java method call like (defn split [a b] (.split a b)) probably costs almost nothing at runtime.

10:39 duck1123: RSchulz: I was referring to wrapping a native java call in a clojure fn

10:39 Chouser: Hotspot will take care of you, I expect.

10:39 AWizzArd: although that would be a wrapper that still means doing java in clojure. Interesting would be useful wrappers.

10:39 RSchulz: (Right) I've been wondering about that. Most of the time reflection is involved, but I'm wondering if it has to happen for ever single call or if the JVM's super-fancy optimizations can eliminate it in many or most cases?

10:39 Chouser: But it's more code and mental overhead for everyone reading your code.

10:40 AWizzArd: For example for adding an event handler to a swing component. A clojurish way would be to do that without (proxy ...).

10:40 Chouser: RSchulz: the JVM will not remove reflection that Clojure puts in.

10:40 duck1123: I try not to create wrappers unless it makes it much nicer to use, but sometimes it's hard to resist that urge

10:41 RSchulz: Chouser: How sure are you? HotSpot can in-line polymorphic calls (even at the native machine code level) and the re-generalize them if new types appear on later calls.

10:41 mibu: duck1123: my rule is: if it doesn't add logic, don't do it.

10:41 Chouser: duck1123: that's an appropriate struggle. keep it up! :-)

10:42 RSchulz: But if the reflection at the point of calling Java methods is, for practical purposes, uneliminable, then we should be considering type tags wherever they're happening in critical loops.

10:43 mibu: I'm interested to know, what you guys use clojure for?

10:44 RSchulz: I'm working towards an "executive" for automating complex (and possibly concurrent) tasks in a theorem prover.

10:44 I also want to produce a shell-like environment for composing and scripting a growing set of logic tools.

10:46 Speaking (thinking) of which... Does anyone know what the state of Rich's new "streams" stuff is? I see the type system seems to be pretty well flushed out, but he hasn't said much about it.

10:46 .... _fleshed out_ !

10:47 Chouser: RSchulz: I'm pretty sure, but I'd be happy to be proved wrong.

10:47 RSchulz: Well, I wouldn't count on it, but I'd like to image the day when the JVM / HotSpot is so sophisticated it can do that sort of thing.

10:47 Definitely not holding my breath, though.

10:47 Which is why I wonder about when / where / how much to type-tag my method calls.

10:48 mibu: RSchulz: why type-tag your calls?

10:48 RSchulz: E.g., character-at-a-time I/O calls?

10:48 Chousuke: mibu: eliminates reflection

10:48 RSchulz: To avoid reflection when invoking them.

10:48 triddell: duck123: jyaml seems like it will work fine, I always liked yaml for the bit of Ruby I did so I used it for my config files

10:48 mibu: RSchulz: premature optimization is the root of all evil.

10:49 RSchulz: Yeah. I know that one. Which is why it's _a question_ of when / where / ...

10:49 Chousuke: after you're profiled it's a problem :)

10:50 triddell: duck1123: see above... got your nick wrong

10:50 mibu: RSchulz: only on inner loops, when you have absolutely determined that they are bottlenecks, which means rarely ever.

10:50 Chousuke: or if you know it's going to get called a million times with the same type.

10:50 RSchulz: Which is why I brought up the character-at-a-time example.

10:50 ... character-at-a-time _I/O_ ...

10:51 duck1123: triddell: have you been using the new standalone compojure library, or are you using the older code?

10:51 I was using the whole framework version, but I got sidetracked by trying to get it working in Tomcat

10:52 RSchulz: Am I the only one with a IRC client that auto-completes nicks (avoiding typos)?

10:52 duck1123: RSchulz: it's still possible with the members of this channel. (too many similar nicks)

10:53 triddell: duck1123: I actually just grabbed the html piece, which also needs a few other files. I'm only doing code generation with it right now for an eclipse plug-in I'm porting from Groovy code.

10:53 RSchulz: Yeah, but mostly only those Chous* guys. And the occasional _ suffix duplicate / variant bit.

10:57 slangan: im writing a DSL and I have some trouble with the repl. I want to read a line but neither read or read-line does the job very well.

10:57 i want to read in a line and get it as a slist(read-line returns a string).

10:58 and read stops at a space

10:58 RSchulz: slangan: Why don't you let the reader handle it? Which means, don't deal in lines and bytes, but in S-Expressions.

10:59 It imposes some constraints on your DSL (like enclosing outer-most parentheses, for one thing).

11:01 slangan: but one of the points f the DSL is allowing 2 + 3

11:01 how do i use the reader anyway?

11:01 gnuvince: Change the DSL not to allow that :)

11:01 RSchulz: Then you're going to need a parser.

11:02 slangan: yes

11:02 RSchulz: Is infix _really_ necessary for your end users?

11:03 slangan: so the parser should hand�e strings?

11:03 and yes infix is necessary

11:03 RSchulz: That's a choice you have. You could still use the Clojure reader if it's rules for interpreting character streams is consistent with your requirements.

11:03 If it's not, you'll have to work up from the character level.

11:04 I've heard tell of people working on parser combinator libraries, so you might want to ask on the list what's available as a starting point.

11:08 slangan: Of course, a convetional ANTLR or JavaCC parser could be used, too, given the relative easy of integrating Java libraries into Clojure programs.

11:20 slangan: ok thanks for the tips

11:20 how do I throw a syntax-error-exception? what is the name of that error?

11:20 RSchulz: (throw (new ExceptionName ...)) I'm not sure what specific exception you're thinking of, but they all work the same way with (throw ...) and (try ... (catch ...) (finally ...))

11:21 slangan: hmm I cant extend Clojur with new types, is that the expression problem?

11:21 Chousuke: what new types do you mean?

11:21 you can write java classes.

11:21 but in general that's only needed to interface with java libraries.

11:23 RSchulz: slangan: Keep in mind that Clojure's types are Java types.

11:23 You can extend them, should you find the need, though I'd expect that to be rare.

11:23 And you can use pre-existing Java types, though not all equally easily, I suppose (very generally speaking).

11:23 Chousuke: most "types" you can simply model using vectors or maps or something

11:23 RSchulz: What do you mean by "the expression problem?"

11:51 slangan: what is mod again?

11:51 (% 46 5)

11:51 cgrand: (rem 46 5)

11:53 Chousuke: clojurebot: awake yet?

11:53 :(

11:53 AWizzArd: still having fun in its for-ever loop

12:13 RSchulz: What timezone does hiredman live in?

12:13 triddell: Any ideas why when I try to compile a ns I get "No such file or directory seq_utils.clj... I am using duck_streams and I see this file is in contrib but that jar is on my classpath... does it need access to the clj files?

12:14 RSchulz: The contents of a JAR file in your classpath is like having all its individual file content directories on your classpath.

12:15 replaca: Q: Is the theory that the wikibook is going to move to the google code wiki? Or are there going to be two different things?

12:15 RSchulz: What (use ...) form or :use clause are you using (no pun).

12:15 triddell: (:use (clojure.contrib duck-streams))

12:16 RSchulz: Try (:use [clojure.contrib.duck-streams])

12:16 triddell: I'm *really* new to the gen-class.. just figuring it out... I am a Java guy though

12:17 RSchulz: Likewise, except I haven't ventured into gen-class territory, yet.

12:33 Lau_of_DK: What on earth happend to our Wiki ?

12:35 replaca: It lloks like queued changes might have finally been approved

12:35 *looks

12:35 Lau_of_DK: Everything worth reading has been removed

12:36 replaca: No, I think it's all there - it's just not all one page anymore

12:36 but maybe I have a different view because I'm "logged in"

12:37 slangan: how do I do if i need to return a ( but that givrs unclosed parameter...

12:37 i quoteed it and sitll the same problem

12:38 replaca: Lau_of_DK: does it look ok when you click through links?

12:39 Lau_of_DK: Yea all the info is there

12:39 But I think its better to have it all on one page

12:39 replaca: cool

12:39 that only works for so long

12:39 and then that page goes crazy

12:40 hopefully clojure is going to generate more than one page of good stuff :-)

12:41 And there's going to be a new FAQ (rhickey was discussing in the google group) that will cover FAQ-y type stuff

12:41 so the wiki can be much more comprehensive

12:42 But I know there's a wiki at google code too, so I'm wondering if we're gooing to move the wiki there

12:43 Lau_of_DK: Probably not

12:43 replaca: OK

12:44 does someone "own" the approval process on this wiki

12:44 it seems to take a long time

12:44 ?

12:45 I added some stuff about unit test frameworks the other day but it was on top of a whole bunch of unapproved edits

12:45 that eventually got approved

12:45 slangan: now i need to convert "(" to (...butusing ( ina function without closing it doesnt work.,..

12:50 Chousuke: hm

12:50 I modified clojurebot some but I can't test my changes as I don't have pircbot installed ;/

12:52 <3 gist

12:52 http://gist.github.com/37563

12:52 (the wrap-execution function)

12:52 hiredman: you may want to check that out too :)

12:53 I make no guarantee that it even works, as it was the simplest solution I could come up with based on the docs and as I said I haven't done any testing :P

12:56 hiredman: clojurebot: ping?

12:56 Chousuke: it's still running an infinite loop :)

12:59 hiredman: java is only at 50%

12:59 which is nice

12:59 RSchulz: slangan: If you want to deal in characters, the notation for char literals is to precede them with a backslash.

13:00 hiredman: Do you have a dual-core, dual CPU or HT processor?

13:00 hiredman: nope

13:00 RSchulz: Then what's throttling it at 50%?

13:00 hiredman: spoke too soon, it spiked back up to 80%

13:00 RSchulz: I've noticed heavy GC causing lowered CPU utilization, though I've never understood why that should be so.

13:01 clojurebot: svn rev 1174; Copy or release 20081217

13:02 hiredman: clojurebot's jvm is running with a small stack and heap, so it needs that gc

13:02 walters: RSchulz: probably stop-the-world collections

13:02 hiredman: clojurebot: how much do you know?

13:02 clojurebot: I know 105 things

13:02 RSchulz: walters: But I don't see how that explains lower CPU utilization? Why doesn't the CPU shift from user threads to the GC thread at the same full-bore demand?

13:03 clojurebot: Do you know not to chase your own tail?

13:03 clojurebot: It's greek to me.

13:03 hiredman: ,(println "No")

13:03 clojurebot: No

13:03 RSchulz: I think even Bender got caught in one of those loops, once...

13:03 walters: RSchulz: well it depends on how many active app threads you have...some GC phases could be single-threaded, a lot comes down to which collector you're using, what flags, etc.

13:04 RSchulz: Not that I'd try it, but does clojurebot protect itself from, say System/exit?

13:04 hiredman: clojurebot: sandbox?

13:04 clojurebot: sandbox is http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

13:04 RSchulz: walters: But what could be happening that causes periods during which the JVM makes _no_ demand on the CPU?

13:04 hiredman: ,(System/exit)

13:04 clojurebot: :DENIED

13:04 walters: RSchulz: possibly parts of the heap got swapped out and it's blocking on disk IO?

13:05 RSchulz: So, hiredman, you're challenging us to find ways to harm Clojurebot??

13:05 walters: That's at least plausible, though I think when I've seen it there hasn't been any swapping / paging going on.

13:05 hiredman: RSchulz: no

13:05 RSchulz: Just checking...

13:06 Chousuke: ,(throw Exception "hmm")

13:06 clojurebot: :DENIED

13:07 Chousuke: hiredman: this version isn't running my modifications yet, is it+

13:07 * Chousuke thinks it would probably break horribly if actually run...

13:07 RSchulz: ,(.. (new ProcessBuilder) (.command "sh" "-c" "ls -l") (.start))

13:07 clojurebot: :DENIED

13:07 RSchulz: Damn!

13:08 ,(.. (Runtime/getRuntime) (.maxMemory))

13:08 clojurebot: :DENIED

13:09 RSchulz: Jeez. What _will_ it let us do??

13:09 Chousuke: infinite loops!

13:09 RSchulz: Yeah. We got that...

13:09 Chousuke: ,(+ 1 1)

13:09 clojurebot: 2

13:09 RSchulz: Woo-Hoo!

13:09 Chousuke: remember that it also supports defining functions

13:09 RSchulz: ,(meaning 'Life)

13:09 clojurebot: :DENIED

13:09 RSchulz: ,(find-question '(:answer 42))

13:09 clojurebot: :DENIED

13:09 Chousuke: meaning = undefined function = exception = :DENIED

13:10 RSchulz: That's rude.

13:10 hiredman: ,(def status (ref {}))

13:10 clojurebot: #'foo/status

13:10 hiredman: ,(dosync (commute status assoc "hiredman" "attempting the summit"))

13:10 clojurebot: {"hiredman" "attempting the summit"}

13:11 Chousuke: ,(eval status)

13:11 clojurebot: clojure.lang.Ref@2016b0

13:11 Chousuke: oops

13:11 hiredman: deref

13:11 Chousuke: ,(eval (deref status))

13:11 clojurebot: {"hiredman" "attempting the summit"}

13:11 Chousuke: hooray

13:11 hiredman: why the extra eval?

13:12 Chousuke: ... I just edited the previous line :P

13:12 nagnals: hmm i need patternmatching. should impelment attermathicng ofr clojure?

13:13 RSchulz: hiredman: Did you get my idea about evaluating submissions from each IRC nick in a namespace derived from that nick?

13:13 hiredman: I saw it

13:14 triddell: ok, another question: I have now compiled my source clj file with the basic :gen-class symbol. My namespace is "solo.core" and I now have core__init.class and the rest of the support classes. What am I missing to be able to call one of my functions (statically hopefully) from Java?

13:15 I made a jar of all the class files...

13:26 ok, I got the core.class file now

13:31 Lau_of_DK: hiredman: I applogize for nuking your bot, I honestly did expect it to recover

13:40 Chousuke: hm

13:40 did some testing with my mods

13:40 not quite working, but close

13:48 cemerick: I've returned to looking at zip again. Am I right in thinking that, because make-node is the way it is, the current zipper impl doesn't lend itself to trees whose branches maintain aggregate data about their siblings?

13:49 i.e. using a 'replace' primitive rather than make-node would enable you to return new parent nodes that contain updated aggregate information, rather than recalculating it each time a parent is created.

13:58 Chouser: cemerick: you're talking about a particular piece of data being copied in several places in the tree?

14:00 Chousuke: hooray

14:00 wait. wuh

14:01 cemerick: Chouser: No -- consider a tree structure whose leaves are vectors that contain integers (e.g. [1 6 28 3]), and the branches/parents are maps like {:children [...] :max XX}, where :children are the node's children, and :max is the maximum value that may be found among the descendant leaves.

14:02 RSchulz: cemerick: I think you could record the derived / aggregate data (max, e.g.) in node metadata which could be replaced on any given node rather than replacing the node (thereby creating a new tree)

14:02 Chousuke: okay, I managed to get my own clojurebot instance to return from an infinite loop but the thread still remains :>

14:03 cemerick: make-node would require a full traversal of the new children to determine the new :max at a given branch. Replacement semantics would allow you to only adjust the :max if a child being replaced had a value equal to the branch's current :max.

14:03 Chouser: cemerick: ok, I think I'm understand your question.

14:04 cemerick: RSchulz: but in a replacement operation (remove then add), I still need to perform a full traversal rooted at the modified branch in order to maintain that aggregate data, regardless of where it's stored.

14:04 RSchulz: Are you chaning the actual tree data, or just computing derived information _about_ that tree's contents?

14:04 cemerick: RSchulz: actually changing the tree's data

14:05 Chouser: cemerick: yes, it looks like you'd have to traverse to the node, replace, traverse back up.

14:05 cemerick: fwiw, this is in the area of "online" spatial indexing -- it's very important to be able to modify the tree, and then support reasonably fast queries over it (which rely upon various pieces of aggregate data at different levels of the tree)

14:05 RSchulz: I have situations like this processing logical formulas (which are tree-structured). I have traversers and transformers that embody the traversal logic. The transformers allow the distinguishing of the top-down phase from the bottom-up phase.

14:06 cemerick: Chouser: That's what I'm doing now -- I put together a little xpath-esque transformer for tree structures that gets the job done.

14:06 karmazilla: I have noticed *1 mentioned a couple of places, but what is it?

14:06 cemerick: I've got some breathing room now, so I thought I'd see if zip could help me out long-term. :-)

14:06 RSchulz: It's the value most recently evaluated at the REPL.

14:06 *2 is the second-most-recent value; And there's a *3, too.

14:07 karmazilla: ok

14:07 cemerick: RSchulz: so you're doing a traversal on every operation as well?

14:07 Chouser: cemerick: they're immutable trees?

14:08 cemerick: Chouser: Yeah. Surely you're not suggesting I start set!-ing refs? ;-)

14:08 RSchulz: My point is that by distinguishing the top-down from the bottom-up, two kinds of algorithms are acommodated: Those that produce new sub-formulas during top-down traversal and those that produce them during the retreat from the bottom. (And those that do both)

14:08 cemerick: Surely you dont' have a Ref for every node in your tree, do you?

14:09 cemerick: RSchulz: no, no -- I thought that's what Chouser was asking about, though.

14:10 RSchulz: I should point out that my Formula classes are immutable, so I don't have a choice in how I implement transformers. They must produce new formulas, though they can share unaltered structure in the downward direction. (They're linked downward.)

14:12 cemerick: RSchulz: Yeah, all of my operations produce new trees as well. But if I were to implement them in terms of zip, I'd end up recalculating aggregates all over the place (since most of the aggregate data I maintain are min/max of some value(s) of a node's descendants).

14:13 RSchulz: I wonder if Huet was assuming some kind of "hash-consing" scheme to minimize duplication?

14:14 cemerick: Not sure, but I think an assumption of "dumb" nodes is made.

14:14 RSchulz: One thing I do use to my advantage in Java code is the IAI pattern: Immutable After Initialization. It allows me to incrementally build up a node in a formula tree, say, but not change it thereafter.

14:14 Chouser: cemerick: that's what I was asking. zip is my only experience with immutable trees -- I don't know how else to do it.

14:16 cemerick: Chouser: if how you descend through the tree is deterministic based on intermediate/aggregate values stored in branches, then it's a simple bubble-up of updates

14:18 RSchulz: Are these quadtrees or octtrees or something of the sort?

14:21 cemerick: RSchulz: I used to use quadtrees, yes. I use r-trees sometimes now, as well as a bidirectional interval trees (which I don't think are specified in the literature -- I hacked those together for use with highly regular spaces, where r-tree node splitting quickly becomes degenerate).

14:22 RSchulz: And you're using basic Clojure data structures to implement them?

14:22 Perhaps this is just an application where a mutable approach is called for?

14:24 cemerick: RSchulz: For now, yes, I'm just using struct-maps for the branches.

14:24 RSchulz: You mean for the nodes.

14:25 cemerick: Sure.

14:25 RSchulz: Each association within a map being an arc?

14:25 cemerick: Not sure why I would slip back to using anything mutable -- that's where these things *came* from :-)

14:25 RSchulz: "Exigent circumstnaces?"

14:26 cemerick: no, everything is rectilinear

14:26 RSchulz: By "arc" I mean Vertex (node) vs. Arc (link)

14:27 CardinalFang: I'm about to try using Clojure to write code for Android. I welcome advice and interjections.

14:27 cemerick: ah. No, these aren't graphs, they're trees.

14:28 RSchulz: Trees are graphs!

14:28 cemerick: a subset with specific characteristics, yes

14:29 RSchulz: Directed Acyclig Graphs in which each node (except one) has in-order equal to one and one node (the root) has in-order equal to 0.

14:29 So the terminology of vertex and arc are still applicable.

14:29 cemerick: forgive me, I'm not classically trained...

14:30 RSchulz: Yeah, and I'm a pedant. I can't help it...

14:31 Anyway, the immutable / mutable thing is pragmatic. If it works against you to use it, I'd say do something else, realizing the tradeoffs that ensue.

14:32 cemerick: Yeah. I had an r-tree impl in Java for years. It was a pretty painful API.

14:33 RSchulz: Specifically because of mutability?

14:33 I've been very happy with my decision to make my formula structures immutable.

14:34 cemerick: and because of Java itself. No easy predicates for specifying queries, filtering results by nonspatial characteristics, etc.

14:34 RSchulz: And if I were to be totally honest, I put in some mutability "back-doors," and ultimately got bitten by them more than once.

14:34 hiredman: clojurebot: ping?

14:34 clojurebot: Gabh mo leithsc�al?

14:34 hiredman: clojurebot: ping is <reply>PONG!

14:34 clojurebot: Ok.

14:34 RSchulz: clojurebot: ping-pong?

14:34 clojurebot: PONG!

14:34 cemerick: well, I also need things to be pure so I can easily backtrack to prior transformation states

14:35 RSchulz: But there are intermediate states during the transformation of generation N of the tree from generation N-1 that you fear will proliferate to undesirable magnitudes?

14:36 What scale are you operating at? How many nodes in these trees?

14:36 hiredman: ,(dosync (commute status assoc "hiredman" "made the summit, awaiting rescue"))

14:36 clojurebot: {"hiredman" "made the summit, awaiting rescue"}

14:36 cemerick: no, not particularly -- why?

14:36 RSchulz: And you said "online," so I take it responsiveness is important?

14:36 cemerick: not many -- many thousands of data elements, so whatever that works out to in a mostly-balanced tree

14:37 RSchulz: So what aspect of using the Zipper concerns you?

14:37 cemerick: that the current impl requires the recalculation of aggregate data

14:38 RSchulz: Redundantly?

14:38 cemerick: it's not a problem, per se -- just that my requirements are orthogonal in one aspect to its impl.

14:38 RSchulz: Why would that be?

14:38 Could you not generate the new tree in one pass and then in another compute the aggregate data?

14:39 cemerick: well, that's the difference between an offline and online data structure -- in the former, you can bulk-load the tree, and maintaining aggregate data is unimportant since you've calculated it once and won't touch it again

14:40 s/touch/modify

14:56 hiredman: ugh

14:56 I think it maybe time to move clojurebot from gist to a proper github deal

15:11 danlarkin: hiredman: I'd like that

15:24 Chousuke: hiredman: I've been trying to get clojurebot working but it appears that it refuses to even connect to IRC if I enable the security manager.

15:24 hiredman: do you have a default permissions file for it?

15:25 hiredman: yes

15:25 Chousuke: I managed to make it interrupt runaway computations

15:26 hiredman: http://gist.github.com/37639

15:26 Chousuke: yeah, very nice

15:26 I saw your gist

15:26 Chousuke: that doesn't quite work though.

15:26 hiredman: yeah, I noticed :P

15:27 Chousuke: hiredman: but hm, isn't running it like that equivalent to not having a securitymanager at all? :P

15:27 hiredman: Chousuke: yes, but the sandbox creates a new security context

15:27 or something

15:28 Chousuke: ah

15:28 hm

15:28 hiredman: ugh

15:28 lame

15:31 Chousuke: hm, right

15:31 now it works, but

15:32 for some reason, *ns* is clojure.core

15:33 and it allows creating new threads :P

15:33 hiredman: yeah

15:33 *ns* is thread locally bound

15:34 Chousuke: but isn't it inherited?

15:34 hiredman: dunno

15:34 I am seeing the this right now with *out*

15:34 my deal runs, but it prints out to system.out instead of the stringwriter

15:36 Chousuke: hm

15:36 hiredman: (binding [*ns* 'foo] (.start (Thread. #(println *ns*))))

15:36 ^- clojure.core

15:36 weird, and lame

15:37 Chousuke: wonder if there's a way to prevent spawning threads

15:37 Chouser: of course a new Thread will see the root binding.

15:37 binding only works within a given thread

15:37 hiredman: Chouser: I sort of figured that out :P

15:37 Chouser: yeah. :-)

15:38 Chousuke: can't have a clojure evaluator if it's able to spawn threads ;(

15:38 hiredman: Chousuke: *shrug*

15:38 Chouser: why's that? applets can spawn threads.

15:39 Chousuke: well, they'd have access to the clojure.core namespace of the bot

15:40 hiredman: Chousuke: you have access anyway

15:40 Chousuke: even if hmm

15:40 oops

15:40 hiredman: ,(do (in-ns 'clojure.core) (naughty stuff))

15:40 clojurebot: :DENIED

15:40 hiredman: ,(do (in-ns 'clojure.core) (println *ns*))

15:40 clojurebot: #<Namespace clojure.core>

15:40 Chousuke: well I guess the evaluated code has to be wrapped in a threadgroup as well

15:41 so that all spawned threads can be killed.

15:41 hiredman: this is getting very complex

15:45 Chousuke: http://gist.github.com/37563 I refactored this so many times it probably doesn't make much sense anymore, but here goes.

15:46 hiredman: Chousuke: the wrap-exceptions deal is useful

15:46 I should have written something like it at the outset

15:47 Chousuke: the wrap-execution stuff runs the thing in a separate thread so that it can be killed

15:48 hiredman: will need to move the *ns* and *out* binding stuff into that thread

15:48 Chousuke: yeah

15:49 mehrheit: anybody know why inner classes are only accessible by package-qualified names? (even if the parent class is imported)

15:49 hiredman: mehrheit: you can import the inner classes

15:49 mehrheit: oh, yeah. I forgot

15:50 thank you

16:00 karmazilla: I recently had a need for some "case" expression and came up with this: http://gist.github.com/37651 - I wonder if it can be written in a more elegant way

16:00 * karmazilla .oO( or maybe something like it already exists. )

16:00 kotarak: karmazilla: clojure.contrib.fcase

16:03 karmazilla: also using 'val is bad, bad, bad. This can lead to clashes with the user code in the expansion use `(let [val# ...] ..). This generates automatically a symbol, which cannot be in the user code.

16:11 lisppaste8: kotarak pasted "karmazilla: modified case" at http://paste.lisp.org/display/72363

16:12 kotarak: karmazilla: this should be save against variable capture, but clojure.contrib.fcase is of course more robust and flexible and...

16:16 karmazilla: ah yes, I knew that there was something or other looking like "~@" but I could not find it on the website

16:24 kotarak: karmazilla: just think Scheme: , => ~ and ,@ => ~@

16:27 karmazilla: I don't know Scheme so that doesn't help

16:28 kotarak: ah. ok. never mind.

16:33 hiredman: ,(loop [] (recur))

16:33 clojurebot: Execution timed out

16:33 hiredman: clojurebot: botsnack

16:33 clojurebot: thanks; that was delicious. (nom nom nom)

16:34 mehrheit: ,1;?

16:34 hiredman: ,(println "hello")

16:35 clojurebot: hello

16:35 mehrheit: ,(prn 1)

16:35 clojurebot: 1

16:35 mehrheit: ,(dotimes x 2 (prn x))

16:36 Chousuke: hiredman: did you merge my changes to your gist repo properly or just by copy&paste? :)

16:36 hiredman: Chousuke: copy and paste

16:36 Chousuke: too bad, means I can't merge your changes back into mine.

16:37 hiredman: uh, well, I am not using git "internally"

16:37 the sandboxing stuff deserves its own lib

16:37 RSchulz: hiredman: You know, now that clojurebot does Clojure code, it's probably going to need to be fed a lot more.

16:38 hiredman: mehrheit: dotimes takes a [] for binding now

16:38 Chousuke: (just in case you'll ever need something like it: in your git clone dir: git remote add chousuke git://gist.github.com/37563.git; git fetch chousuke; git merge chousuke; git push # (to push to github))

16:38 RSchulz: Did you do the sandboxing in Clojure or in Java?

16:39 hiredman: jvm and clojure

16:41 fatal: 'chousuke' does not point to a commit

16:44 mehrheit: ,(dotimes [x 2] (prn x))

16:44 clojurebot: 0 1

16:45 Chouser: ,(doseq [i (.split "I am a bot" " ")] (println i) (Thread/sleep 3000))

16:46 clojurebot: Execution timed out

16:46 Chouser: ,(doseq [i (.split "I am a bot" " ")] (println i) (Thread/sleep 500))

16:46 clojurebot: I am a bot

16:47 drewr: ,(System/exit 0)

16:47 Chouser: clojurebot: hi!

16:47 clojurebot: Huh?

16:47 drewr: ,(System/getProperty "user.dir")

16:47 Chouser: ,(class *out*)

16:47 clojurebot: class java.io.StringWriter

16:48 mehrheit: ,(prn *ns*)

16:48 clojurebot: #<Namespace foo>

16:48 hiredman: ,(System/getProperty "user.dir")

16:48 man, I hope I did not just break it

16:49 drewr: ,foo

16:49 hiredman: drewr: needs a paren

16:49 drewr: Ah.

16:49 danlarkin: ,(slurp "/etc/group")

16:49 hiredman: no io

16:49 danlarkin: clojurebot: rude!

16:49 clojurebot: I don't understand.

16:50 karmazilla: ,(loop [] (recur))

16:50 hiredman: dunno why it is swallowing exceptions again

16:50 drewr: Heh.

16:50 clojurebot: Execution timed out

16:50 drewr: Does it fire each one in a thread?

16:50 Chousuke: yeah

16:50 karmazilla: may I try to break that threading?

16:50 Chousuke: and then it waits for it to finish, so no concurrent stuff :P

16:51 there's still a problem with it.

16:51 hiredman: many problems

16:51 Chousuke: you can spawn your own threads that will not get killed.

16:52 hiredman: Chousuke: sshhh

16:52 Chousuke: though that'll just require wrapping the thing in a threadgroup so that all its chidren threads can be killed as well :P

16:52 hiredman: loose lips sink ships

16:52 karmazilla: ,((fn john_mcclane [] (try (loop [] (recur)) (catch Throwable _ (apply john_mcclane)))))

16:52 clojurebot: Execution timed out

16:52 hiredman: when you ride alone you ride with hitler

16:52 mehrheit: , (prn 1)

16:53 ,(println ",(println 1)")

16:53 Chousuke: hm.

16:53 hiredman: uh

16:54 Chouser: ,(prn :still-here)

16:54 hiredman: locked

16:54 karmazilla: kill -QUIT?

16:54 Chouser: this is probably a very good way to clean up a sandboxing implementation.

16:55 Chousuke: maybe we should make a #clojurebot-playground channel

16:57 AWizzArd: hiredman: on what level does this io blocking happen? On the byte code level?

17:00 karmazilla: I think john_mcclane caught your Thread.stop call :)

17:01 hiredman: java has 0 load

17:01 AWizzArd: however the jvm does it

17:01 but the repl is locked

17:04 anyway

17:04 I have stuff to do, so if you break clojurebot, I will not be here to restart him

17:07 karmazilla: also, since a new thread is started for every input line, then it shouldn't matter much that one thread was hijacked :/

17:08 that is, if it was

17:10 Chousuke: hm

17:16 it seems clojurebot's code evaluation is completely broken at the moment. I did some tests in query and all it gives me are exceptions :/

17:16 oh well

17:31 rfgpfeiffer: ()

17:32 hiredman: whoopd

17:32 fixed

17:33 looks like some one shook up a snow globe outside

17:34 drewr: hiredman: Where are you?

17:35 lisppaste8: mmcgrana pasted "get source file and line" at http://paste.lisp.org/display/72369

17:35 mmcgrana: can anyone figure out a simpler way to do this?

17:35 hiredman: drewr: seattle

17:36 drewr: We had our share last week in TN.

17:36 hiredman: ,(loop [] (recur))

17:36 clojurebot: Execution timed out

17:37 mmcgrana: can the clojurebot run code now?

17:37 drewr: mmcgrana: Yup! It even writes code for you. Just tell it your problem.

17:37 Chousuke: hiredman: there should be some way to prevent people from redefining the sandboxing function :P

17:38 mmcgrana: cool

17:39 danlarkin: clojurebot: I need to go grocery shopping. Please give me code for that

17:39 clojurebot: Huh?

17:39 mmcgrana: lol. btw is there some place that all of clojurebot's functionality is documented? is his implementation open source?

17:39 drewr: clojurebot: I need a statistical model for a linear regression whatsamadozit.

17:39 clojurebot: Pardon?

17:39 drewr: See, it even recognizes bs.

17:39 Chouser: mmcgrana: ha! clever.

17:40 danlarkin: clojurebot: where are you?

17:40 clojurebot: http://gist.github.com/27733

17:40 danlarkin: mmcgrana: ^

17:41 Kerris7: clojurebot: what is your relationship with lispbot?

17:41 clojurebot: Huh?

17:41 Kerris7: clojurebot: don't deny it, we have evidence!

17:41 clojurebot: Titim gan �ir� ort.

17:41 Kerris7: wha?

17:41 mmcgrana: danlarkin: thanks

17:41 RSchulz: hiredman: What's the time limit? 10 seconds?

17:44 Chousuke: yeah

17:44 Chouser: mmcgrana: the top-level 'let' isn't doing anything for you.

17:45 well, nothing that 'do' wouldn't do.

17:46 hiredman: ,((fn john_mcclane [] (try (loop [] (recur)) (catch Throwable _ (apply john_mcclane)))))

17:46 clojurebot: Gabh mo leithsc�al?

17:46 hiredman: :)

17:47 doesn't accept stuff with catch in it

17:47 karmazilla: no more action movie heroes, then

17:48 mmcgrana: hmm is there a function like multiget on maps? (mget {:foo :1 :bar 2} [:foo :bar]) => (1 2)

17:51 hiredman: karmazilla: cute

17:52 Chouser: mmcgrana: map

17:52 mmcgrana: o good call

17:53 Chouser: (doc ns-unmap)

17:53 clojurebot: Removes the mappings for the symbol from the namespace.; arglists ([ns sym])

17:53 RSchulz: Shouldn't it filter?

17:53 lisppaste8: mmcgrana annotated #72369 with "more concise" at http://paste.lisp.org/display/72369#1

17:53 Chouser: ,(doc ns-unmap)

17:53 clojurebot: ------------------------- clojure.core/ns-unmap ([ns sym]) Removes the mappings for the symbol from the namespace.

17:53 Chouser: hehe

17:55 lisppaste8: Chouser annotated #72369 with "with more reader macros" at http://paste.lisp.org/display/72369#2

17:56 mmcgrana: but am i right to think that one can't do this file-line business without using a (def in there?

17:56 Chouser: nice

17:56 Chouser: mmcgrana: there is *file* which doesn't seem to work for repl-ln, but does work in read files.

17:57 But there's no equivalent *line* -- there is a Var with the value you want (it's what 'def' uses), but it's not available to Clojure code.

17:58 mmcgrana: ok

17:58 Chouser: oh!

17:58 (var-get clojure.lang.Compiler/LINE)

17:59 there it is, it just isn't in any namespace.

17:59 clojurebot: svn rev 1175; make sure find returns entry with original key

18:00 mmcgrana: also SOURCE, which is a little confusing because it doesn't correspond to *file*

18:00 the name i mean

18:00 karmazilla: hiredman: do you also prevent ((fn john_mcclane [] (try (loop [] (recur)) (finally (apply john_mcclane))))) ?

18:01 lisppaste8: mmcgrana annotated #72369 with "with help from Compiler" at http://paste.lisp.org/display/72369#3

18:01 Chouser: rhickey: arg, I had that except for the RT change.

18:02 Which only became a problem when Clojure maps became java.util.Maps.

18:02 rhickey: Chouser: right, that was my first thought

18:02 but as you saw there were a couple of fabricated entries

18:03 thanks for looking into it

18:03 Chouser: yeah, I found those, but was stumped as to why that didn't fix the problem.

18:03 rhickey: So, how do I get that into the branch of the release I made?

18:04 * rhickey is practicing for 1.0

18:04 * rhickey fumbles around with IntelliJ's svn support

18:05 Chouser: I'm afraid this is where svn is going to start hurting you.

18:05 RSchulz: rhickey: Which version of IDEA are you using?

18:05 rhickey: It all looks promising - there are menu options for integrate into branch

18:05 RSchulz: 8.0

18:05 looks like it wants me to have a working copy of the branch?

18:05 RSchulz: Me, too. But I do my version control from the command line.

18:06 rhickey: 8.0.1

18:06 RSchulz: Right. 8.0.1. I made the mistake of trying the first EAP of 8.1. Messy.

18:07 Chouser: can't help now, but I'd recommend keeping careful notes of which versions you merge in which direction.

18:07 My understanding is that you may need this information in later merges.

18:08 mmcgrana: o man svn merges

18:08 rhickey: Chouser: my idea was: cut a release, create a branch of it, continue working on trunk, move bugfixes into branch, never go the other way

18:08 no real merging

18:19 clojurebot: svn rev 1176; make sure find returns entry with original key

18:19 hiredman: clojurebot: uh?

18:19 clojurebot: It's greek to me.

18:20 rhickey: seemed to work ok

18:21 might be trickier when I want to move fixes but not features

18:35 lisppaste8: drewr pasted "macro & namespace" at http://paste.lisp.org/display/72375

18:36 drewr: Why does "in" in the binding form get namespaced?

18:37 Chousuke: it needs a ~

18:37 drewr: When I do that, line can't be used in the expansion.

18:38 It becomes foo.bar/line too.

18:38 Chousuke: you need to force name capture

18:38 with ~'line

18:38 make sure to document the implicit binding as well.

18:39 drewr: Do I do that in the when test?

18:39 Chousuke: both instances of line

18:39 kotarak: Better: let the user provide a name for the variable.

18:39 Avoids the capture.

18:39 drewr: kotarak: OK, that's a good idea.

18:40 RSchulz: Or use line#, since why would the invoker care what a local name is?

18:40 Chousuke: yeah, something like (defmacro with-each-line [[name-to-bind source] & body] ...)

18:40 RSchulz: the idea is to give the user access to each line in the body

18:40 RSchulz: Oh, I see. Evaluating the body.

18:41 Chousuke: though that looks like something you could just use line-seq for :)

18:43 drewr: Chousuke: Hm, possible. The input stream is from a socket in this case though.

18:43 Chousuke: (doseq [line (line-seq (BufferedReader. (FileReader. "foo.txt")))] whatever)

18:43 RSchulz: Whether it souces a socket or a file or an internal stream really doesn't matter.

18:43 At least Java does _that_ for you.

18:43 Chousuke: drewr: line-seq just wants a BufferedReader :)

18:43 drewr: RSchulz: *Shouldn't* matter. :-)

18:43 RSchulz: Can you think of a case when it would?

18:44 Chousuke: though hm

18:44 does line-seq close the file when it's done?

18:44 RSchulz: Hopefully not.

18:44 That would be presumptuous.

18:44 drewr: Chousuke: No, just creates a lazy-cons.

18:45 RSchulz: Some Streams / Readers / Writers are seekable.

18:45 Chousuke: in that case you might want to use (with-open) too :)

18:47 drewr: RSchulz: You raise a good point. I would definitely prefer line-seq.

18:47 Much more functional and less Java-y.

18:47 RSchulz: Which point?

18:48 drewr: That the reader shouldn't matter if it's network-dependent.

18:48 RSchulz: As long as you don't assume that once you've managed to open a stream (etc.) that you won't get errors, you'll be OK.

18:49 Even local files can present errors during I/O.

18:49 But they're distinctly more likely when reading from a network endpoint, of course.

18:49 drewr: My concern was related to the fact that I won't get things any particular order like in a file.

18:50 But I think I would still be OK in this case because I'm just responding to what comes across, which can be in any order anyway.

18:50 RSchulz: Well, ordering is independent, and if you're using TCP, then guaranteed by the underlying protocol.

18:51 drewr: Yep, TCP.

18:51 RSchulz: And if you don't trust that, then you'll need your own application-level protocol with redunancy of some sort to detect when the stream has become corrupted.

18:52 If you're consuming multiple inbound networks streams, then of course ordering will be unpredictable and you'll have to account for that.

18:52 drewr: Single input stream; just one socket.

18:53 * drewr doesn't want to use line-seq though because his macro his �ber-l33t

18:55 RSchulz: What is the granularity of the items you process? Bytes? Characters? Forms? Native (int / long / etc.)??

18:58 drewr: Text-based protocol with \r\n line termination.

18:58 crlf, rather

18:58 RSchulz: Then using a line-oriented reader seems appropriate.

19:01 drewr: OK, (doseq [line (line-seq in)] ...) it is. :-)

19:56 Chousuke: hm

19:57 RSchulz: hm? His Majesty?

20:03 Chousuke: RSchulz: I just patched my local version of clojure with a with-open that supports multiple bindings.

20:03 just wondering whether it'd make sense to close the opened streams in reverse order.

20:06 RSchulz: I thought with-open already did support multiple bindings... Nonetheless...

20:06 Chousuke: RSchulz: no, it doesn't.

20:06 RSchulz: I don't think it really matters the order in which they're closed.

20:06 Chousuke: it silently only closes the first binding

20:06 RSchulz: That's not cool!

20:07 Chousuke: too bad I don't have a CA :/

20:07 RSchulz: Under the (I think reasonable) assumption that each output stream targets a different ultimate destination, the implicit flush upon close _could_ be signicicant...

20:08 But I'm not sure that is something that is more correct one way than the other.

20:08 Is there an issue with submitting a CA from outside the U.S.?

20:09 Chousuke: I don't know :/

20:09 RSchulz: Gack. What I said was nonsense. If each stream is independent, order doesn't matter. If two or more target the same output stream, then the implicit flush would matter, but I don't think that's something that factors into the definition of the with-open macro.

20:09 Just state the order and leave it at that.

20:09 With-open is in the core?

20:10 If the CA is an issue, you could just report the problem to Rich and let him fix it.

20:10 hiredman: clojurebot: rhickey?

20:10 clojurebot: he works hard so you don't have to

20:10 RSchulz: clojurebot: hiredman?

20:10 clojurebot: hiredman is an evil genius.

20:10 RSchulz: I _KNEW_ it!

20:11 hiredman: karmazilla was mucking with clojure.asm through clojurebot

20:13 RSchulz: Sounds kind of like performing neurosurgery.

20:13 Chousuke: I suppose I can't just release a patch to the public domain either :P

20:13 RSchulz: Curious notion... Would the quoting of the original content to be changed considered fair use?

20:14 Still, you could just post it to the list and let the chips fall where they may. I assume the change is straightforward and not voluminous?

20:15 Chousuke: pretty much

20:15 RSchulz: Much ado about nothing (or little)??

20:15 Not to denigrate your contribution.

20:15 Why don't you just send off a signed CA?

20:15 Chousuke: I should, I suppose.

20:15 RSchulz: I hear they have air mail for the trans-Atlantic route now!

20:16 Chousuke: unfortunately I don't have time to do so until sometime in January :P

20:16 RSchulz: When I was an SWL kid, I had to send IRC (that's International Reply Coupons) to get air-mail replies!

20:16 How long does it take to print a PDF, sign it and put it in the mail??

20:17 Chousuke: well, I don't own a printer.

20:17 RSchulz: Surely there's _something_ available to you? Some equivalent to Kinkos (copy shop that has computers for printing and such)?

20:17 Chousuke: and I'll be busy tomorrow leaving this place to spend christmas vacation with family :P

20:18 RSchulz: Well, at a minimum, you could post the issue / request for change to the list.

20:18 Chousuke: yeah

20:18 RSchulz: Where do you travel for your christmas vacation?

20:18 You live in Finland, right?

20:19 Chousuke: yeah.

20:20 RSchulz: Short daylinght hours these days, huh?

20:20 I hate the cold!

20:20 I left Wisconsin 'cuase of the awful winters.

20:35 Chousuke: hmmhmm

20:36 I can probably get a CA sent tomorrow if I'm quick. in the meantime, there's an issue on the google code tracker now.

20:36 and it's way past my bedtime :)

20:41 lgas: Hi all. I'm new to Clojure and relatively new to lisp in general. I have a seq of items and I want to process them in groups of three... I'm sure there's an easy way to do this but it has me stumped. What functions should I be looking at?

20:44 Nevermind... I just found partition.

20:44 :)

20:48 hiredman: (doc partition)

20:48 clojurebot: Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap.; arglists ([n coll] [n step coll])

21:21 francois__: Hey all!

21:21 Just wondering if my style is correct: http://gist.github.com/37764

21:21 I want to extract the unique words of a string of text

21:21 The string will be Twitter status update messages

21:24 dhaya: francois__: how about this? (distinct (re-seq #"\w+" "hello world world"))

21:25 francois__: dhaya: Hmm, yes, that would be much simpler, yes

21:25 Besides, it would probably work better than what I'm getting at the moment: java.lang.ClassCastException: clojure.lang.PersistentList (NO_SOURCE_FILE:0)

21:25 This message is very cryptic

21:25 No stack trace, nothing

21:25 I don't even know what's wrong

21:28 dhaya: The regexp trick works just fine

21:29 I had to modify the regexp slightly #"[#@\w]+" so it caught everything I needed, but this is perfect

21:29 Thank you

21:40 Chouser: francois__: for a stack trace: (.printStackTrace *e)

21:41 francois__: Ah, but I'm at the REPL, so there's not much of a stack trace anyway :(

21:43 dhaya: francois__: I have never used read, it seems its typically used for reading in and emitting clojure data structures. For instance, all your "words" are emitted as clojure.lang.Symbol objects.

21:43 francois__: Yes, that's what I wanted initially

21:43 Using strings will achieve the same effect in the end for me

21:47 Chouser: francois__: for what it's worth, removing the parens around (word) got your original working.

21:47 francois__: Oh wow...

21:47 So, Clojure was trying to evaluate the symbol, and failing

21:48 I thought if required parens around the condition

21:48 But I remember now: symbols evaluate to themselves

21:48 If I put parens, that's a function call

21:48 Chouser: hm, well ... in this case, I don't think it's the "symbols evaluate to themselves" rule that's in play

21:49 francois__: I really want to know if it's nil or not

21:49 Since nil is false, I just wanted to use that

21:49 Chouser: 'word' is evaluating to the value of the local named 'word'

21:49 francois__: Which is a symbol, such as I

21:50 as in (def status "I read a book")

21:50 (I) would fail

21:50 (I) from the REPL returns: java.lang.Exception: Unable to resolve symbol: I in this context

21:51 Chouser: it's more like (let [word 'my] (word))

21:51 dhaya: francois__: Symbols are functions of map, so that (word) is expecting an map argument to be passed. In fact, thats the stack trace I get if i try yours. "Wrong number of args passed to symbol."

21:52 francois__: Were you at the REPL?

21:53 dhaya: francois__: yes

21:53 francois__: And which revision of Clojure?

21:53 I'm using r1149

21:57 dhaya: r1160. I am using emacs repl with slime and swank.

21:58 francois__: Hmmm, compiling 1160 fails for me with deeply nested exceptions

21:58 dhaya: did you try ant clean?

21:59 francois__: Ah, had to clean before

21:59 I still get a PersistentList error: java.lang.ClassCastException: clojure.lang.PersistentList

22:00 rHEAD has the same error (1162

22:02 dhaya: francois__: I doubt if the difference is because of clojure versions. AFAIK, nothing much changed with exception reporting in the last few days.

22:02 francois__: I didn't expect that too

22:03 I'm straight at the command line on Mac, using Java 1.5.0_16

22:03 Chouser: francois__: you get that exception while 'ant' is running?

22:04 francois__: Chouser: The PersistentList error? No, at the REPL, right after executing the (distinct (loop [] ...))

22:04 Chouser: oh

22:04 francois__: Here's a paste of the session: http://gist.github.com/37856

22:05 clj is a script that sets the classpath to clojure + clojure.contrib and jline

22:06 Chouser: francois__: run (.printStackTrace *e) after that and paste it too?

22:06 oh, you're giving it different input

22:06 it's still trying to evaluate whatever object 'read' is returning first

22:07 francois__: Possibly, yes

22:07 The first word ends up being a deref

22:07 http://gist.github.com/37856

22:07 I updated again, this time with the real content

22:09 Chouser: the @foo is expanded by the reader to a list (clojure.core/deref foo)

22:10 francois__: Correct, and (word) ends up evaluating that list, right?

22:10 Chouser: then it tries to evaluate that list as a function

22:10 right

22:10 francois__: Yeah, problem solved!

22:10 Not a problem in fact :)

22:10 Thank you for the help

22:10 I very much appreciate

22:10 I'm very new at Clojure in general, although I have years of imperative programming experience behind me

22:12 Chouser: great! how are you liking it?

22:12 francois__: I like it very much

22:12 It's interesting

22:12 I needed to find something to challenge myself

22:12 I did try Common Lisp a while ago

22:12 Chouser: wrong kind of challenge?

22:12 francois__: I knew how to read basic lists, but didn't devote enough time

22:12 triddell: quick thoughts from anyone? I need to build a sorted-map of sorted-sets while processing a set (seq) of files... doing this functionally with immutable data structures is daunting.... any tips?

22:12 francois__: Had to get back to paying work :)

22:13 triddell: basically, look if the key exists, if so add an entry to the set (value), otherwise add a new key and create a new set

22:14 francois__: triddell: loop/recur ? Isn't that the solution?

22:14 triddell: haven't used that yet... I'll check that out... thx

22:15 Chouser: loop/recur is almost always sufficient, but it's close to the biggest hammer

22:15 often 'reduce' or 'into' works well for building maps and sets

22:16 dhaya: triddell: I have also found update-in, assoc-in to be helpful when working with nested structures.

22:16 triddell: I read about that on the group, where you and Rich gave examples, but it didn't seem sufficient in this case

22:17 dhaya: ok, yes, I was looking at assoc but need to deal with the immutability

22:19 Chouser: triddell: (reduce (fn [smap file] (if (smap file) (assoc (smap file) ...) (assoc smap ... (sorted-set)) (sorted-map) fileseq)

22:19 or something

22:21 triddell: Chouser: thanks! I'll study that approach

Logging service provided by n01se.net