#clojure log - Aug 18 2009

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

0:10 cable_: potentially dumb map/reduce question

0:10 are map operations automatically made concurrent?

0:11 rlb: cable_: no -- see pmap

0:11 cable_: ah thx

0:56 lowlycoder: i have this really difficult task; I'm not sure if I can do it in clojure -- how do I open a file & read it in?

0:57 rlb: ?

0:57 lowlycoder: i'm kidding; how do I read in a file in clojure though?

0:57 rlb: lowlycoder: text?

0:57 (i.e. plain text lines, or other?)

0:58 lowlycoder: plain text

0:58 (doto (java.io.FileReader. filename) ... ) ?

0:58 what in ...

0:58 rlb: (line-seq java-buffered-reader)

0:59 Then you have a seq of lines you can do whatever you want with.

0:59 (i.e. lazy seq of lines)

0:59 arbscht: ,(doc slurp)

0:59 clojurebot: "([f] [f enc]); Reads the file named by f using the encoding enc into a string and returns it."

1:00 rlb: (line-seq (BufferedReader. (FileReader. file)))

1:00 or similar

1:02 lowlycoder: k#<CompilerException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (test.clj:0)>

1:04 (import '(api.java.io 'BufferedReader 'FileReader))

1:04 (line-seq (BufferedReader. (FileReader. "test.clj")))

1:04 results in: #<CompilerException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (test.clj:0)>

1:04 rlb: lowlycoder: your import command is wrong.

1:05 lowlycoder: it's just java.io

1:05 rlb: (import '(java.io BufferedReader FileReader))

1:05 lowlycoder: wonderful; thanks

1:08 how do I convert a string to a interger?

1:09 rather, a number, it may be either an integer or a floating point

1:10 clojure's # ... % notation for lambdas is prettty cool

1:10 arbscht: ,(class (read-string "99.9"))

1:10 clojurebot: java.lang.Double

1:11 arbscht: read-string may be too general (unsafe with untrusted input)

1:12 ,(Integer/parseInt "9")

1:12 clojurebot: 9

1:12 lowlycoder: why unsafe? does it execute it too?

1:13 does #(... ) notation nest? i.e. the % match only the innermost #

1:14 ack, nested #() are not allowed :-(

1:18 replaca: lowlycoder: but nested (fn [x y z] ...) lambdas are allowed

1:20 lowlycoder: why can't I (cons 1 2) but can (cons 1 '(2 3)) ?

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

1:20 lowlycoder: does cons must return a list?

1:21 rlb: I'm not sure clojure handles cons the same way as scheme/lisp.

1:21 arbscht: cons returns a seq

1:23 replaca: ,(class (cons 1 '(1 2)))

1:23 clojurebot: clojure.lang.Cons

1:24 replaca: lowlycoder: a clojure cons-cell can only have a seq in the cdr, I believe

1:24 tomoj: ,(class (cons 1 nil))

1:25 clojurebot: clojure.lang.PersistentList

1:25 replaca: lowlycoder: part of the challenge for lispers coming to clojure is to let go of things we assume from our days in CL or scheme

1:26 lowlycoder: (class (map #(re-split #" " %) (line-seq (BufferedReader. (FileReader. "m393/m393.off")))))

1:26 why is this a LazySeq, and why can't I take the car of it?

1:27 tomoj: line-seq is lazy

1:27 replaca: lowlycoder: map always returns a lazyseq

1:27 lowlycoder: how do I take the care of a lazyseq

1:27 replaca: (first foo)

1:28 lowlycoder: so now, first & rest is the standard way to take items from a sequence, of any form, and car/cdr is just for persistent lists?

1:28 arbscht: ,(doc car)

1:28 clojurebot: "/;nil; "

1:28 replaca: lowlycoder: what do you mean car? clojure has no such function (and really doesn't have the exact same concept)

1:28 lowlycoder: wtf, I don't even have car?

1:29 arbscht: yes

1:29 tomoj: there are no cons cells, what do you need car for..

1:29 lowlycoder: i'm just used to using it

1:29 replaca: lowlycoder: deep breath... you're leaving common lisp now... buckle your seatbelt and enjoy the ride :-)

1:29 lowlycoder: well, this is why they created define-macro :-D

1:30 replaca: lowlycoder: yeah, don't go there. you'll be paddling upstream

1:30 lowlycoder: try to really get into the "clojure way" and then see if you like it once you've got it

1:30 lowlycoder: i like the java libraries :-D

1:31 replaca: you might or might not, but fighting it pretty much guarantees you'll end up in a place that won't make you happy

1:33 if it turns out that you want Lisp on the java libs there are other solutions (kawa, for instance) that could get you there in a more familiar envinronment

1:33 a lot of us have realized that clojure is awfully well put together, once we let go of what we're used to

1:34 (and I know - I wrote the CL compatible format for clojure :-))

1:34 arbscht: if you haven't already, watch rich's presentations on blip.tv where he explains how clojure is different from CL or Scheme and the rationale behind the changes

1:36 tomoj: replaca: does it have ~r?

1:38 rlb: ...or, if you've spent much quality time with posix threads, his talk covering the ant demo...

1:38 "quality"

1:48 lowlycoder: user=> (def x '(1 2 3 4 5))

1:48 #'user/x

1:48 user=> (map print x)

1:48 (12nil 3nil 4nil 5nil nil)

1:48 doesnt' map generate lazy sequences?

1:48 why does it print 1 2 3 4 5?

1:48 rlb: lowlycoder: because the repl needs to print the result?

1:48 lowlycoder: user=> (def y (map print x))

1:48 #'user/y

1:48 user=> y

1:48 (12nil 3nil 4nil 5nil nil)

1:49 this is intresting, on future 'y' 's, it only shows the nils

1:49 map really is lazy; that is good to know

1:49 any other surprises I should know?

1:49 rlb: hard to know in advance what might surprise you ;>

1:49 If you're coming from s

1:50 Scheme, there's no TCO.

1:50 (tail call optimization), at least no guaranteed TCO.

1:50 You have to use loop/recur explicitly.

1:50 lowlycoder: that i also know

1:50 what else?

1:51 rlb: Not sure offhand. Stuart's book might be helpful.

1:51 And I did find the ant video quite interesting.

1:56 lowlycoder: how do I convert _anything_ to a string?

1:57 str

1:57 whoa, that is so easy

2:00 arbscht: lowlycoder: as I said, watch rich's presentations on blip.tv. that might clear up a number of potential surprises

2:01 hiredman: lowlycoder: str doesn't really work on lazy sequences

2:01 you have to use prn-str

2:02 ,(str (map inc (range 10)))

2:02 clojurebot: "clojure.lang.LazySeq@c5d38b66"

2:02 hiredman: ,(prn-str (map inc (range 10)))

2:02 clojurebot: "(1 2 3 4 5 6 7 8 9 10)\n"

2:02 hiredman: ,(pr-str (map inc (range 10)))

2:02 clojurebot: "(1 2 3 4 5 6 7 8 9 10)"

2:02 hiredman: this is unfortunate, and was not the case once

2:03 lowlycoder: can I download these blip.t episodes?

2:03 hiredman: yes

2:04 lowlycoder: how? on clojure.blip.tv i see the movie but can't see the link

2:04 hiredman: lower right of the page there is a menu called "files" or something similar

2:04 it has links to download mp4s or flvs

2:06 lowlycoder: even after clicking on deatils, I see it it not

2:07 hiredman: ~blip.tv

2:07 clojurebot: blip.tv is http://clojure.blip.tv/

2:07 lowlycoder: i'm looking at clojure.blip.tv

2:08 hiredman: lowlycoder: you have to open one of the videos

2:08 lowlycoder: i clicked on play on one of them

2:08 I don't see where the link is

2:08 hiredman: and on the page for the video there is a menu called "files and links"

2:08 click on it

2:10 lowlycoder: hmm, i actuallllly don't see files and links

2:10 i'm using firefox 3.0

2:10 on ubuntu

2:10 hiredman: on the lower right of the page

2:11 lowlycoder: let's binary search; above or below the line that syas " Subscribe to this show via iTunes, Miro, channels.com or RSS" ?

2:12 hiredman: I think you don't actually have the page for the video open

2:12 lowlycoder: i'm an idiot

2:12 i see it now

2:32 replaca: tomoj: are you still here? yup, it has full ~r support.

2:36 tomoj: nice

2:36 did you do that yourself or does java know how to do that somewhere?

2:44 lowlycoder: whoa, so let works like let*

2:45 hiredman: yes

2:48 replaca: tomoj: sorry, i'm jumping in and out

2:48 wrote it all myself

2:49 doc is here: http://richhickey.github.com/clojure-contrib/doc/pprint/CommonLispFormat.html

2:50 and api overview is on the pprint page: http://richhickey.github.com/clojure-contrib/pprint-api.html#pprint/cl-format

2:52 lowlycoder: is there a wya to convert a string to an integer besides read-string?

2:53 hiredman: ~jdoc Integer

2:53 er

2:54 anyway, there are a few methods there

2:54 Integer also has a constructor that takes a string

2:54 replaca: ,(Integer/parseInt "34")

2:54 clojurebot: 34

2:57 lowlycoder: how do I get the length of a sequence?

2:57 length does not seem to be bound

2:57 hiredman: ,(doc count)

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

2:58 lowlycoder: if I have (def x '(1 2 3 4 5 6 7))

3:00 is there anyway I do a binding of the form [y z]

3:00 to have z = '(2 3 4 5 6 7) ?

3:00 [y z] gets z = 2

3:00 and I can't do [y . z]

3:00 hiredman: ,let [[y & z] '(1 2 3 4 5 6 7)] z)

3:00 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/let

3:00 hiredman: bah

3:01 ,(let [[y & z] '(1 2 3 4 5 6 7)] z)

3:01 clojurebot: (2 3 4 5 6 7)

3:03 lowlycoder: nice; thans

3:04 hiredman: ~destructuring

3:04 clojurebot: destructuring is http://clojure.org/special_forms#let

3:08 lowlycoder: is there a builtin for taking a list and splitting it into the first 100 elements and the rest?

3:08 hiredman: ,(doc split)

3:08 clojurebot: "clojure.contrib.str-utils2/split;[[s re] [s re limit]]; Splits string on a regular expression. Optional argument limit is the maximum number of splits."

3:08 hiredman: lowlycoder: there are docs on clojure.org

3:09 ,(doc split-with)

3:09 clojurebot: "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"

3:09 hiredman: hmm

3:09 lowlycoder: hiredman: i didn't know what to search for :-)

3:10 hiredman: (fn [n s] [(take n s) (drop n s)])

3:11 ah

3:11 ,(doc split-at)

3:11 clojurebot: "([n coll]); Returns a vector of [(take n coll) (drop n coll)]"

3:11 hiredman: http://clojure.org/sequences

3:14 lowlycoder: take & drop, cool :-)

3:20 why does (doc str) work but (doc re-split) not?

3:21 hiredman: ,(doc re-split)

3:21 clojurebot: "clojure.contrib.str-utils/re-split;[[pattern string] [pattern string limit]]; Splits the string on instances of 'pattern'. Returns a sequence of strings. Optional 'limit' argument is the maximum number of splits. Like Perl's 'split'."

3:21 hiredman: re-split is in contrib

3:21 so you might not have it loaded

3:21 lowlycoder: nice; thanks

3:22 hamza: hey guys, i can not call the following method from clojure second argument seems to be optional. http://java.sun.com/javase/6/docs/api/javax/swing/RowFilter.html#regexFilter%28java.lang.String,%20int...%29

3:22 replaca: lowlycoder: for contrib refs see: http://richhickey.github.com/clojure-contrib/index.html

3:22 hiredman: hamza: you have to pass in an array

3:22 lowlycoder: web pages is cool, but I like accessing repl instead

3:22 hiredman: even an empty one

3:23 lowlycoder: user=> (doc re-split)

3:23 -------------------------

3:23 clojure.contrib.str-utils/re-split

3:23 ([pattern string] [pattern string limit])

3:23 ... it works

3:23 hamza: i am calling like so (RowFilter/regexFilter "input" 0 )

3:23 replaca: lowlycoder: you've got to load the namespace your interested in then (as hiredman pointed out)

3:23 lowlycoder: I did :-)

3:23 leading to my comment above of "nice; thanks"

3:23 hiredman: hamza: (into-array Integer/TYPE [0])

3:23 lowlycoder: ah, taht could have been interpreted as hiredman's use of clojurebot

3:23 replaca: but the web page tells you about things that aren't loaded

3:24 yeah, hiredman has a "special" doc function, I think

3:24 hiredman: hamza: java varargs are syntactic suger for passing an array

3:24 hamza: kk it worked why is the syntax different?

3:25 hiredman: clojure doesn't have the syntactic sugar

3:25 alinp: hi

3:25 I have an agent defined like this:

3:25 (def x (agent 0))

3:25 and want to do this:

3:26 (send-off x #(+ %1 %2) 3 4)

3:26 @x -> 7

3:26 what's wrong with it ?

3:26 what I'm doing wrong here ?

3:26 hiredman: ,(doc send-off)

3:26 clojurebot: "([a f & args]); Dispatch a potentially blocking action to an agent. Returns the agent immediately. Subsequently, in a separate thread, the state of the agent will be set to the value of: (apply action-fn state-of-agent args)"

3:26 hiredman:

3:27 in what you described, the function send-off needs to take three arguments

3:27 alinp: it will use the initial state as the 1st param ?

3:28 well .. I send 3 arguments

3:28 but .. still, doesn't work

3:28 hiredman: the function you send-off

3:28 alinp: (#<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to: user$eval--335$fn>)

3:28 hiredman: ^-

3:28 you are send-off'ing a 2 arg function where it needs a three arg function

3:29 alinp: whay is that ?

3:30 hiredman: is the docstring not clear? (apply action-fn state-of-agent args)

3:30 args is [3 4]

3:30 alinp: ah, ok then

3:30 thanks

3:30 missed that

3:42 lowlycoder: user=> (doc do)

3:42 Please see http://clojure.org/special_forms#do

3:42 wtf, if you have room for an online documentation system, why give me a URL?

3:42 hiredman: do is a special form, so there is no var to attach a docstring to

3:43 alinp: hiredman: and this means that all special forms are "documented" this way ?

3:44 lowlycoder: user=> (doc do)

3:44 -------------------------

3:44 do

3:44 hiredman: all six or seven of them

3:44 alinp: ah, ok

3:44 lowlycoder: if the system can look it up to print a message, why can't it put the doc there?

3:45 hiredman: lowlycoder: *shrug*

3:45 it would have to be put inside the doc lookup function

3:46 alinp: user=> (doc doc)

3:46 -------------------------

3:46 clojure.core/doc

3:46 ([name])

3:46 Macro

3:46 Prints documentation for a var or special form given its name

3:46 nil

3:46 " or special form"

3:46 :)

3:47 Fossi: how about not pasting so much stuff in here? both of you. thanks.

3:47 alinp: ,(doc doc)

3:47 clojurebot: "([name]); Prints documentation for a var or special form given its name"

3:47 hiredman: ditto

3:47 ~url

3:47 clojurebot: Excuse me?

3:47 hiredman: er

3:47 lisppaste8: url

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

3:48 hiredman: ~def print-special-doc

3:49 god github is slow

3:51 arbscht: ,(doc foo)

3:51 clojurebot: "/;nil; "

3:52 arbscht: hiredman: thoughts on a patch like this so clojurebot says something sensible when the symbol isn't found? http://gist.github.com/169596

3:53 hiredman: I think you reverse d that patch

3:54 anyway, yes, something should be done about it

3:54 arbscht: so I did, yes

3:54 I can fork clojurebot and do a pull request if you want

3:55 hiredman: I'd have it reply with one of the befuddled responses

3:55 arbscht: heh

3:56 hiredman: if you want, sure, I'd hate to put you through the trouble for something so small

3:57 arbscht: might as well, could be handy in the future

3:59 er, if github co-operates, that is.

4:00 hiredman: ,(doc foo)

4:00 clojurebot: "I don't understand."

4:00 arbscht: :-)

4:00 hiredman: arbscht: abort, abort!

4:07 Fossi: clojurebot: is weird in speaking far too many languages

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

4:08 lowlycoder: does clojure have c++ equiv of /* ... */

4:09 Fossi: C-SPC M-C-;

4:09 that is: i don't think so

4:10 you could write a macro for it

4:10 hiredman: there is commet

4:10 comment

4:10 Fossi: ah, right

4:10 hiredman: but comment is a macro, not really a comment

4:10 arbscht: clojurebot: def defn

4:11 Fossi: (10:13:35) arbscht: clojurebot: def defn

4:11 (10:13:37) clojurebot: (notice) defn: http://tinyurl.com/p7c7c4

4:11 (10:13:49) defn_ [i=defn@anapnea.net] entered the room.

4:11 ;D

4:11 arbscht: ha

4:12 the README says google code still

4:15 AWizzArd: lowlycoder: if you want to comment out a whole form just put #_ in front of it

4:15 ,(println (+ 1 2) #_(+ 3 4) #_(+ 5 6))

4:15 clojurebot: 3

4:15 AWizzArd: ,(println (+ 1 2) #_(+ 3 4) (+ 5 6))

4:15 clojurebot: 3 11

4:16 lowlycoder: how does #_ work?

4:16 i suspect it's a macro for something else

4:16 AWizzArd: The comment macro can also be fine, but you should be aware that it will evaluate to nil.

4:17 lowlycoder: it is a reader macro

4:17 lowlycoder: and it turns out to comment something out

4:17 that evalutes to nil?

4:17 AWizzArd: the reader reads the form and throws it away

4:17 ,(str (+ 1 2) (comment (+ 3 4)) (+ 5 6))

4:17 clojurebot: "311"

4:17 AWizzArd: okay, stupid example as str ignores the nil

4:18 ,(+ 1 (comment 2))

4:18 clojurebot: java.lang.NullPointerException

4:18 AWizzArd: but #_ does not get evaluated

4:18 the reader consumes the form, but won't eval it

4:19 arbscht: comment is nice at the top level for documentary sections etc

4:19 AWizzArd: yes

4:25 hamza: hey guy's, if i use proxy to extend JButton how can i pass variables to its contructor?

4:28 lowlycoder: AWizzArd: thanks

4:30 d2dchat: is there a protected division operator?

4:30 like % ?

4:30 I know traditionally that is used for modulus but

4:30 it can also be protected division

4:31 any function like that avail?

4:38 mebaran151: what do you mean by protected division: the regular clojure one's check for overflow I think

4:38 and div by zero

4:39 Fossi: hamza: ,(doc proxy)

4:42 lowlycoder: so if I (print ...) something in a child thread, it doesn't pop up in the main repl stdout?

4:44 Fossi: i don't think so

4:44 with slime you can switch that

4:45 not sure for the repl

4:56 Neronus: lowlycoder: You could try passing *out* of the repl to the thread at its creation (it has some main function, I guess?) and then binding it in the main function or around the main function

4:59 lowlycoder: (send-off (agent [*out* "foo"]) (fn [[out o]] (binding [*out* out] (println o)))) something like that

5:00 hiredman: lowlycoder: use println instead of print

5:00 or if you must use print, call flush

5:03 Neronus: hiredman appears to be right for child threads, as (.run (Thread. #^Callable (fn [] (println "foo")))) prints to the *out* of its creating thread

5:03 hiredman: :|

5:04 you know no Thread constructor takes a Callable right?

5:08 Neronus: You're right, I meant runnable of course. Works either way :)

5:09 hiredman: I doubt a type hint there would ever give you a performance increase, so even with #^Runnable, best to omit the hint

5:22 Neronus: This wan't about performance, this was about a memory associated wrong. With ThreadPoolExecutor.sumbit I had to do that declaration, or clojure didn't know which .submit I meant (I didn't care, but how should the compiler know that?)

5:25 lowlycoder: this is really dumb

5:26 how do I load in "test.clj" from the current directory

5:26 (use 'test) is not loading it in

5:27 hiredman: ,(doc load)

5:27 clojurebot: "([& paths]); Loads Clojure code from resources in classpath. A path is interpreted as classpath-relative if it begins with a slash or relative to the root directory for the current namespace otherwise."

5:27 hiredman: ,(doc load-file)

5:27 clojurebot: "([name]); Sequentially read and evaluate the set of forms contained in the file."

5:32 lowlycoder: I have gears.clj in current directory; I can do (use '(gears)) ; gears.clj has a function (go) defined in it ... why can't I call (gears.go) ?

5:35 Neronus: You can do either (go) after use because you refer each defined symbol of the namespace gears in the namespace doing the (use ...), or you can do gears/go, which is the way to refer function go of namespace gears

5:36 lowlycoder: (ns gears)

5:37 that is the first line of gears.clj

5:37 do i need to export go?

5:37 Neronus: na, if you defined go by (def) or (defn) its exported

5:37 lowlycoder: hmm, user=> (use '(gears))

5:37 nil

5:37 user=> gears/go

5:37 java.lang.Exception: No such namespace: gears (NO_SOURCE_FILE:0)

5:38 ~/genesis:master*$ cat gears.clj| grep go

5:38 (defn go []

5:38 clojurebot: I don't understand.

5:39 Neronus: lowlycoder: (use 'gears)

5:40 lowlycoder: user=> (use 'gears)

5:40 java.io.FileNotFoundException: Could not locate gears__init.class or gears.clj on classpath: (NO_SOURCE_FILE:0)

5:41 nice, it works now

5:42 i had incorretly set up class paths

5:42 Neronus: great :)

7:18 Does anyone here know if the loading of a string literal via ldc (bytecode instruction) causes the class java.lang.String to be loaded?

7:22 Ah, found it. thanks

7:30 Fossi: Neronus: so?

7:51 Neronus: If the constant pool entry to be loaded by ldc is to be loaded for the first time, a new String object will be constructed. Thus, String has to be loaded

7:52 JVMS 5.1

8:55 AWizzArd: I have (def x {:abc "ABC"}) and defined an inline accessor for it: (definline abc [obj] `(:abc ~obj)). So (abc x) ==> "ABC".

8:56 I set *warn-on-reflection* to true. Now (.toLowerCase (abc x)) gives me a warning as expected. But unfortunately (.toLowerCase #^String (abc x)) also does. If abc is not an inline macro but a function then the type hint works.

8:56 Any idea why it does not work for the inline?

8:57 Chouser: Use macroexpand and *print-meta* to see what the compiler actually consumes.

8:58 hm, except macroexpand doesn't work on :inline

8:58 AWizzArd: Yes, it's strange, I can't macroexpand it.

8:58 right

8:58 Chousuke: maybe you need to do #^String `(:abc ~obj)

8:58 AWizzArd: In the inline itself? I will try that.

8:58 Chousuke: ,(meta #^String `test)

8:59 clojurebot: nil

8:59 Chousuke: hmm

8:59 Chouser: well, I'm pretty sure this is what's happening:

8:59 Chousuke: ,(meta #^String 'test)

8:59 clojurebot: nil

8:59 Chousuke: :/

8:59 Chouser: the String :tag is put on the list (abc x). Then the :inline is expanded, and the results replace the old list

8:59 AWizzArd: Chousuke: oh cool trick, it works when I do (definline abc [obj] `#^String (:abc ~obj))

9:00 Chouser: those new results have no tag, thus the reflection warning

9:00 ,(meta '#^String test)

9:00 clojurebot: {:tag String}

9:00 AWizzArd: Yes, that could be it Chouser. But good that Chousukes trick works. Thanks you two.

9:01 Chouser: rhi<tab> ... rhi<tab> ... *sigh*

9:02 Chousuke: I just added autofn support for my reader.

9:02 AWizzArd: Chousuke: what is that?

9:02 Chousuke: #()

9:02 the worker function is *ugly* but at least it works :P

9:02 AWizzArd: Chouser: yes, he takes some days off it seems :)

9:04 Chouser: AWizzArd: he said a week. It's now been more.

9:04 how dare he. ;-)

9:05 oh, hooray.

9:06 drewr: rhickey: welcome back!

9:06 Jenncaspot: hi

9:06 rhickey: hi all!

9:06 Chouser: Chousuke: as soon as it passes the test suite, I'll start using it.

9:06 Jenncaspot: i am new here

9:06 Chouser: Jenncaspot: welcome.

9:07 Jenncaspot: thanks

9:07 this is my first time to chat

9:07 AWizzArd: oh funny, rhickey, only 2 minutes ago we were talking about you and your holidays :-)

9:07 wb

9:08 rhickey: AWizzArd: that would be holiday (singular), first without working on Clojure since I released it

9:10 AWizzArd: It's a good thing.. holiday without your child - nice to have from time to time.

9:59 LauJensen: rhickey: In your absence I updated http://en.wikipedia.org/wiki/Functional_programming to include Clojure under functional languages used in industry - dunno how they could have forgot :(

10:00 rhickey: LauJensen: putting it first probably isn't a good idea

10:00 LauJensen: Oh. I felt it would be wrong to put it behind any of the inferior languages in the same category.

10:01 If you had updated the site, then I could see a potential problem :)

10:02 rhickey: as the most recent entrant, Clojure should go last

10:03 being pushy won't win Clojure any converts, and may seem fanboyish, and thus less credible

10:04 let's stay modest, as a community

10:04 Fossi: i think the list should be alphabetically ordered

10:04 which it also seems to be

10:05 LauJensen: Its your language and therefore your call. I just feel it would be wrong to put Clojure in a less visible position and thereby perhaps leading some down the wrong path first. I'd hate to be the cause of somebody wasting a year in F# because I tried to display a false sense of humility. I know it seems like I'm overthinking something as simple as the order of mention, but I would really feel bad if it happend anyway

10:06 Fossi: then again such lists with "... including [list goes here]" are always a discussion topic anyway

10:07 and a reference would surely help

10:07 LauJensen: rhickey: I've updated the page now

10:07 Fossi: especially since the other mentions have them

10:07 LauJensen: its the last mention, although in uppercase red letters size 72

10:07 rhickey: LauJensen: thanks

10:07 LauJensen: np

10:09 Fossi: LauJensen: also check the "R and S-Plus" part of the discussion page

10:11 LauJensen: I dont have the patience for those types of discussions

10:12 Fossi: yes, but you seem to have the time to make an edit

10:12 so imho you either do neither or both

10:12 but be free to be reverted

10:18 i want to modify the values in a map. anybody got a merge-with example or can tell me how to return a (new?) MapEntry?

10:19 tomoj: what do you want a MapEntry for?

10:19 AWizzArd: Fossi: maybe update-in can do the job

10:25 Fossi: Is the documentation grammatically wrong or is it my brain being too stupid to parse it?

10:25 ,(doc update-in)

10:25 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

10:26 Chouser: ,(assoc {:a 0, :b 1, :c 2} :b 99)

10:26 clojurebot: {:a 0, :b 99, :c 2}

10:26 Chouser: Fossi: do you want more than that?

10:27 Fossi: also ,(update-in {:foo 'foo :bar 'bar} #(do (println %) %)) doesn't work so well

10:27 for every val in the map, i want to add something to it

10:27 Chouser: add as in + or as in conj?

10:27 Fossi: or i might even replace it

10:28 Chouser: ,(into {} (for [[k v] {:a 0, :b 1, :c 2}) [k (+ 100 v)]))

10:28 clojurebot: Unmatched delimiter: )

10:28 Chouser: ,(into {} (for [[k v] {:a 0, :b 1, :c 2}] [k (+ 100 v)]))

10:28 clojurebot: {:c 102, :b 101, :a 100}

10:28 Fossi: ,(update-in {:foo 'foo :bar 'bar} #(do (println %) %))

10:28 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$update-in

10:28 Fossi: ,(update-in {:foo 'foo :bar 'bar} #(do (println %) %) nil)

10:28 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: sandbox$eval__2411$fn__2413

10:29 Fossi: seems k &ks is not optional, but has to be a vec

10:29 Chouser: update-in is for nested maps

10:29 and probably not the best choice if you're going to change every value of the map

10:30 if you're going to touch every value, it's probably best to iterate over them (using 'map', 'for', etc.) and then build them back into a map using 'into', as I demonstrated.

10:32 Fossi: yeah, i had a map there to start with, but got confused how to make it keep the map type

10:33 "map"

10:33 Chouser: If you want to keep the particular variety of map you started with (sorted or whatever), you can use (into (empty my-map) ...) instead of (into {} ...)

10:47 cemerick: rhickey: welcome back :-)

10:55 cschreiner: On the Macintosh; In Emacs 22 (Carbon Port, CVS version) you can use the variable ‘mac-control-modifier’ to remap the Control key.

10:55 What denotes the caps-lock key?

10:57 Chousuke: I think you need to remap caps-lock from the keyboard settings.

10:57 cschreiner: (wrong group, heh)

10:57 So I cannot do this locally for emacs only

10:58 Chousuke: try M-x apropos capslock? :P

10:58 clojurebot: x is y

10:59 Chousuke: I mapped mine through the keyboard preferences to control and then in emacs I swap meta with control

10:59 I need to be careful with cmd-w now though :P

10:59 cschreiner: hehe

11:00 Chousuke: in emacs it'll be ctrl-w. but in other apps it'll close the window ;(

11:03 cschreiner: do you happen to know how I turn *off* eldoc-mode? ;( it's slowing down scrolling in my buffers

11:03 there's turn-on-eldoc-mode but no turn-off...

11:03 tomoj: M-x eldoc-mode ?

11:06 Chousuke: ah, it works as a toggle. duh

11:07 Neronus: For gtk-apps, you can tell gtk to use emacs like keybindings... e.g. pidgin ignores that though and closes the window none the less

11:08 again, IIRC

11:08 Fossi: i have [[k1 v1] ...] and [[k1 x1] ...] and like to merge them as [k1 [v1 x1] ...]. any hints?

11:09 Chousuke: easiest to make those into maps first, then use (merge-with vector ...)

11:11 ,(vec (merge-with vector (into {} [[:k1 1] [:k2 2]]) (into {} [[:k1 2] [:k3 3]])))

11:11 clojurebot: [[:k3 3] [:k2 2] [:k1 [1 2]]]

11:13 Chousuke: hmm

11:14 I wonder if there's something wrong with the way clojure-mode (or clojure-swank) does eldoc. it doesn't cause lag with elisp :/

11:14 Fossi: thanks

11:20 Chouser: Hm, I'd like to use the timeout arg to promise's CountDownLatch.await()

11:24 danlarkin: Hey LauJensen, why the move to gitorious?

11:24 alrex021: I have a test in attr-map of my function: (defn #^{:test (fn [] (is (= (add3 6) 9)))} add3 [n] (+ 4 n))

11:24 I get a FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:1) as expected....but I also get a :ok as a result

11:25 LauJensen: danlarkin: Speed and consistent use of markup all around the site.

11:25 (hey btw)

11:25 alrex021: expected: (= (add3 6) 9) actual: (not (= 10 9)) ....and then on last line REPL I see .... :ok ...how does tht make sense?

11:27 danlarkin: LauJensen: I see, good reasons

11:28 Chouser: alrex021: looks like a mismatch between 'is' and 'test'

11:28 stuartsierra: alrex021: you're mixing clojure.test with the older clojure.core/test.

11:28 Chouser: alrex021: 'is' returns true or false. 'test' expects an exception on failure, not just 'false'

11:28 stuartsierra: Run your tests with clojure.test/run-tests.

11:28 alrex021: oh I see

11:29 rhickey: Chouser: timeout on deref of promise? returning what if timed out?

11:29 alrex021: so when using functions from clojure.test ...use run-tests

11:30 Chousuke: rhickey: you could require the user to specify a timeout value

11:30 alrex021: so run-tests will actually look at functions in namespaces :test and treat it the same way as deftest functions?

11:30 just want to make sure I understand this

11:31 Chousuke: rhickey: then it could look like (deref obj timeout ::timeoutval)

11:31 Chouser: rhickey: yes. nil would work in this case, though I suppose one might eventually want to specify the value to return on failure.

11:32 rhickey: I'm not sure I want to overload deref for this, but both future and promise have potentially blocking derefs and timeout options

11:33 Chouser: yeah, it stretches deref quite a bit. maybe a new interface. :-/

11:33 since I'm on 1.0 and have my own copy of 'promise' anyway, I may just add (invoke [timeout unit] ...) to the proxy.

11:34 * rhickey can't wait until all these interfaces are in a single small clojure file

11:34 Chousuke: heh

11:34 alrex021: What is the best practice, if any, when writing tests in clojure.....to have them closely tied to function using :test or to define them using deftest macro?

11:34 cemerick: adding an available?/done? fn to IDeref would make setting up timeouts on any IDeref pretty straightforward with latch

11:35 * cemerick beats the dead horse on the former again

11:35 Chouser: cemerick: those may be related.

11:35 cemerick: I mean, things that might want a timeout on "deref" may also be the things that you'd want to ask 'available?' of.

11:35 rhickey: cemerick: I'm not sure I understand use case for timeouts on non-future/promise refs

11:35 clojurebot: for is not used enough

11:36 cemerick: Chouser: yeah, I know...trying to build my use-cases :-)

11:36 rhickey: In any case it's not going in IDeref, maybe IMightDerefIfImReady?

11:37 Chouser: perfect

11:37 stuartsierra: alrex021: it's really a matter of taste.

11:37 cemerick: rhickey: there is none -- I'm just pitching for an available/done marker on IDeref in general, which could be leveraged by a timeout mechanism

11:37 rhickey: IMightDerefIfYoureLicky

11:37 cemerick: avaialble/done just invite polling, which is bad

11:38 stuartsierra: alrex021: In general, I would recommend only adding :test metadata directly if you're using the clojure.core/test, which expects an exception on failure.

11:38 Chouser: The question you have to ask yourself is, do you feel licky. Well do you, punk?

11:38 LauJensen: No.. Not real licky Chouser... :)

11:38 cemerick: rhickey: my use case is with regular delays, to avoid incurring computation in certain circumstances

11:38 Chouser: LauJensen: yeah, me either.

11:39 stuartsierra: alrex021: Personally, I use clojure.test/with-test to add small unit tests to isolated functions; I use deftest to write broader integration tests.

11:39 cemerick: right now, I carry around an atom/delay pair to track whether the latter's been accessed yet or not

11:40 alrex021: stuartsierra: I must admit that I am loving the concept of testing using :test .... I'd prefer to look at source of function see its test right there. like the doc string

11:40 stuartsierra: alrex021: That's what clojure.test/with-test is for.

11:41 ,(doc clojure.test/with-test)

11:41 clojurebot: Titim gan éirí ort.

11:41 stuartsierra: wha?

11:42 rhickey: cemerick: would you be satisfied with deref-with-timeout vs done?/available?

11:46 cemerick: probably not -- I use the atom/delay pair to help amortize the cost of certain operations in a data structure

11:49 is the temptation to poll really that strong with some?

11:49 rhickey: cemerick: then I don't understand the semantics of available? - you haven't asked for anything to be done, who sets the atom?

11:53 m3lling: day 2 of this... http://blog.thinkrelevance.com/2008/9/16/pcl-clojure-chapter-3

11:54 personally i think there is a bug in clojure somewhere.

11:54 checked my stuff out with git and built it.

11:54 the example does work if I remove the spaces from the data and put in a -

11:55 Dixie-Chicks ... for example

11:55 otherwise it's java.lang.ArrayIndexOutOfBoundsException: 9

11:56 cemerick: rhickey: The atom always starts at false, and is flipped to true when the delay is accessed.

11:56 Specifically, the delay is deref'd (and the atom reset to true) on a query, which will build out the portion of the data structure it represents. On removal and swaps, those parts of the structure that haven't yet been accessed at all are just replaced with a new atom/delay. Those that have are replaced with an updated value from the already-forced delay.

11:56 duck1123: are you sure "Dixie Chicks" is quoted appropriately?

11:56 m3lling: i copied it from the blog.

11:56 doube-quotes...?

11:57 tomoj: that looks like it was written almost a year ago

11:57 m3lling: ^

11:57 m3lling: actually, i believe the problem is when trying to load the data from the file.

11:57 duck1123: I don't see anything that looks like it wouldn't still apply though

11:57 m3lling: it doesn't get reparsed right.

11:59 i have a simpler version on StackOverFlow... http://stackoverflow.com/questions/1291765/how-do-i-persist-and-restore-my-defstructs-to-a-file/1294018#1294018

11:59 rhickey: cemerick: got it. It's interesting because in the non-async case of delay the has-been-calculated question is less about waiting for something else to complete, as with future/promise

11:59 m3lling: (def x (struct bookmark "news.ycombinator.com" "News" "Tech News")); Doesn't handle "Things in quotes"

12:00 (save-db x "url-db.txt") ... (def y (load-db "url-db.txt")) .. will fail...

12:00 Chouser: you need prn instead of print

12:01 or (pr-str db) instead of (with-out-str (print db))

12:02 cemerick: rhickey: yeah. I think the available? semantics would apply to all IDerefs, though.

12:02 stuartsierra: m3lling: I don't think you can pr/read struct-maps right now.

12:02 cemerick: sort of useless with refs, but still applicable

12:02 m3lling: so this example doesn't work?

12:02 rhickey: cemerick: I'm not sure I agree, but now see the utility for delay

12:02 m3lling: it does work if no spaces are in the values

12:03 cemerick: rhickey: hey, it makes sense to me! ;-)

12:03 tomoj: I had trouble where pr'ing structmaps with *print-dup* true printed stuff that couldn't be read

12:03 stuartsierra: m3lling: it will work if you use pr instead of print, but when you read it back in, you'll get plain maps instead of struct maps.

12:03 tomoj: #=(clojure.lang.PersistentStructMap/create ...)

12:04 rhickey: I think delay/promise/future might support something like that, and promise/future something like deref-with-timeout. Name suggestions for functions and interfaces welcome

12:04 tomoj: "no matching method found: create"

12:05 stuartsierra: tomoj: Yes, I've had the same problem.

12:06 m3lling: k. i changed the save-db and it works.

12:06 thx.

12:06 cemerick: deref-before seems like a no-brainer

12:07 or deref-within maybe

12:08 the terracotta guys are growing (http://blog.terracottatech.com/2009/08/terracotta_and_ehcache_a_marri.html). Glad they're doing so well.

12:10 m3lling: are we sure this thing isn't a struct when it's read back in? (println (= x y)) is true.

12:10 x is original and y is loaded value.

12:10 stuartsierra: tomoj: created a ticket: http://www.assembla.com/spaces/clojure/tickets/176-structs-printed-with-*print-dup*-true-cannot-be-read

12:11 tomoj: stuartsierra: cool

12:11 hamza: how can i create a java.awt.geom.RoundRectangle2D.Double?

12:11 m3lling: k

12:11 hamza: (new java.awt.geom.RoundRectangle2D.Double ...) creates error

12:11 tomoj: I went down the road towards manually serializing/deserializing from json

12:12 stuartsierra: hamza: is "Double" a nested class of RoundRectangle2D?

12:13 cemerick: yes, it should be java.awt.geom.RoundRectangle2D$Double

12:13 hamza: dunno in java i can get it using g2.draw(new RoundRectangle2D.Double(0,0,(getWidth()-3),...

12:14 cemeric thx it worked..

12:14 cemerick: hamza: RoundRectangle2D$Double is the real classname -- the period in java source code is just syntactic sugar

12:16 hamza: one more question if i proxy say JButton how can i override its contructor?

12:16 cemerick: you can't override constructors in proxies

12:17 hamza: is there any other way to do it?

12:17 cemerick: but you probably don't want to override its constructor, just provide it with whatever args you want in the second vector provided to the proxy fn

12:17 ,(proxy [javax.swing.JButton] ["some text"])

12:17 clojurebot: java.lang.IllegalStateException: Var null/null is unbound.

12:18 cemerick: huh, hadn't seen that before

12:18 does clojurebot run in headless mode or something?

12:20 hamza: what about super call how can i refer it?

12:22 cemerick: hamza: see proxy-super

12:38 oh, how I want to stop ever writing java

12:39 * cemerick starts writing a java impl of flatten :-(

12:41 rhickey: cemerick: in Java because...?

12:41 cemerick: rhickey: legacy code base, java 1.4 compat required.

12:41 rhickey: ah, can't help you there

12:42 cemerick: I shouldn't complain, this is the first java I've written in at least a month.

12:42 yeah, I've gone astray for 15 min

12:47 cable_: rhickey: fantastic job with everything, ive finally found a JVM language worth switching to

12:47 rhickey: cable_: thanks!

12:48 technomancy: so... is there any way to build the fnparse library without an IDE?

12:48 the build.xml files are a bit intimidating

12:58 Chousuke: Progress! (eval (first (item-seq (rh-from-str "(defn foo [#^String x] (.toUpperCase x))")))) now gives me a foo function without any pesky reflection warnings.

12:59 Chouser: Chousuke: that's your reader?

12:59 stuartsierra: ok, I think clojure.contrib.http.agent is finally finished.

12:59 Chousuke: yeah.

12:59 Tomorrow I'm going to try if my reader can read core.clj :P

12:59 Chouser: Chousuke: very cool

13:00 Chousuke: I still don't have support for \characterescapes but that should be simple.

13:00 and it's probably more lenient on what it accepts as tokens than the java reader

13:04 clojure.lang.reader> (= (read-string test-str) (my-read-str test-str))

13:04 tru

13:04 e

13:04 reassuring

13:05 (metadata is probably different though)

13:12 technomancy: hiredman: what rev of fnparse are you running clojurebot on?

13:17 hiredman: technomancy: running ant just always worked for me, but I haven't built it in a few months

13:18 technomancy: I'm not sure

13:22 technomancy: I got it to compile by tearing out a bunch of crap from the build.xml and hardcoding some classpath vars in, but now I'm getting wrong number of args

13:23 if you've got a sha1 rev for me to work from that'd be awesome

13:25 hiredman: I don't :(

13:25 technomancy: OK, I'll go back a couple months

13:25 see if that does it

13:27 cemerick: technomancy: is this a netbeans build process?

13:28 technomancy: cemerick: yeah, actually I think it's just copied from the enclojure build process

13:28 cemerick: well, enclojure is a netbeans module suite, which is a whole lot more complicated than a regular project.

13:28 For the latter, you should be able to just set a system property to bootstrap the whole thing.

13:29 what do you get if you just "ant jar" the thing?

13:30 technomancy: cemerick: it was complaining about not having clojure.jar on the classpath

13:30 apparently ignoring the CLASSPATH environment var

13:30 cemerick: hrm. what's the github url?

13:30 (the CLASSPATH env var is a scourge on our society IMO, but anyway... :-) )

13:31 technomancy: cemerick: I don't use it unless I'm desperate. =)

13:31 http://github.com/joshua-choi/fnparse

13:32 cschreiner: I loathe the classpath concept

13:34 cemerick: technomancy: ugh. The clojure jar is set up as a platform library, e.g. you'd have to either be in a properly-configured NB IDE or have an NB platform harness around configured just like Joshua's in order to get it to build.

13:35 Not the best thing to do with a lib that's going to get built elsewhere (e.g. set up core stuff as platform libraries)

13:35 Chousuke: I don't think the classpath is that different from LD_LIBRARY_PATH... the main problem I guess is that classes aren't versioned so you can't have two versions of the same class at the same time. :/

13:38 technomancy: cemerick: sounds like I just need to get the author to get his build process fixed then

13:38 cemerick: heh, people are touchy about their build processes :-)

13:38 but yeah, I'd say it's essentially unbuildable as-is, based on my skimming of the project files

13:38 technomancy: well I'm on metered 3G bandwidth right now, so there's no way I'm downloading netbeans. =)

13:39 cemerick: you'd still have to set up clojure as a "platform library", which is ill-advised outside of very constrained circumstances.

13:40 e.g. ties you to your current IDE, unless you're building against an internally-canonical NB platform harness (which we happen to do in one case, but for very good reasons)

13:41 technomancy: well I can try my "disable the tests and hardcode the classpath" approach with an earlier revision

13:41 hiredman: what do you use fnparse for?

13:41 Chouser: Chousuke: LD_LIBRARY_PATH is not recommended either -- there are global config files that are preferred, but AFAIK the jvm has no such thing.

13:41 technomancy: could I just rip out that functionality?

13:42 looks like just factoids?

13:42 what exactly are ... factoids?

13:46 hiredman: clojurebot: clojure?

13:46 clojurebot: clojure is cheating

13:46 hiredman: that is a factoid

13:47 duck1123: "You can't just have concurrency without having to worry about deadlocks, that's cheating"

13:47 technomancy: hiredman: ah, so all the dictionary stuff?

13:47 hiredman: yeah

13:47 technomancy: would be a shame to lose that.

13:47 hiredman: it'd didn't always uses fnparse

13:52 does fnparse need to be built? maybe just jar up the source?

13:52 technomancy: maybe

13:52 I'll add that back in later once I have it running

13:54 hiredman: ugh

13:54 java.lang.IllegalArgumentException: Wrong number of args passed to: fnparse$followed-by (factoids.clj:14)

13:55 technomancy: yup. =\

13:56 hiredman: I think I must be using pre-monad fnparse

13:57 ugh

13:57 it returns a map now

13:57 technomancy: do you want the working fnparse.jar I have?

13:57 technomancy: sure

13:58 hiredman: http://www.thelastcitadel.com/lab/fnparse.jar

13:58 technomancy: thanks

14:13 hiredman: would it be a lot of hacking to get clojurebot running in multiple channels?

14:21 this doesn't seem to... work. at all.

14:22 changeNick and joinChannel are no-ops

14:23 sendMsg seems to work though

14:27 konr: What should I use as a GUI designer with swing?

14:32 cemerick: konr: NetBeans matisse is pretty good

14:32 apparently, the instantiations swing designer is superior, but I'm decidedly not an eclipse fellow

14:53 mebaran151: are there any web frameworks a little lighter than compojure out there

14:54 something that doesn't have any batteries for html etc

14:55 dnolen: compojure about as light as it gets it seems to me. I personally never use it's built in HTML facilities, I prefer Enlive.

14:55 stuartsierra: mebaran151: ring

14:55 mebaran151: does ring have a routing layer?

14:55 dnolen: compojure is actually heavily based on ring's routing layer.

14:55 stuartsierra: http://github.com/mmcgrana/ring/tree/master

14:56 Does compojure use Ring internally, or just implement the same API?

14:56 mebaran151: oh nice

14:56 and can I easily make a war out of a ring app

14:56 it's http, just without any html

14:56 dnolen: stuartsierra: I forget how closely related their codebase is...

15:02 LauJensen: Anybody know of a simple quick java image processing lib that I can use for cropping and scaling ?

15:10 mebaran151: I think java.awt.image might have some useful classes for this sort of thing

15:11 cemerick: Cropping is pretty straightforward just using the standard Java2D stuff.

15:11 Scaling is pretty complicated, and Image.getScaledInstance is often not what you want: http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

15:12 cable_: there's jai as well

15:12 cemerick: SwingX contains some utility functions that implement the recommendations of the above article, which it mentions.

15:18 tomoj: stuartsierra: I don't think it uses ring, as I didn't have to download ring to get compojure to work

15:19 stuartsierra: right, makes sense

15:20 LauJensen: Alright - Thanks alot guys

15:21 dnolen: LauJensen: while it's definitely not simple, the Advanced Imaging library does have a lot of functionality, I've always hoped someone would created a simpler interface to it.

15:22 hiredman: technomancy`: I don't think it would take that much

15:22 I have clojurebot running in here and in #clojurebot

15:55 mebaran151: it's nice to have only one type of datastructure, the seq

15:56 a lot of my old oop code seemed to be used to repurpose various types of reducing operations over subtly different collections

15:56 LauJensen: dnolen: A bit beyond the scope of this project - But remind me next time something like this comes up :)

16:05 hiredman: http://twitter.com/clojure/status/3382120972 <-- ha ha

16:10 Chousuke: :p

16:10 hmm

16:11 cemerick: does rhickey control the clojure twitter acct?

16:11 hiredman: clojuredev

16:11 clojure is someone else, I assume

16:11 Chousuke: if I have a function that takes a seq (aseq) as a parameter and I want to do this: (let [aseq (do-some-stuff-that-consumes aseq)] ...), how do I avoid holding onto the head?

16:11 cemerick: ah, that explains the Germany location.

16:14 Chousuke: hmm. or does nth hold on to the head of lazy seqs? that was what I tested with :/

16:18 LauJensen: Looking at Swing, its not obvious to me how I would render an image, and then provide some easy way of stretching out a rectangle for cropping it. Containing the image could be done with ImageIcon, but then what ?

16:21 Chousuke: hm

16:22 let seems to cause things to hold onto their head

16:23 ((fn [aseq] (let [aseq (nth aseq 1000000)] aseq)) (iterate inc 1)) fails, but simply ((fn [aseq] (nth aseq 1000000)) (iterate inc 1)) doesn't.

16:26 LauJensen: First one doesnt fail here

16:27 Chousuke: try with a bigger n?

16:28 Chouser: I don't think much of anything about swing is obvious.

16:29 cable_: heh re: swing

16:30 LauJensen: Chousuke: yea x50 blows the heap after a while

16:30 Chousuke: I wonder why that is.

16:31 LauJensen: I'm ashamed to say, that Rich actually explained it a couple of weeks ago, but I forgot

16:31 Chouser: of course it does -- your are returning the head, so it must be retained

16:31 oh.

16:31 wait.

16:31 stuartsierra: When you let-bind the head of a sequence, the compiler doesn't know that you're not going to use it latert

16:32 Chousuke: hmm

16:32 stuartsierra: (let [aseq (make-big-sequence)] (consume aseq) ... what happens here?)

16:32 Chouser: let is in the tail position, so it could theoretically null out the earlier aseq. Apparently it doesn't.

16:33 stuartsierra: yeah, I think the analysis for whether or not aseq gets consumed could get pretty complicated

16:35 Chousuke: hmm

16:36 so how do I avoid holding on to the head of the function parameter at all?

16:36 it seems using let will cause it to be held, no matter what I do :(

16:36 Chouser: they get nulled out before whatever you call in the tail position, I believe.

16:36 LauJensen: Didnt Rich give an example of how he rewrote filter to avoid retaining the heaed?

16:36 Chousuke: ((fn [aseq] (let [foo (nth aseq 1000000)] foo)) (iterate inc 1)) also boom

16:37 cemerick: LauJensen: You'd need to handle the rendering of the lasso and such yourself. I'm not familiar with any libraries that provide a lasso "control".

16:37 Chousuke: ((fn [aseq] (nth aseq 1000000)) (iterate inc 1)) no boom, but no good either ;(

16:37 LauJensen: Chousuke: How about ((fn [aseq] (let [foo (nth aseq 1000) bar 5] ...) ?

16:38 Chousuke: LauJensen: adding more stuff to the let makes no difference.

16:38 LauJensen: Sure about that?

16:38 Chousuke: user=> ((fn [aseq] (let [foo (nth aseq 1000000) bar 5] foo)) (iterate inc 1))

16:38 stuartsierra: Chousuke: what exactly are you trying to do, anyway

16:38 Chousuke: java.lang.OutOfMemoryError: Java heap space (NO_SOURCE_FILE:0)

16:39 LauJensen: k

16:40 Chousuke: stuartsierra: well, in my reader I currently do (let [[item rh] (consume rh)] ...) a lot.

16:40 stuartsierra: but if that causes the old rh to be held, it causes unnecessary slowdown and memory use :(

16:46 Chouser: yeah, that's a bit tricky.

16:51 Chousuke: Hi, technomancy. I have a question for you. eldoc-mode seems to cause some rather nasty lag within clojure buffers in my Cocoa emacs when scrolling lines. I suspect swank-clojure is to blame... it seems to try connecting to the clojure instance immediately when I scroll to a new line, somehow blocking rendering when I hold down the scroll key. elisp buffers don't have this

16:51 behaviour, and I noticed they have a slight delay before the arg documentation appears in the minibuffer.

16:51 But I have no idea where, or how, to fix that :/

16:52 technomancy: Chousuke: I believe eldoc works with an idle timer...

16:52 so it shouldn't even try to activate until you've paused on a line

16:53 what's your value for eldoc-idle-delay?

16:53 Chousuke: looks like it's not working in my clojure buffers :/

16:53 clojurebot: clojure is a very attractive hammer with a nice heft to it

16:53 Chousuke: I'll check.

16:55 Chouser: Chousuke: do you have a specific example of where you're running into that OOM error?

16:56 Chousuke: I'm not getting it with my reader yet, fortunately.

16:57 but since it appears with the (let [foo (use foo)] ...) pattern, it's quite certainly there :P

16:57 technomancy: it was 0.5. I set it to 1.0, with no apparent effect.

16:59 technomancy: it looks like it's ignored

17:00 technomancy: elisp buffers honour the value, but clojure buffers don't seem to.

17:00 technomancy: weird; I can't repro myself. and it only occurs when eldoc-mode is on?

17:00 Chousuke: yeah.

17:00 technomancy: try ruling out platform-specific problems... do you get it when you run in terminal Emacs?

17:03 LauJensen: Dudes and Dudettes, how do I proxy my way out of something like this

17:03 Chousuke: hmm, clojure-mode doesn't even work in my terminal emacs :P

17:03 LauJensen: class SliderListener implements ChangeListener { public void stateChanged(ChangeEvent e) {

17:03 technomancy: we have more than one dudette now?

17:03 Chousuke: probably because it's 22.1

17:04 technomancy: Chousuke: yeah, can you run your 23 install with -nw?

17:05 Chousuke: hmm, it still fails to load. it seems I have some Cocoa-specific configs

17:05 technomancy: is this a post-1.0-ism? (import (java.util.logging Logger Level))

17:06 Chousuke: yeah, I try to toss those into a (when (= window-system 'ns) block

17:06 but that sounds like a yak shave

17:07 hiredman: technomancy: yes

17:08 technomancy: Chousuke: how much do you have on top of the standard clojure-slime-config?

17:08 hiredman: I think sometime post 1.0 the need to quote stuff in import and require and use went away

17:08 technomancy: are you on the starter kit?

17:08 hiredman: cool; thanks

17:08 I'm thinking about backporting contrib's logging lib to 1.0-compat

17:09 Chousuke: technomancy: looks like it happens only in Cocoa emacs.

17:09 technomancy: Chousuke: not sure I can help then. =\

17:09 very strange that the idle-timer behaviour is different

17:10 maybe in the mean time I can clean up the obscene amounts of trailing whitespace in this logging.clj file. =\

17:10 Chousuke: technomancy: no, wait.

17:10 technomancy: clojure-mode still ignores the delay

17:11 the terminal version is just quick enough that it doesn't mind the lag I guess.

17:14 I suspect that if I disable the delay, elisp buffers will get laggy too

17:14 I'll try.

17:14 technomancy: Chousuke: are you using the starter kit? how much do you have on top of clojure-slime-config?

17:17 Chousuke: technomancy: no. I cloned this as a base: http://github.com/purcell/emacs.d/tree/master

17:17 but I have quite many changes to it already.

17:17 though, nothing to clojure-mode that should affect this.

17:18 and I tested on elisp buffers... they work fine even with no delay it seems.

17:18 technomancy: Chousuke: would be interested to know if you could repro with the starter kit as per http://technomancy.us/126

17:18 but again: kind of a yak shave

17:19 hiredman: ~yak

17:19 clojurebot: fastest sheers on IRC

17:25 Chousuke: hmm.

17:25 clojure-install seems to have taken over emacs :P

17:25 technomancy: it does take a while unfortunately

17:25 no concurrency =\

17:26 bitbckt: It's even worse when git:// is blocked...

17:26 Chousuke: I wonder if it's even possible to have proper concurrency in emacs.

17:27 technomancy: Chousuke: well lexical scope is targeted for 24

17:27 that's the main thing holding it back

17:29 Chousuke: emacs starter kit has no problems it seems.

17:30 I guess it's something in my config.

17:30 JAS415: i had better luck doing a manual install

17:31 was not too complicated after i figured out what the heck classpaths are

17:32 technomancy: JAS415: what problems were you seeing specifically?

17:32 curious

17:32 Chousuke: Maybe I should see if I could move my config on top of emacs starter kit

17:33 JAS415: well it was just a matter of I have sbcl installed as well as clojure, and I had trouble finding the stuff that I needed to manipulate to add different libraries and stuff to the classpath

17:34 Chousuke: looks like it has most of the features I care about anyway

17:34 JAS415: also i wanted to build from the most recent github version

17:34 so i kind of used clojure-install to get an idea of what things were supposed to look like

17:35 then i uninstalled it and reinstalled it again so I had an idea of how it actually worked

17:35 (reinstall by hand)

17:35 technomancy: oh yeah, I never bothered to figure out how to use it with CL too

17:36 I figure if you know CL, you're probably capable of figuring it out on your own. =)

17:36 Chousuke: I'm quite impressed by paredit btw.

17:36 I couldn't quite figure it out previously, but then I realised how to use barf and slurp and that alone makes it awesome :P

17:37 next I need to learn the commands for navigating sexps I guess

17:37 technomancy: I'm working on a screencast.

17:37 slowly...

17:37 Chousuke: the emacs transpose feature is weird btw.

17:38 technomancy: clojurebot: paredit screencast is http://p.hagelb.org/paredit-screencast.html

17:38 clojurebot: c'est bon!

17:38 Chousuke: I haven't found a single useful use for it yet, but it's interesting :P

17:40 lrenn: Chousuke: transpose sexp can be used to move an sexp down (just keep hitting it). I don't use it, but there ya go.

17:49 JAS415: technomancy: for me its more like i'm stubborn enough to not admit that I can't figure it out

17:55 technomancy: hiredman: did you say you were able to run clojurebot in slime?

17:55 I'm getting a lot of java.security.AccessControlExceptions from the securitymanager -D args

17:56 hiredman: technomancy: I don't use emacs

17:56 technomancy: do you have the policy file setup?

17:57 technomancy: hiredman: oops. /path/to/this.policy.

17:57 hiredman: easiest if you just copy example.policy to ~/.java.policy

17:57 technomancy: =)

17:58 hiredman: I could not get specifying the path to the policy file to work

17:58 Chousuke: it needs to be an URL

17:58 hiredman: oh

17:58 Chousuke: file:///path/to/policy.file

17:58 hiredman: well, there you go

17:59 technomancy: I meant that I had it set to the literal "file:///path/to..." instead of the actual path

17:59 hiredman: nice

18:00 technomancy: still getting access denied though... I'll stick with rlwrap for now.

18:00 hiredman: I have code for getting clojurebot to work in a multiuserchat with jabber too, I just haven't shoehorned it in yet

18:01 Chousuke: I did run clojurebot in emacs... hmm

18:01 I think I have my old emacs config somewhere

18:02 mebaran151: are compojure and ring likely to merge: it seems like they mirror each other's functionality

18:03 hiredman: ring is lower level, I think compojure is built on top of ring these days

18:04 LauJensen: True

18:05 Chousuke: technomancy: I had '(swank-clojure-extra-vm-args (list "-server" "-Djava.security.manager" "-Djava

18:05 .security.policy=file:///Users/oranenj/.emacs.policy"))

18:05 where .emacs.policy is the example.policy

18:06 rhickey: Dan Weinreb with nice things to say about Clojure: http://www.youtube.com/watch?v=xquJvmHF3S8

18:06 50 minutes in

18:07 but the rest a nice survey about the applicability of Lisp to hard problems requiring flexibility, an area Clojure should also cover well

18:13 JAS415: are there any plans for multiple value return in clojure?

18:14 it would be really nice :-)

18:21 mebaran151: JAS415, what's wrong with simply packing a vector and destructuring on input

18:21 rhickey: JAS415: no plans, sorry

18:22 there isn't the requisite stack manipulation in Java bytecode for it

18:22 so it would be 'faked' in any case

18:23 I had an implementation when first doing Clojure, using thread locals

18:23 JAS415: ah that's too bad

18:24 membaran: nothing intrinsically, just a little less efficient to be creating and destroying objects all the time

18:24 technomancy: GC is cheap

18:25 JAS415: oops x'd the box when i wanted to resize

18:26 well i guess its just i just have sort of a mental differentiation between a vector that i'm destructuring and returning multiple values

18:26 it also seems like people get mislead into writing fairly inefficient code

18:28 there was that 'uncle bob' thread in the clojure google groups and he was asking 'why is this so slow' and it was kind of obvious, as he was making like 8,000,000 2 length immutable vectors and destructuring

18:29 or maybe it was 16,000,000

18:30 mebaran151: but for multiple return, you would have to pack it in SOMETHING

18:30 because Java has not native tuple type

18:30 hiredman: Map.Entry

18:31 Chousuke: :P

18:31 JAS415: unless you can manipulate the stack like rich was talking about, which you can't

18:31 Chousuke: are thread locals too slow them? :/

18:31 JAS415: so i'll wait for it along with TCO

18:31 Chousuke: then*

18:31 hiredman: ,(java.util.AbstractMap.SimpleImmutableEntry. :a :b)

18:31 clojurebot: java.lang.ClassNotFoundException: java.util.AbstractMap.SimpleImmutableEntry

18:31 hiredman: bah

18:31 ,(java.util.AbstractMap$SimpleImmutableEntry. :a :b)

18:31 clojurebot: #<SimpleImmutableEntry :a=:b>

18:32 Chousuke: hiredman: that's still creating a new object though.

18:32 rhickey: JAS415: multiple returns are not coming, so don't wait for them :)

18:32 JAS415: haha

18:32 fair enough

18:34 rhickey: the #1 use case (for me) of multiple return in CL was gethash, covered by optional not-found arg to get

18:34 JAS415: honestly most of the uses of multiple return in CL i've found have been in incomprehensible spaghetti code

18:35 rhickey: Otherwise nice but not necessary. And the inefficiencies today of ephemeral tuples for returns might disappear with the escape analysis of tomorrow...

18:35 Chousuke: I guess if you have a function returning multiple values or tuples in a tight loop you'll just have to use some mutable thread-local slot to hold the values and unpack them immediately. :/

18:35 JAS415: the thing is I kind of feel like I want either to be able to return multiple values or to be able to use state

18:37 technomancy: hiredman: you have some defmultis in clojurebot that check for clojure.lang.PersistentHashMap that should check for IPersistentMap

18:37 since small maps are usually PersistentArrayMaps... you shouldn't care about the size of the map

18:39 Chousuke: rhickey: btw, how do you avoid holding on to the head of aseq in code like (fn [aseq] (let [aseq (consume-a-lot-of aseq)] (first aseq))). I noticed that using let for some reason doesn't "overwrite" the function argument reference and you end up consuming more memory than needed

18:39 hiredman: technomancy: good catch

18:39 thanks

18:41 looks like just the one

18:42 rhickey: Chousuke: lazy seqs are not ephemeral seqs, so if you realize part/all of it and then go on to use the head you've got the whole seq there. It's not possible to get rid of it since you asked for it and still need it. Args and ocals are cleared on tail calls only (when it is known that they can't be used again). Also, the let 'aseq' and the arg 'aseq' are two completely different lexical things. Calling the let one 'foo' would make no diff

18:45 technomancy: hiredman: ah, you're right; just one

18:46 unfortunately I'm modifying the codebase pretty significantly or I'd be inclined to send patches instead of just "hey, could you fix..." =)

18:46 hiredman: shouldn't really be there anyway

18:46 I imagine it would take a significant modification to make it suitable for anyone beyond #clojure

18:47 technomancy: mostly just ripping things out so far

18:47 Chousuke: rhickey: in my reader I do (let [[item rh] (consume rh)] (do-something-more item rh))) a lot, and code like that ends up holding on to the old rh for longer than necessary. the thing is, I can't quite see how to avoid that without removing all the lets from my code. :/

18:47 technomancy: Chousuke: you mentioned you were using clojurebot? what for?

18:48 Chousuke: technomancy: ages ago :P

18:48 when I hacked it from v1 to v2. :P

18:48 technomancy: heh; right

18:48 hiredman: and an excellent job he did

18:49 Chousuke: I do regret the "dfn" macro though.

18:49 because when I re-read my code a while ago I couldn't figure out what I was thinking.

18:49 hiredman: haha

18:50 rhickey: Chousuke: it would clarifythings a bit for you if you used different names, as I said, they are different things, and reusing the name is giving you false expectations

18:50 hiredman: what is a code base without its peculiarities

18:51 rhickey: (let [[foo bar] (consume baz)] (do-something-more foo bar)))

18:51 same

18:52 baz will stick around until the tail call to do-something-more

18:55 Chousuke: hmm, I think I will have to restructure my code a fair bit then.

18:55 No matter. I have a feeling the end result will be more functional, in both senses of the word

18:57 Many thanks for the clarification.

19:13 technomancy: hiredman: also clojurebot would be a lot more repl-friendly if you used defonce for some of your initializing stuff like *bots*

19:18 hiredman: yeah, I've been ignoring that part of core

19:19 technomancy: minor point

19:19 hiredman: it hasn't been an issue for me, because I am in the habit of sending a function at a time to the repl, and not a whole file

19:21 rhickey: Chousuke: it is a possible future optimization to tighten arg/local lifetime to point of last use (instead of tail call), which would solve this problem for you and many others. might not happen until cinc

19:25 technomancy: is defvar like defonce but with docstring sugar?

19:26 oh, it's not once-only like it is in elisp.

19:30 konr: Do you guys know of more Clojure examples with Swing, besides the Celsius/Fahrenheit one?

19:33 technomancy: hiredman: did you take a look at the fnparse followed-by problem?

19:36 jfields: how can I convert a char to a byte, eg \A to 65

19:37 technomancy: ,(int \A)

19:37 clojurebot: 65

19:37 jfields: thanks

19:55 konr: do you guys know of any enclojure (preferably with matisse) tutorial?

20:02 cemerick: there's a PDF tutorial in the google group, IIRC

20:30 hiredman: technomancy: I haven't

20:34 they are some big changes between the version I am using and the latest version

20:34 technomancy: strange that I'm still getting that error with the fnparse jar you sent me though

20:34 hiredman: oh?

20:35 uh

20:35 I hope I gave you the right one

20:35 yeah, that is the same jar I have in ~/.jars/

20:35 technomancy: could you give me the URL again?

20:35 hiredman: SHA1 (.jars/fnparse.jar) = b281abd4b298f5cdbac876791629e2014e356867

20:36 technomancy: that's what I've got. weird

20:36 hiredman: http://www.thelastcitadel.com/lab/fnparse.jar

20:36 hmmm

20:37 technomancy: no big deal; I don't really need factoids now

21:12 tomoj: what's the deal with sync vs dosync?

21:13 oh, nevermind, rich explained it a few seconds later :)

21:33 hiredman: haha, "what the hell, just crash it"

21:33 clojurebot: memory leak is <reply>what the hell, just crash it

21:33 clojurebot: In Ordnung

21:48 JAS415: clojurebot: memory leak

21:48 clojurebot: what the hell, just crash it

22:55 technomancy: any jruby people; I've got my clojure-gem working pretty decently: http://github.com/technomancy/clojure-gem

22:55 supports dosync and the 4 major persistent collections

22:55 just no lazy seqs yet.

22:59 Chouser: technomancy: nice. We're using a mix of C++, Java, Clojure, and JRuby now.

22:59 I'll pass the URL along to our ruby guy.

23:00 hiredman: (through the bars of his dank prison cell)

23:02 TheBusby: interesting mix of languages, end up with C, Ruby, Clojure here

23:02 seems like a combination of C/C++ for performance, Clojure for structure, and ruby/python for scripting is becoming very common

23:03 hiredman: funny, I seem to recall someone predicting clojure for scripting and scala for structure

23:04 Chouser: our C++ is for legacy reasons more than performance

23:04 TheBusby: although I'm very fond of clojure, ruby's simple string handling, quick startup time, and backticks make it much easier for scripting I think

23:04 Raynes: It's sad how when people see a side-by-side of Clojure and Scala they see 'OOP' tacked on Scala's side, and immediately lose interest in Clojure. :|

23:15 technomancy: Raynes: it's arrow-oriented!

23:22 hiredman: ~scala

23:22 clojurebot: Scala often gets in the way when trying to write neat code -- seen in #scala

23:24 TheBusby: I'm just waiting for a language to come out that compiles to C code

23:25 hiredman: :(

23:25 my facilities does C offer to entice language designers?

23:25 TheBusby: it compiles on every platform

23:25 hiredman:

23:26 TheBusby: pick just about any chip/platform/system these days, and they all have support for C

23:27 (speaking mainly for the embedded world)

23:27 hiredman: they don't support C, there is a compiler that turns C into asm for the chip

23:28 TheBusby: correct, and for many platforms that is the only compiler available for that chip

23:31 albino: TheBusby: Seen gambit-scheme?

23:31 TheBusby: no, googling now

23:33 albino: There have been some blog entries lately on using gambit to generate C that runs on the iPhone

23:33 TheBusby: albino: much appreciated, I'll be trying this out at once

Logging service provided by n01se.net