#clojure log - Nov 20 2009

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

0:57 gilbertleung: hi

0:58 i'm trying to use wall-hack-method, which requires a list of params to be passed in

0:59 if the param is of string class, then i just pass in java.lang.String

0:59 so... what if the param is of String[] ?

1:00 hiredman: ,(-> "foo" vector into-array .getClass)

1:00 clojurebot: [Ljava.lang.String;

1:00 hiredman: ,(Class/forname ""[Ljava.lang.String;"")

1:00 clojurebot: EOF while reading

1:01 hiredman: ,(Class/forName "[Ljava.lang.String;")

1:01 clojurebot: [Ljava.lang.String;

1:01 gilbertleung: hmm

1:02 hiredman: it is less than ideal, but most things dealing with classes of arrays are

1:04 gilbertleung: interesting

1:04 hiredman: thx

1:06 hiredman: ,(-> "foo" vector into-array class)

1:06 clojurebot: [Ljava.lang.String;

2:23 mrSpec: hello

5:41 ordnungswidrig: anybody using leiningen on w32?

5:42 Bjering: is there a function to list all my variables so I can run test on those that have :test metadata?

5:45 ordnungswidrig: Bjering: all vairables or all functions?

5:46 liwp: Bjering: you can look up the vars in a namespace I think

5:46 Bjering: all variables that holds functions

5:47 liwp: so you could iterate over all the vars exported by a ns and see if they have :test metadata on them or not

5:47 Bjering: What I am really after the best way to manage my unittests, I have no java legacy its a new project. I am new to Clojure.

5:47 yes that was my idea

5:47 liwp: Bjering: you should look into the clojure test framwork: clojure.test I think

5:49 ,(doc clojure.test)

5:49 clojurebot: java.lang.ClassNotFoundException: clojure.test

5:49 liwp: or not...

5:50 Bjering: ,(doc test)

5:50 clojurebot: "([v]); test [v] finds fn at key :test in var metadata and calls it, presuming failure will throw exception"

5:50 Bjering: Thats all the doc I find

5:51 liwp: ,(doc clojure.test-is)

5:51 clojurebot: java.lang.ClassNotFoundException: clojure.test-is

5:51 liwp: grr

5:52 Bjering: now I am reading "the book" now, and it describes the test-is library. I just wanted to go with the core test first, until it was proven to me it wasnt enough. Maybe I already reached that point?

5:53 liwp: AFAIK clojure.contrib.test-is got moved to clojure.test and it's used e.g. in writing tests for core

5:53 I haven't used it myself, but there's an oldish article about it at http://stuartsierra.com/2009/01/18/tests-are-code

5:54 seems straight forward enough, i.e. I don't think you need to worry about it being overkill for you needs

5:54 Bjering: thank you, I'll read that

6:15 cypher23: VimClojure question: The keybindings don't seem to work, is there anything I need to do to activate them?

6:57 rhickey: heh, potential JDK syntax for function expressions? #() :) http://www.jroller.com/scolebourne/entry/closures_in_jdk_7

6:59 _ato`: :D

7:53 Bjering_: I want to rotate a vector, like this:

7:53 (reduce conj (subvec v n) (subvec v 0 n)))

7:54 is there a way todo this O(1) ?

8:02 ordnungswidrig: Bjering_ Rotate by one element? What about concat? (concat (subvec v n) (subvec v 0 n))

8:02 ,(let [v [1 2 3 4] n 3] (concat (subvec v n) (subvec v 0 n)))

8:02 clojurebot: (4 1 2 3)

8:02 ordnungswidrig: ,(let [v [1 2 3 4] n 1] (concat (subvec v n) (subvec v 0 n)))

8:02 clojurebot: (2 3 4 1)

8:06 Bjering_: ornungswidrig: Ah perfect, now it would be great if concat was listed among "related functions" ner vector at http://clojure.org/data_structures

8:07 ordnungswidrig: Bjering_ yes, the api is very large and dynamic typing makes it hard to browser for matching functions.

8:08 Bjering_: I understand

8:10 hmm, concat destroys the "vectorness" though, its a lazy-seq

8:10 ordnungswidrig: Bjering_: but is O(1) I suppose :-)

8:11 Bjering_: As long as I dont want to use it as a vector later.

8:11 ordnungswidrig: Bjering_: you mean random access?

8:11 Bjering_: yes, such as subvec

8:11 ,(= [1 2 3 4 5 6] (concat [1 2 3] [4 5 6]))

8:11 clojurebot: true

8:12 Bjering_: one is a seq, one is a vec still they are equal?

8:12 ordnungswidrig: Bjering_: you'd better ask somebody who is more familier with clojure's datastructurs. I don't know them very well.

8:16 ,(let [v [1 2 3 4] n 3] (vec (subvec v n) (subvec v 0 n)))

8:16 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$vec

8:17 Bjering_: Well, I can make my rotate return a vector by using the vec-ctor, sure, but I assume the vec call is O(n)

8:19 ordnungswidrig: Bjering_: basically you need sth. like concat for vectors which is O(1)

8:21 Bjering_: yes but this doesnt exist?

8:27 chouser: ,(into [1 2 3] [4 5 6])

8:27 clojurebot: [1 2 3 4 5 6]

8:27 chouser: That's roughly O(n) where n is the length of the second vector

8:28 rhickey: Bjering: there is no constant-time vector rotate in Clojure

8:28 Bjering_: ok, thats the best possible?

8:28 ok

8:29 rhickey: so, in playing with callsites I've added the ability to more-statically link to defn-ed vars you know won't change (e.g. clojure.core), for significant perf boost in some situations, thinking about how best to expose/express this option

8:30 could be at the var or lib levels, property of the author or consumer...

8:31 chouser: hm, fun...

8:32 rhickey: seems to give 20% perf boost easily, and can be many times that when a small work unit gets inlined

8:32 chouser: that's a bit better than I saw going from vars to letfn in finger tree

8:32 rhickey: you would never need letfn for perf again

8:32 chouser: yay

8:33 rhickey: the tradeoff is, no dynamic rebinding, no redef without reloading deps (not a restart though)

8:34 I found few cases of dynamic rebinding of fns, one in test itself, some in a mock and trace lib

8:35 so, this ad hoc capability is costing everyone, even when not used, but can be tricky to determine granularity of expressing static/non

8:36 chouser: producer could provide a "hint" and a consumer could still override that, right?

8:37 rhickey: it's notthat simple when you think of libs that might dynamically rebind something expecting that to be in effect for called code that statically linked

8:37 that's a made-up but possible case

8:39 chouser: ah, right. like a trace applied to someone else's code

8:40 djork: is there a standard way to create a fully-qualified symbol from a "base" symbol and a namespace?

8:40 rhickey: so there are a few division points - this fn was designed to be rebound, this lib is done/static, this code is under dev/dynamic, this lib superimposes dynamism on things it doesn't own

8:40 djork: ,(namespace 'foo/bar)

8:40 clojurebot: "foo"

8:40 djork: should I just do it with strings

8:41 ,(str "some-ns/" (name 'foo))

8:41 clojurebot: "some-ns/foo"

8:41 rhickey: for the latter case there could just be a 'turn off direct linking' option, back to old semantics

8:42 but if on consumer side, :requires in different libs could have conflicting directives re this

8:42 durka42: ,(symbol "foo" "bar")

8:42 clojurebot: foo/bar

8:43 djork: ah, thanks a lot durka42

8:46 hmm, can't use private fns in a macro that's used somewhere else...

8:47 chouser: is it possible to get a warning if you try to rebind something that has direct linking?

8:55 Bjering_: the seq returned by (seq (vector 1 2 3)) is lazy I presume?

8:59 this paste-webpage I have seen you use, how do I use it?

9:01 rhickey: chouser: I guess if it was a property of the var in the first place - I haven't gone there yet, but on the todo is a more varied set of vars, with/without rebind e.g., and 'constant' vars

9:02 but while linkage could be a global property, it need not be, since it is really a property of each fn how strongly it links to the vars it references

9:07 one consuming fn could say - I'm happy with the current def indefinitely, another that is wants to see changes

9:08 of course, #' does the latter right now

9:11 chouser: Bjering_: just go to http://paste.lisp.org/new/clojure and fill out the form

9:11 Bjering_: chouser: Thank you

9:13 lisppaste8: Bjering_ pasted "fast-drop" at http://paste.lisp.org/display/90945

9:14 rhickey: also on the table this weekend was putting protocol fn defs right into deftypes, and having protocols auto-generate interfaces. The desire is to hide the interfaces, which really are an implementation detail, but not have deftype + interfaces be more convient than deftype + protocols, and not have there be any code munging required to move an extend impl to an interface-based one

9:14 Bjering_: Is there a reason (other then deemed unimportant) why this kind of optimization isn't in?

9:14 rhickey: but protocols-autogenerate-interfaces has the problems of gen-and-load-interface :(

9:17 Bjering: special handling of particular data structures would bloat all of the standard fns, and how to decide which to special-case? When the standard fns are protocol-based, this kind of optimization will be easy, natural, and extensible

9:18 Bjering_: rhickey: Where can I learn about "protocol-based"?

9:18 rhickey: https://www.assembla.com/wiki/show/clojure/Protocols

9:19 Bjering_: Thank you

9:19 chouser: Bjering_: currently clojure's core fns and datatypes don't use protocols, but there are plans to move in that direction.

9:20 mikem`: Hi, I have a call to map like this: (map (fn [x] (list (keyword (first x)) (second x))) (some-seq)) -- instead of (fn ...) I tried to use #('((keyword (first %)) (second %))) but that throws java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn. what am I missing?

9:22 chouser: mikem`: #(foo) is (fn [] (foo)) not (fn [] foo)

9:23 mikem`: so you're trying to eval something like ('(a b))

9:23 but a list is not a function, so you get an error.

9:24 mikem`: ok. so can I write a function like with #() that returns a list based on the argument it receives?

9:24 rhickey: (fn [x] (anything x)) ==> #(anything %)

9:25 chouser: mikem`: #(list (keyword (first %)) (second %))

9:26 mikem`: ok, thanks! it's working.

10:48 djork: are there any catches to using defmulti/defmethod across namespaces or files?

10:52 chouser: not really. a defmulti can be extended by a defmethod in any file or namespace

11:05 hamza`: ~memoize

11:05 clojurebot: Gabh mo leithscéal?

11:05 hamza`: how did we get the url to source for a function?

11:07 jweiss: bah. paredit. doesn't do what i want in clojure. anyone here gone thru this already? (paredit in emacs)

11:07 chouser: ~def memoize

11:07 hamza`: ool thanks..

11:07 * cool

11:08 liwp: jweiss: I have

11:08 jweiss: I had problems with {} I think

11:08 jweiss: liwp: ok, for instance, i want the slurp/barf to work within square braces. how do i do that

11:09 btw i love that they named it 'barf'

11:09 liwp: jweiss: huh? what happens at the moment?

11:09 jweiss: slurp / barf are paredit functions?

11:09 jweiss: liwp - that command does nothing if i run it withing square braces

11:09 liwp: paredit-forward-slurp-sexp

11:10 liwp: jweiss: what happens in your case?

11:11 ~paste

11:11 clojurebot: lisppaste8, url

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

11:11 jweiss: liwp - nothing happens. if i have this (let [a b | ] c) where | is the point, and i run that command, i want it to give me (let [a b c]) . but it does nothing.

11:13 liwp: jweiss: IIRC you have to hack paredit source to understand [] and {}. Let me see if I can figure out what I changed...

11:14 jweiss: liwp: maybe just diff your paredit.el with the orig

11:14 or create patch :)

11:14 liwp: jweiss: have a look in paredit.el:667

11:15 jweiss: you should see a bunch of (define-paredit-pair) forms

11:15 jweiss: liwp: yeah

11:15 liwp: do you have forms for all these: () [] {} <>?

11:15 jweiss: liwp yes

11:16 liwp: jweiss: uhh, must have been something else that I changed then...

11:16 jweiss: round, square, curly, angled.

11:16 liwp: yeah

11:16 jweiss: liwp: just run diff from http://mumble.net/~campbell/emacs/paredit.el to your file

11:18 liwp, or better just just pastebin your file and i'll use that :)

11:18 s/just just/yet just/

11:18 liwp: jweiss: yeah, let's try that for starters

11:18 the-kenny: I fell asleep two times in a row watching "Clojure Data Structures - Part 1". Sorry :(

11:18 jweiss: we should probably post this somewhere maybe on github for other people

11:19 liwp: jweiss: I'd love to figure out what I changed first :-)

11:19 uhh, "paste too large"

11:19 jweiss: liwp: i'll diff it for ya if you like

11:19 liwp: maybe try the non-lisp pastebin

11:20 http://pastebin.com/

11:21 liwp: jweiss: apparently my paredit.el is identical to the one on the above url...

11:21 this isn't really helping :-(

11:21 jweiss: liwp. so you didn't change anything?

11:21 that is... odd

11:22 liwp: jweiss: I distinctly remember changing something. IIRC I wasn't able to type in curly braces with the default paredit.el

11:23 jweiss: liwp, for what it's worth, i CAN slurp in the next item if it's an sexp

11:23 liwp: jweiss: ahh, I think there's some magic in clojure-mode.el for paredit

11:24 jweiss: can you pastebin some code that doesn't work for you

11:24 jweiss: liwp, ok, hm

11:24 liwp: jweiss: my clojure-mode say this: ./clojure-mode/clojure-mode.el:225: ;; Enable curly braces when paredit is enabled in clojure-mode-hook

11:24 jweiss: liwp: yeah i think i have that too

11:24 this is on the REPL by the way

11:25 liwp: ahh, I don't have paredit enabled on slime repl

11:25 jweiss: liwp: (interpose [|] :a [1 2 3])

11:25 where the cursor is at the |

11:25 i want to slurp in the :a

11:26 liwp: jweiss: I get this after a slurp: (interpose [| :a] [1 2 3])

11:26 let me try that in the repl

11:27 jweiss: liwp: works for me in a clojure file

11:27 not the repl tho

11:27 liwp: jweiss: yep, works there as well

11:27 jweiss: is that a slime repl or the inferior-lisp buffer?

11:27 jweiss: liwp, slime-repl

11:28 ok i think i have a problem in my .emacs, let me see if i can fix liwp

11:28 liwp: jweiss: seems to work for me everywhere, sorry I can't help :(

11:32 mattrepl: any active contributors know if it's fine to self-assign an open ticket in assembla?

11:34 Chousuke: mattrepl: I don't think the assigment system is used for anything other than tracking who's working on the issue

11:35 mattrepl: Chousuke: thanks

11:35 liwp: mattrepl: I think so. If you think that you can fix something, go for it. The patch will go through verification before it's applied in any case.

11:38 jweiss: liwp: ok i figured it out. had to enable clojure-mode in the repl, and then enable paredit-mode in the repl.

11:38 Joreji: Hey guys, how can I dispatch a multimethod on a & rest param? (e.g.: (defmethod [:one :two LazySeq] [one two & rest] nil) )

11:38 liwp: jweiss: good job

11:38 jweiss: liwp: i am not sure how to get this to happen in my .emacs file tho, any suggestion

11:39 liwp: jweiss: let me see what I do to get slime going...

11:41 Joreji: jweiss: (add-hook 'slime-repl-mode-hook (lambda()(progn(clojure-mode 1)(paredit-mode 1)))) ?

11:41 jweiss: Joreji: letme try that

11:41 liwp: jweiss: it seems that I don't have clojure-mode enabled in my slime-repl (I don't know why paredit seems to work for in that case). But I'm sure you can use some mode hook to enable clojure-mode

11:42 Joreji: yeah, something like that

11:44 jweiss: Joreji: didn't work, i get a strange message when i run slime:

11:45 bah, it won't even paste because it has multibyte chars

11:45 Joreji: error in process filter: progn: Wrong number of arguments: #[nil (and then bunch of list items)

11:47 liwp: jweiss: try it without the progn, i.e.: (add-hook 'slime-repl-mode-hook (lambda () (clojure-mode 1) (paredit-mode 1)))

11:48 Joreji: Hmm strange

11:49 jweiss: liwp: Joreji, nope, same err

11:49 Joreji: I doubt the problem lies with the top level progn

11:50 then again, I've just activated clojure-mode inside my repl, and I must say that I don't see the use for it.

11:50 You can't have the repl-mode and clojure-mode be activated at the same time.

11:51 jweiss: Joreji: hm, i can't get paredit to work right unless i activate clojure-mode

11:51 the-kenny: jweiss: Just add a hook to slime-repl-mode

11:51 jweiss: the-kenny: um, i'm an emacs newb, how do i do that

11:52 Joreji: jweiss: You already tried that.

11:52 the-kenny: (add-hook 'slime-mode-hook (lambda () paredit-mode +1))

11:52 jweiss: the-kenny: i don't think that's it. clojure-mode does something to make paredit work right.

11:52 the-kenny: jweiss: It's working for me.

11:53 liwp: Joreji: yeah, you're right, enabling clojure-mode disables repl-mode

11:53 jweiss: the-kenny: in the REPL?

11:53 the-kenny: jweiss: Yes

11:53 paredit doesn't have anything to do with paredit

11:53 ordnungswidrig: whoohoo. chatting at the train with my g1

11:53 the-kenny: Ew.. I mean clojure-mode

11:53 jweiss: the-kenny: try this: (interpose [|] :a) where | is the cursor, and hit C-[rightarrow]

11:53 see if it slurps in the :a

11:54 the-kenny: yes it does, i think. clojure-mode's code has some paredit stuff in it

11:55 the-kenny: jweiss: Hm.. you're right. It adds functionality for {

11:55 But that works for me in my REPL without extra changes

11:55 jweiss: the-kenny: crap

11:56 ordnungswidrig: the-kenny paredit doesn't work on { for me.

11:56 the-kenny: ordnungswidrig: Oo strange

11:56 jweiss: i can't seem to surround a list with [] in the repl

11:56 the-kenny: Maybe it works because I've opened a buffer in clojure-mode *before* I started the repl?

11:57 jweiss: nor slurp the list into empty []

11:57 ordnungswidrig: when i insert a { no } is inserted. the rest works as expected... deleting etc.

11:57 jweiss: ordnungswidrig: yeah i don't get any curly brace love on the repl either

11:58 the-kenny: i didn't realize it mattered where you start slime from

11:58 it opens a new buffer for me

11:58 ordnungswidrig: jweiss: in the clojure buffer i do not get it neither

11:59 jweiss: ordnungswidrig: oh yea, me neither

11:59 liwp: you don't get {} in a clojure buffer?

11:59 jweiss: liwp: no

11:59 liwp: jweiss: I do

11:59 ordnungswidrig: liwp: no insert of { after }

12:00 liwp: If I type '{' I get '{}' and the point is in between the braces

12:00 ordnungswidrig: liwsp: tr/{}/}{/

12:00 jweiss: liwp, doesn't work for me

12:00 ordnungswidrig: strange stuff

12:00 liwp: jweiss: I think this is exactly what clojure-mode fixes in paredit.el

12:00 jweiss: liwp: so what's going wrong then

12:01 loaded in the wrong order or something?

12:01 ordnungswidrig: must i enable paredit by clojure-mode?

12:01 liwp: I don't think that should make any difference...

12:01 ordnungswidrig: ...let enable...

12:02 liwp: I autoload paredit first and the require clojure-mode

12:02 ordnungswidrig: hmm. i'm on debian unstable. does the clojure-mode version matter?

12:02 liwp: ordnungswidrig: possibly, I think most people get it directly from github

12:03 I gotta run, good luck!

12:03 ordnungswidrig: iirc I use clojure installed by elpa-cl-swank

12:03 yes, will keep trying. good to know that it can work fine.

12:04 Chousuke: elpa should have a recent enough clojure-mode I think

12:05 jweiss: i installed it thru elpa as well

12:05 but if i put (require 'clojure-mode) in my .emacs it won't start correctly

12:06 my clojure mode is udner my ~/.emacs.d/elpa

12:08 aha, had to move the elpa stuff to the top of .emacs

12:15 Bjering_: What is the idiomatic way to check for the empty list? #(= '() %)

12:17 stuartsierra: Bjering_: seq or empty?

12:17 Bjering_: thank you

12:50 jweiss: if i have a little mini function i want to call a couple times within a defn, but i don't need the mini function anywhere else, is it ok to just define it in a let? or will this waste memory each time the larger function is called? i would hope it's the same as any place you use #()

12:51 the-kenny: jweiss: Let is fine..

12:51 I think there is also letfn or so

12:52 jweiss: You're on the JVM. The JIT does a good job in optimizing such things

12:58 stuartsierra: Each instance of (fn ...) or #(...) creates a single Java class. A new instance of that class is created each time you evaluate the fn/#() form.

12:59 hiredman: each time you compile

13:00 (which is what eval does, but saying it happens each time you compile the form sounds less threatening)

13:00 the-kenny: ,(time (dotimes (_ 100000) (let [foo (fn [] nil)] (foo))))

13:00 clojurebot: java.lang.IllegalArgumentException: dotimes requires a vector for its binding

13:00 the-kenny: ,(time (dotimes [_ 100000] (let [foo (fn [] nil)] (foo))))

13:00 clojurebot: "Elapsed time: 56.972 msecs"

13:00 hiredman: the-kenny: what will only compile the function once

13:01 that

13:01 the-kenny: hiredman: That compiles only once? Very good :)

13:03 bgs100: ,(map .toUpperCase ["a" "b" "c"])

13:03 clojurebot: java.lang.Exception: Unable to resolve symbol: .toUpperCase in this context

13:03 hiredman: bgs100: java methods are not first class values

13:03 bgs100: Oh

13:04 hiredman: ,(map (fn [x] (.toUpperCase x)) ["a" "b" "c"])

13:04 clojurebot: ("A" "B" "C")

13:04 the-kenny: ,(map (memfn toUpperCase) ["a" "b" "c"])

13:04 clojurebot: ("A" "B" "C")

13:04 hiredman: ,(map #(.toUpperCase %) ["a" "b" "c"])

13:04 clojurebot: ("A" "B" "C")

13:19 defn: hiredman, S. Halloway's book, eh? :)

13:19 errr, nvm, didn't notice the-kenny interjected there

13:20 it should be noted that memfn is less favorable

13:20 the-kenny: defn: Why is memfn not favorable?

13:20 defn: It came from when Clojure didn't have anonymous functions

13:20 anonymous functions are the preferred way of using Java calls

13:21 the-kenny: ah ok.. got it.

13:49 krukow: Anyone up for an emacs/slime classpath question?

13:51 the-kenny: krukow: Just ask. meta-questions are just time consuming

13:51 krukow: sure: I can use add-classpath to dynamically a to the classpath, yes?

13:51 for example:

13:52 the-kenny: krukow: You could, but it's discouraged.

13:52 krukow: (add-classpath "file:////Users/krukow/emacs/enlive/enlive.jar")

13:52 (add-classpath "file:////Users/krukow/emacs/enlive/enlive.jar")

13:52 yes, just for a repl session

13:53 following the enlive tutorial I am adding enlive.jar and tagsoup-1.2.jar

13:53 this works fine. However adding: (add-classpath "file:////Users/krukow/emacs/enlive/src")

13:54 doesn't seem to work for me

13:54 at least it can't see a file located in the src directory

13:55 it works with java -cp<paths here> clojure.main

13:56 KirinDave: Enlive looks nice.

13:56 I am glad the culture of sexp->html is not deeply rooted in the clojure community. It's such a tiresome practice to dispel.

13:58 krukow: noone on the emacs classpath q?

14:00 the-kenny: krukow: Which question?

14:00 krukow: I was wondering why seems to be able to see the html file in enlive/src with java -cp<paths here> clojure.main

14:01 but not when using add-classpath file:////Users/krukow/emacs/enlive/src

14:01 inside emacs

14:02 the-kenny: Because add-classpath is buggy ;)

14:02 krukow: oh ;-)

14:02 hiredman: ~add-classpath

14:02 clojurebot: add-classpath is Fraught with Peril!

14:02 krukow: which is why it is discouraged :-)

14:02 the-kenny: hiredman: Is ~ a shortcut for ,(doc name)?

14:03 hiredman: ~ is a shortcut for clojurebot:

14:03 clojurebot: for is not used enough

14:03 hiredman: clojurebot: add-classpath

14:03 clojurebot: add-classpath is Fraught with Peril!

14:04 michaeljaaka: hi

14:04 I have question

14:04 http://gist.github.com/241284

14:05 are these sequences whole consumed?

14:05 or only first element is evaluated

14:05 and removed as filter wants

14:06 hiredman: michaeljaaka: those sequences are not lazy, so it makes no difference

14:06 michaeljaaka: but if those were lazy?

14:06 how to check this in future

14:06 hiredman: only the first

14:06 michaeljaaka: I will have sequences from file

14:06 hiredman: check what?

14:06 michaeljaaka: is there any simple way to ensure

14:07 that sequences are not evaluated?

14:07 hiredman: "sequences from a file" is pretty vague

14:09 michaeljaaka: if the filter computes after checking only first element from each seq, then it is ok

14:09 thanks

14:13 Chousuke: michaeljaaka: note that functions that transform or consume sequences may consume more than is strictly necessary. first doesn't though, so in this case it's safe.

14:14 michaeljaaka: ok, thanks

14:24 esj: any way of seq'ing an integer ? Doing an Euler problem where I want to treat a number as seq, and turning it into a string first seems a bit wasteful.

14:25 Chousuke: you can devise another method of extracting the digits from an integer I suppose.

14:26 rhickey: add-classpath is not buggy, it just can't make the added classpath visible to all classloaders, thus, not that useful and to be avoided

14:27 krukow: ok, interesting. can you explain why adding a jar seems to work while adding a directory does not?

14:27 esj: Chousuke: sure I could do it numerically or via the string, but seems roundabout

14:29 rhickey: krukow: don't use add-classpath, I'm going to remove it at some point. Use regular classpaths

14:30 I don't see a reason why jars and dirs would be different if the dir has the same structure

14:31 krukow: ok, but it's still a nice feature to dynamically extend a repl session

14:31 except that it doesnt work of course :-)

14:32 rhickey: I wish there was a standard way to extend the root classpath, but there isn't

14:33 if you are using JDK 6 you can add a wildcard dir to your classpath, then dynamically drop jars there

14:34 krukow: cool, didn't know that

14:34 rhickey: my classpath ends with :/Users/rich/dev/ext/* and everything I put there is visible

14:35 the-kenny: Does this really work? I remember problems with that

14:35 rhickey: it's quite painless

14:35 krukow: I think I'll add something similar to my swank-clojure-extra-classpaths

14:36 thanks

14:36 rhickey: the-kenny: java.ext.dirs can be tricky, but the wildcard isn't afaict

14:37 chouser: With some effort I've gotten java.ext.dirs to work pretty consistently. I should probably try the wildcard instead.

14:37 the-kenny: hm.. so should "java -cp classes/*:lib/*:src/* my.class" work?

14:37 chouser: the-kenny: probably "classes:lib/*:src" if you've got a "normal" layout

14:38 the-kenny: hm... does the order matter?

14:38 chouser: the-kenny: if there are two classes with the same name in different places, yes.

14:39 rhickey: wildcards are for dirs containing jars only

14:39 chouser: the-kenny: but I was pointing out that 'classes' and 'src' are usually each the root of a classpath, with dirs named like 'com' and 'org' in them.

14:39 while 'lib' is usually a directory full of .jar files.

14:39 the-kenny: chouser: Yes, that's my layout.

14:40 rhickey: hrm, claspath wildcards are not dynamic, guess I never really needed that

14:41 at least they keep you from ever-expanding classpath args

14:41 http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html

14:41 the-kenny: I just started using `echo lib/*.jar|sed -e 's/ /:/g'` some minutes ago

14:41 krukow: ok

14:42 jweiss: can someone point me to an example of using callbacks/listeners in clojure? I am trying to implement something like TestNG in clojure. testng is java, and to add a listener to it you implement one of their interfaces, and it calls your listener when certain events happen.

14:43 the-kenny: ,(doc proxy)

14:43 clojurebot: "([class-and-interfaces args & fs]); class-and-interfaces - a vector of class names args - a (possibly empty) vector of arguments to the superclass constructor. f => (name [params*] body) or (name ([params*] body) ([params+] body) ...) Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, must be first. If not provid

14:44 chouser: jweiss: 'proxy' is the best way to implement an interface

14:44 jweiss: there are examples in contrib and you can probably google for more.

14:44 jweiss: ok

14:44 hiredman: http://clojure.org/jvm_hosted has an actionlistener example

14:45 jweiss: proxy is not what i'm looking for though, i don't need to interact with testng, just do a clojure-only version of it

14:45 chouser: oh!

14:45 then you just write a high-order function.

14:45 'map', for example, essentially calls the "callback" you give it, right?

14:46 jweiss: chouser: yeah i know how to call a single function, but how to group them together like in java's interface?

14:46 i suppose i could just make a map

14:46 of keywords to fn's

14:47 chouser: jweiss: ah. In the "new" branch, defprotocol. but yes, a map would be perfectly acceptible.

14:47 actually, depending on your use cases a map might be best even if defprotocol were available.

14:47 jweiss: i don't know if i'm ready to mess up my new emacs dev environment with the new branch :) i'll try maps

14:48 the-kenny: jweiss: "new" is very stable in my opinion.. never had a crash

14:49 jweiss: the-kenny: yeah i'm more worried about getting it working with swank-clojure

14:49 the-kenny: jweiss: Works without any problems here.

14:50 jweiss: hm. so i just h ave to replace the jar i build in the swank-clojure emacs.d dir?

14:50 the-kenny: "git co new; ant clean; ant build" and the same for clojure-contrib was enough :)

14:50 jweiss: Hm.. Maybe you have to recompile the jar.

14:50 jweiss: the-kenny: swank-clojure jar?

14:50 the-kenny: Yes

14:51 jweiss: k, i'll give it a shot in a bit

14:51 krukow: krukow:~/emacs/clojure/clojure$ git checkout new

14:51 error: pathspec 'new' did not match any file(s) known to git.

14:51 the-kenny: Yeah, you have to add the remote branch.. wait

14:54 jweiss: git checkout --track -b new origin/new

14:54 ?

14:54 the-kenny: yeah, something like this

14:56 krukow: great :-) really gotta read up on git soon...

15:01 kzar: yea me too krukow, submitted a patch the other day and it was pretty easy but I want to learn a lot more about it

15:03 krukow: same here, I read a bit of theory about it but I don't know many actual commands besides git clone :-)

15:04 the-kenny: git is really cool :)

15:04 chouser: http://www.newartisans.com/2008/04/git-from-the-bottom-up.html

15:04 krukow: thx - reading it now

15:04 chouser: that helped me a bit. I should probably read it again, actually.

15:04 kzar: oo thanks I'll read that later too

15:08 Is this kind of code OK or is it bad form to redefine stuff like this with let? (let [example "hello", example (take 3 example)] example)

15:08 stuartsierra: kzar: that's ok

15:09 although it may be more readable to use different names

15:09 chouser: kzar: but it's good you're asking. :-)

15:09 krukow: I would have guessed that would result in an error, but it runs fine

15:09 kzar: Heh cool, it makes more sense in my actual code but I wanted to make sure it's not a taboo or something heh

15:10 krukow: why is that ok - I would consider it bad style

15:10 hiredman: let performs sequential binds so its like (let [example 1] (let [example 2] example))

15:10 krukow: ah

15:10 hiredman: generally it's kind of icky

15:10 but I do it all the time :P

15:10 chouser: it's no worse than using the same local variable to mean a couple different things in any other language.

15:10 rhickey: me too

15:11 krukow: can someone give a compelling example?

15:11 hiredman: usually it means I mean incrementally mucking with a function

15:11 I have been

15:11 fogus_: krukow: I do it when I coerce

15:12 chouser: mm, yes (fn [x] (let [x (int x)] ...))

15:12 hiredman: http://github.com/hiredman/clojurebot/blob/master/hiredman/clojurebot/code_lookup.clj#L66

15:12 started out as google being the google url

15:13 then clojure moved from google svn to github

15:13 kzar: krukow: (I'm having a go at changing my tetris to be functional like a few articles I read. So I have signals being passed and I'm setting the signals to be the result of routing the signals, then setting the signals to be the result of routing the input signals. So I could call them signals, signals after processing, input-signals, input-singals-after-processing ... but I rather just keep 'changing' something called

15:13 signals)

15:13 hiredman: so I wrote a transform to turn the google svn url into a github url

15:13 chouser: I guess I'd say it's a matter of taste. If you're *realy* rather say (fn [x-obj] (let [x (int xobj)] ...), then go ahead. But it hardly seems clearer.

15:14 hiredman: code_lookup is icky anyway

15:14 chouser: nearly all code that actually does anything seems to be icky in the end

15:14 krukow: LOL

15:15 kzar: chouser: At least all the code I've received money for has been

15:15 krukow: can I quote that? ;-)

15:15 chouser: that's one nice thing about projecteuler type problems. You can write tidy little solutions that you can feel good about.

15:15 krukow: :-P sure

15:15 hiredman: sometimes it has a brutalist beauty

15:16 chouser: hiredman: that's true. the beauty of a good hack.

15:19 esj: chouser: you don't mean to tell me that once I've learn't clojure through PE my mercenary coding won't suddenly be beautiful. *crestfallen*

15:20 hiredman: http://gist.github.com/184831 <-- I still like this

15:21 ~ticket search Keyword

15:21 clojurebot: ("#154: (keyword \"a/b\") => ns nil, name a/b; should be ns a, name b" "#154: (keyword \"a/b\") => ns nil, name a/b; should be ns a, name b" "#154: (keyword \"a/b\") => ns nil, name a/b; should be ns a, name b" "#64: GC Issue 61: \t Make Clojure datatype Java Serializable" "#174: Make c.l.Keyword Serializable" "#6: GC Issue 1:\t:validator as keyword arg for ref/atom/agent" "#174: Make c.l.Keyword Serializable" "#200: Exte

15:21 stuartsierra: yowza

15:22 chouser: hiredman: I'm pretty sure I wrote zip-filter exactly so I wouldn't have to write code like that. :-P

15:23 hiredman: ~ticket #64

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

15:23 * the-kenny likes paredit

15:26 krukow: people don't like me at work anymore because of clojure...

15:27 tmountain: krukow: why is that?

15:27 * chouser guesses evangalism

15:27 jweiss: i'm guessing because clojure is greek to them

15:27 krukow: because I've started programming my Java more functionally, I think

15:27 zaphar_ps: krukow: yeah we want to know

15:27 mauritslamers: question: is it possible to create arrays of primitives inside clojure for use in calling Java functions?

15:28 chouser: ,(into-array Integer/type [1 2 3 4])

15:28 clojurebot: java.lang.Exception: Unable to find static field: type in class java.lang.Integer

15:28 chouser: ,(into-array Integer/TYPE [1 2 3 4])

15:28 clojurebot: #<int[] [I@1738d88>

15:28 tmountain: krukow: when every variable in your class begins with final, you know you've drank the koolaid ;-)

15:28 krukow: it does, but it's not just that

15:28 jweiss: ick, can't imagine trying to force java's square peg into that round hole

15:29 stuartsierra: ,(int-array [1 2 3 4])

15:29 clojurebot: #<int[] [I@13bb93a>

15:29 mauritslamers: chouser: when I call my function with that, it returns a ClassCastException

15:29 chouser: stuartsierra: so much better!

15:29 stuartsierra: but I think that creates an array, not convert

15:29 ,(doc int-array)

15:29 clojurebot: "([size-or-seq] [size init-val-or-seq]); Creates an array of ints"

15:29 mauritslamers: stuartsierra: checking out :)

15:29 stuartsierra: nope, it converts to an array too

15:32 mauritslamers: stuartsierra: it seems to return the correct array, but when I call my function with the result, it still throws an ClassCastException

15:32 krukow: anyway, I find myself mimicking clojure constructs in the code

15:32 chouser: mauritslamers: are you sure the method you're calling wants an array of primitive int?

15:32 mauritslamers: public byte[] convertDoubleArrayToByte(double[] incoming){

15:32 hiredman: int[] is not double[]

15:32 stuartsierra: That's a double array you want, then.

15:32 jweiss: hehe

15:33 mauritslamers: of course :)

15:33 (def heletoonsarray (double-array heletoonsbuffer))

15:33 in which heletoonsbuffer is a list of floating point values

15:33 krukow: it's really quite facinating... I've never tried this with a language before

15:33 mauritslamers: doubles to be exact

15:33 chouser: krukow: using clojure idioms in Java?

15:34 mauritslamers: calling the function with: (.convertDoubleArrayToByte dsp heletoonsbuffer)

15:35 chouser: mauritslamers: you're saying that's what you've been doing and you still get the exception? Can you paste the whole stack trace somewhere?

15:35 mauritslamers: how do I get the whole stack trace?

15:35 the only message I get is: user=> (.convertDoubleArrayToByte dsp heletoonsbuffer)

15:35 java.lang.ClassCastException (NO_SOURCE_FILE:0)

15:36 stuartsierra: (.printStackTrace *e)

15:36 chouser: (.printStackTrace *e) if you're at a plain terminal repl

15:37 mauritslamers: the stack trace only contains clojure stuff and sun.reflect et

15:37 *Etc

15:37 chouser: you can often get a better message too if you type-hint the first arg. (.methodOfFoo #^Foo dsp arg2 etc)

15:37 mauritslamers: chouser: http://gist.github.com/241351

15:38 rhickey: urk, looks like pprint rebinds core fns

15:38 hiredman: :(

15:38 chouser: really!? which ones?

15:38 pprint is rather ambitious

15:38 hiredman: mauritslamers: can you pastebin your code?

15:39 mauritslamers: hiredman: which code exactly?

15:39 rhickey: looks like pr

15:39 mauritslamers: it is quite a lot :)

15:39 krukow: chouser: at least thinking much more in terms of identities and values

15:39 hiredman: mauritslamers: the code that produces the exception

15:39 like a small test case

15:39 chouser: mauritslamers: did you try the type hint?

15:40 mauritslamers: chouser: when I do: (.convertDoubleArrayToByte #^ml.mesic.dsp.DSP dsp heletoonsbuffer)

15:40 java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to [D (NO_SOURCE_FILE:0)

15:40 chouser: ah, now we're getting somewhere.

15:40 hiredman: mauritslamers: you are running map or something over the array at some point

15:41 so it is no longer an array

15:41 mauritslamers: it shouldn't...

15:41 moment. checking...

15:41 ah... oops ...

15:41 chouser: :-)

15:41 the best words in a debugging session

15:41 mauritslamers: *shame*

15:41 chouser: naw, that's what debugging is all about

15:42 mauritslamers: it ain't gonna work if I keep feeding it with the wrong argument ... :\

15:42 anyway: thanks a lot :D

15:43 chouser: I wonder why the error message is different for dynamic method calls

15:43 krukow: if the bug isn't there it's because it is somewhere else

15:43 hiredman: http://hsivonen.iki.fi/rdf-competition/

15:44 rhickey: so, that's a good example - some lib like pprint wants to redefine something like pr for everyone. Leaving all those hooks open means slowing everyone else down...

15:45 aargh - (deftest dotrace-on-core ...)

15:53 mauritslamers: interesting... my function written in java is much much MUCH faster than the one in clojure...

15:55 For those interested: http://gist.github.com/241366

15:55 the clojure code takes at least half a second

15:57 KirinDave: The JVM is pretty notoriously bad at byte-level manipulation.

15:57 mauritslamers: but why is the java code faster than the clojure code :)

15:58 stuartsierra: mauritslamers: The difference in this case comes from the overhead of Clojure's persistent data structures.

15:58 Every call to your float-to-two-bytes creates a persistent vector as an intermediate value.

15:58 mauritslamers: so for this type of conversions it is better to write stuff in java

15:58 and create a clojure wrapper

15:59 rhickey: hrm, mocking is in obvious conflict with direct linking...

15:59 stuartsierra: Also, Clojure's bit-shifting operations are not well-optimized.

15:59 mauritslamers: you would get closer to Java performance by writing a single function using loop/recur and Java arrays instead of reduce/mapcat

16:00 But you will probably not be able to match Java performance on bit twiddling (yet).

16:00 rhickey: only failures in clojure and contrib with direct linking are now in the mocking stuff

16:00 mauritslamers: stuartsierra: which is not really a problem, since I have to do other java stuff anyway :)

16:01 I need the bit twiddling to be as fast as possible

16:01 thanks!

16:01 stuartsierra: rhickey: what's this mocking/linking?

16:01 * mauritslamers needs to go now :)

16:01 mauritslamers: tty all later!

16:02 KirinDave: It'd be cool if Clojure had optimized binary pattern matching like erlang. :)

16:02 rhickey: stuartsierra: I now can do direct-linking of call sites. For code you are not going to be changing at runtime, nor rebinding (e.g. core, etc) you can get much faster perf by limiting dynamism and directly hooking up the callee. The mocking is just the contrib library, the only thing left in contrib that doesn't work with direct linking

16:03 stuartsierra: I see.

16:03 I like.

16:03 wtetzner_: how do i use the clojure printer from java?

16:03 i found the reader in LispReader.class

16:03 but i can't find the printer

16:04 stuartsierra: wtetzner_: You can invoke the clojure.core/print function directly.

16:04 RT.var("clojure.core", "print").invoke(...)

16:04 wtetzner_: oh

16:04 cool

16:04 thanks

16:04 hiredman: prn

16:04 I imagine you'll want prn

16:04 wtetzner_: so you can call any clojure functions that way?

16:05 rhickey: stuartsierra: fyi, test/report was another problem area

16:05 wtetzner_: hiredman: yeah, actually prn-str

16:05 stuartsierra: Oh, yeah.

16:05 rhickey: but now test/report and pr are marked {:dynamic true}

16:05 krukow: rhickey: why are these problematic?

16:05 rhickey: so test and pprint work

16:05 stuartsierra: rhickey: Ok.

16:05 rhickey: krukow: they are being dynamically rebound by design

16:06 krukow: ok so just marking them is fine

16:06 stuartsierra: rhickey: So does this mean that any var which is dynamically rebound must be declared {:dynamic true}?

16:06 rhickey: krukow: I've been testing all of clojure and contrib with direct linking

16:06 KirinDave: Or can we enable an optimization by saying {:dynamic false}

16:06 krukow: what kind of speed up are you expecting from direct linking?

16:06 rhickey: stuartsierra: just vars that are invoked, so not your normal *foo* stuff

16:07 stuartsierra: rhickey: Ok, that's good.

16:07 Functions, in other words.

16:07 rhickey: functions

16:07 right

16:07 chouser: you get an error? when?

16:08 rhickey: krukow: it can be quite substantial, depending on what the function does, but overall you can see 20% easily, some specific calls might be several times faster

16:09 chouser: what error?

16:10 chouser: if you try to dynamically bind a static fn

16:10 do you get an error or just the root binding behavior?

16:10 rhickey: chouser: no error, just won't be dynamic

16:10 chouser: hm

16:10 KirinDave: So you'd try to rebind it and it'd fail for some calls?

16:11 rhickey: as I was saying before, direct linking is a property of the caller, not the callee

16:11 one caller could directly link and another not

16:11 KirinDave: Ah

16:11 stuartsierra: even better

16:11 So which is declared {:dynamic true}? The caller or the callee?

16:12 krukow: I guess that could give some strange behaviour with binding core fns

16:12 rhickey: a directly linked caller will see the original value forever (or until they themselves are re-evaluated)

16:12 krukow: that's the question - who's binding core fns and why?

16:12 there was only one case in all of contrib - pprint

16:13 none in core

16:13 trivial functions can be 10x faster with direct linking

16:14 so, it's important, to me at least

16:14 krukow: I was just thinking of an example on the web:

16:14 stuartsierra: I assume direct linking allows the JVM to inline the function as well?

16:14 rhickey: but the general question is, how do we want to talk about this, at what granularity, with what defaults

16:14 stuartsierra: yep

16:14 krukow: cant find it right now, but I think it was about using binding to create som AOP like feature

16:15 rhickey: krukow: one option could be - I never want direct linking

16:16 stuartsierra: rhickey: I feel I should mention that it feels like features keep getting added, pushing a 1.1 release farther into the future.

16:16 rhickey: that is the simplest story for ad hoc whatever

16:16 stuartsierra: I mean, they're cool features, no question, but have you thought about where you're going to stop?

16:16 hiredman: stuartsierra: 2.0 :P

16:17 krukow: actually it sounds very cool to me - just immediately trying find an example it would break :-)

16:17 rhickey: stuartsierra: none of this is going into 1.1. I would love it if someone would come up with a punch list for calling what we've got 1.1, producing some release candidates etc. I've added a new field in the tickets - bug/enhancement - I'd like to see all tickets categorized

16:17 stuartsierra: Would that include deftype/defprotocol?

16:18 rhickey: stuartsierra: nothing from new is going in 1.1, so no deftype/defprotocol

16:18 spuz: In Clojure, if a variable is not actually variable... then what do we call it?

16:18 hiredman: spuz: a binding

16:18 rhickey: It came up the other day that chunked seqs might be controversial - we need the broader community trying master

16:18 krukow: rhickey: when do you expect deftype/protocol?

16:19 spuz: hiredman: funny how I could read a whole book about clojure and not get that...

16:19 stuartsierra: If it's any help, I've been using master for months without any problem.

16:19 rhickey: krukow: soon after 1.1, at least with 1.1 out it can move into master and get more hands on it. But it is still a work in progress

16:20 krukow: really looking forward to it, btw :-)

16:20 rhickey: stuartsierra: right, and yet, I think hiredman and AWizzArd were both troubled by it the other night, as it can change full lazy semantics. And we don't have a seq1 to force dribbling

16:21 hiredman: spuz: I was just looking over the chapter on lexical bindings in essentials of programming languages

16:21 rhickey: I'd love to know how the community breaks down as far as which release/branch they use

16:21 stuartsierra: rhickey: Ah, ok, hadn't considered that.

16:22 rhickey: so, 1.1. is a matter of - no new enhancements, tidy up anything unfinished, produce release candidates and get broader feedback, cut a release when ready

16:23 the new branch work will follow 1.1

16:23 krukow: diff 1.1 1.0?

16:23 rhickey: but I am fully (like 10 hrs a day) occupied with the new branch, so people that want 1.1. have to step up and volunteer

16:24 krukow: I want the new branch :-)

16:24 rhickey: krukow: right, but we want releases of things that are relatively stable, as is master right now

16:24 krukow: I'm not sure if it is my object oriented mind kicking in but I am missing deftype

16:25 sure - I value stability highly

16:25 stuartsierra: rhickey: I'm volunteering. :)

16:25 rhickey: but yes, deftype/protocols fill an important gap

16:25 stuartsierra: great!

16:26 stuartsierra: I'll start by making a which-release-are-you-using survey

16:26 hiredman: clojurebot: stuartsierra is volunteering

16:26 clojurebot: c'est bon!

16:27 stuartsierra: rhickey: What do you want to know, besides http://spreadsheets.google.com/viewform?formkey=dFJSd1p4YXh0d0VxV0xjdk42MTU5RkE6MA

16:28 chouser: what's a SNAPSHOT release?

16:28 spuz: is there a command to reset the state of the REPL?

16:28 stuartsierra: The maven repositories take snapshots of master roughly every 24 hours

16:28 rhickey: is that from hudson?

16:28 chouser: is that just some version of master we've chose ourselves, vs. "github master" being continuouly upgrading?

16:28 ah

16:29 the-kenny: What are chunked sequences? :)

16:29 stuartsierra: chouser: I was thinking keeping it up to date regularly.

16:30 twbray: Wondering why if-let only lets you do one binding... I have two or three bindings to do and some forms to run, but only if the first binding is non-nil. Why would that be wrong?

16:31 chouser: stuartsierra: ok. I recently switch our work code from 1.0 to some a recent 1.1-snap, but probably won't change it again until 1.1.0. wasn't sure which answer I'd pick for that.

16:31 rhickey: stuartsierra: question 1 is good enough for me. Maybe asking people if they know how to get from github or maven. But if we do release candidates we can make that just a download for everyone

16:32 chouser: twbray: some people that ask for mutliple if-let bindings only want the "true" case if all the bindings are true. you're asking for something different?

16:32 rhickey: twbray: if if-let did multiple bindings, it would be unclear as to which would be involved in the conditional

16:32 KirinDave: twbray: It's probably just historical. This is why we have macros and -contrib.

16:33 twbray: Hmm... I read the docs and assumed it would key off the first binding.

16:33 spuz: yes, what are chunked sequences? :)

16:33 twbray: chouser: Yep... I can see the ambiguity.

16:34 krukow: spuz http://blip.tv/file/2301367

16:34 chouser: http://www.assembla.com/wiki/show/clojure/Chunked_Seqs

16:34 hm, that's pretty thin

16:34 twbray: So I'm left with (let [x (some complex fun)] (if x (let [bunch of other bindings]. Not terrible I guess.

16:34 stuartsierra: ok, changed the questions a bit: http://spreadsheets.google.com/viewform?formkey=dFJSd1p4YXh0d0VxV0xjdk42MTU5RkE6MA

16:35 hiredman: twbray: you can still use if-let

16:36 spuz: krukow: thanks, it says "Rich Hickey, inventor of Clojure, talks about the new "chunked seq" architecture which allows first-order Clojure functions such as map to as fast (or faster) than hand-coded loops." why would that be a bad thing? Why ask the question in the questionnaire?

16:36 KirinDave: twbray: Why not try and get a macro into contrib? I'm sure people would use it. It sounds useful.

16:36 spuz: (obviously, I still need to watch the video, but just incase it's not obvious...)

16:36 rhickey: stuartsierra: I recently made another milestone - Approved backlog - into which we can move things from Next Release that aren't going in, in order to use Next Release as a punch list

16:36 stuartsierra: ok

16:37 hiredman: spuz: it can alter the lazy nature of seqs

16:37 spuz: ah I see

16:37 hiredman: because chunked seqs are processed in 32 item chunks

16:37 rhickey: http://clojure.googlegroups.com/web/chunks.pdf

16:38 twbray: hiredman: Right... (if-let [x (some complex func)] (let [ other bindings] ...

16:38 chouser: twbray: that's not an uncommon pattern in my code, fwiw.

16:41 falkor2: hi, why is there clojure.lang.PersistentList$1 ? My question regards the $1, I seem to see it inside macros...

16:41 chouser: falkor2: that's normal Java naming for a anonymous inner class

16:42 twbray: chouser: Thanks, that's the kind of thing a n00b likes to hear.

16:42 falkor2: yep, I know, but sometimes it is not therre

16:42 rhickey: looks like there are a dozen or so patches waiting in backlog, but they should probably wait until after 1.1 unless trivial

16:43 falkor2: (println (type '(1)) -gives persistentlist (no $1)

16:44 hiredman: falkor2: some annonymous subtype of plist

16:44 falkor2: `(println (type ~lst)) [Note in macro], gets $1

16:44 hiredman: implementation detail

16:44 ignore it

16:44 chouser: ,(class clojure.lang.PersistentList/creator)

16:44 clojurebot: clojure.lang.PersistentList$1

16:45 falkor2: The problem is that I am doing type inspection (probably not in the best way...)

16:45 chouser: PersistentList$1 is a function, not a list

16:45 hiredman: falkor2: don't

16:46 chouser: falkor2: lst may not be what you think it is, or may be being misused.

16:46 stuartsierra: rhickey: any more questions for the survey, before I post it to the group?

16:46 falkor2: I am doing macros (newbie) and I think I am being bitten by some confusion still lingering in my head...

16:47 rhickey: stuartsierra: the whole 'reliability' part of it seems a little weird

16:47 stuartsierra: What do you want to know?

16:47 I thought that was the point.

16:47 chouser: falkor2: seems plausible. maybe paste somewhere your macro that's includes the `(println (type ~lst)) ?

16:48 rhickey: I think we get the reliability reports on the group etc, I really want to know if they are using master yet

16:48 stuartsierra: ok, I'll drop that question.

16:48 rhickey: i.e. are we close to 1.1. from a community feedback perspective, or have most of them never tried the master code, and we'll be seeing a lot of new reports once we do a release candidate

16:48 stuartsierra: And the "Describe any reliability problems..." question.

16:49 ok, just 3 questions now

16:49 rhickey: it used to be, most people were on trunk, so when the bug reports eased, we were good to go. Now, I'm unsure what the ratios are, and with more, and more conservative, users, we might need a decent beta period

16:50 KirinDave: So where is the right place to get the most current stable clojure?

16:50 The github?

16:50 stuartsierra: KirinDave: define stable :)

16:50 There is one official release, 1.0.

16:50 KirinDave: stuartsierra: Well, usable.

16:50 yes, but no one seems to use that. :D

16:50 They want the new features.

16:50 chouser: well the 'master' features at least, if not the 'new' ones.

16:51 * chouser giggles

16:51 falkor2: chouser: I think I have to do a bit more self-investigation before I pester you guys ;)

16:51 stuartsierra: All the major new features (reify, deftype, defprotocol) are on the "new" branch.

16:51 The "master" branch seems to be quite stable.

16:51 KirinDave: So are people going builds from http://github.com/richhickey/clojure:master?

16:51 chouser: falkor2: ok, that's up to you. Don't get too frustrated though before asking.

16:51 stuartsierra: But "master" doesn't have any whiz-bang new features.

16:51 chouser: falkor2: and if it's about a macro, we have a form to help ask the question well.

16:52 ~macro help

16:52 clojurebot: macro help is http://clojure-log.n01se.net/macro.html

16:52 rhickey: it's all usable, that's always been the Clojure way. some of the very latest features are works in progress, but you won't have existting code that a) uses them, or b) will be broken by them

16:52 KirinDave: Cool, so it's relatively safe to run off new then?

16:52 rhickey: if you use the latest features, you are helping me define them with your feedback

16:52 chouser: stuartsierra: that's just an age thing. master has futures, chunked seqs -- good stuff!

16:52 falkor2: I have to say, coming from Prolog, that evaluation in lisp is made a bit complex and convuluted

16:52 stuartsierra: chouser: Oh, I thought futures were in 1.0

16:53 rhickey: KirinDave: master is the best choice unless you are really interested in the new features and testing

16:53 chouser: stuartsierra: hm, I may be thinking of promises

16:53 stuartsierra: chouser: promises, promises

16:53 chouser: exactly

16:53 rhickey: there are a ton of new things in master, we're all just used to them already

16:53 chouser: exactly

16:54 stuartsierra: We're blase'

16:54 rhickey: nice

16:54 chouser: anyone want to bet on survey results?

16:54 stuartsierra: ok, ready to go? http://spreadsheets.google.com/viewform?formkey=dFJSd1p4YXh0d0VxV0xjdk42MTU5RkE6MA

16:54 chouser: I say <20% of responders on 1.0

16:54 rhickey: stuartsierra: sure - we'll know more than we do now! Thanks

16:54 stuartsierra: no problem

16:55 rhickey: stuartsierra: wanna stick a logo on it?

16:55 hiredman: you should stick a picture of a wallaby on it

16:55 chouser: if you like it you should stick a ring on it

16:55 rhickey: hiredman: because?

16:56 chouser: um. nevermind.

16:56 hiredman: they're cute

16:56 stuartsierra: rhickey: don't know how to do that on GDocs.

16:56 hiredman: chouser: ha ha

16:56 rhickey: stuartsierra: ok

16:56 stuartsierra: and I already emailed it to the lists

16:57 chouser: the url doesn't change when you edit the doc

16:57 oh, inlined. nevermind

16:58 rhickey: it's fine

16:58 falkor2: There are other ways to get clojure, BTW: I mostly use whatever comes in enclojure....

16:58 technomancy: like leiningen. =)

16:59 chouser: stuartsierra: care to share the results url?

16:59 so that I can obsessively reload it?

17:00 stuartsierra: technomancy: ok, added "IDE/Package manager" as an option.

17:00 chouser: yes, hang on

17:00 chouser: while you're fixing things, typo on "the help me"

17:01 stuartsierra: chouser: thanks, fixed

17:02 rhickey: looks like 2 how do you get questions now

17:03 stuartsierra: yes

17:03 from the early responses

17:03 oops, ok, fixed

17:06 Results link: http://spreadsheets.google.com/ccc?key=0AuEMlyQZQkUMdFJSd1p4YXh0d0VxV0xjdk42MTU5RkE&hl=en

17:06 chouser: stuartsierra: thanks

17:07 stuartsierra: "Form-> Show summary" gives you pie charts.

17:07 zaphar_ps: one question is shown twice

17:07 stuartsierra: zaphar_ps: fixed now

17:07 Oh, in the results? yes, that's a leftover

17:07 zaphar_ps: ahh ok

17:08 github is obviously the most frequent method to get clojure shown so far

17:09 chouser: "in early results"

17:09 zaphar_ps: which probably features the early adopter type crowd

17:09 chouser: with less than 2% of precincts reporting...

17:09 zaphar_ps: :-)

17:09 stuartsierra: Ok, that's my contribution for the day, got to go.

17:09 chouser: I can't choose the "form" menu

17:10 (to see the pie charts)

17:10 stuartsierra: huh

17:10 zaphar_ps: me either

17:10 stuartsierra: Are you logged in with a Google acct?

17:10 chouser: stuartsierra: don't worry about it. go do what you need to do.

17:10 yeah

17:11 stuartsierra: Don't know how to fix that.

17:13 chouser: heh. I "made a copy" of the spreadsheet, and there I can choose form->show summary, but it says 0 responses

17:14 hiredman: clojurebot: ~logs

17:14 clojurebot: logs is http://clojure-log.n01se.net/

17:17 falkor2: OK, I think a more clever question would be: Is is possible to know, in a macro, the type of an object without executing it? Say, I do (mymacro (1 2 3) (println 3) ) And are able to see the type of both lists, and execute the 2nd?

17:17 hiredman: the type of what?

17:17 the datastructure passed to the macro?

17:17 falkor2: Whatever I pass to the macro...

17:18 hiredman: the type of the result of calling eval on the datastructure?

17:18 falkor2: so in this case, There are 2 lists

17:18 no, not the result

17:18 but I would like to inspect the objects without executing them

17:18 hiredman: why are you interested in concrete types?

17:19 falkor2: mainly in seeing the first element and do a decision on how to proceed

17:19 hiredman: falkor2: have you looked at multimethods?

17:19 falkor2: I need something a bit more general

17:19 hiredman:

17:19 falkor2: let me explain

17:19 hiredman: then you haven't looked at multimethods

17:20 multimethods let you define a dispatch function

17:20 that is about as general as you can get

17:20 funkenblatt: i think he wants to decide whether to evaluate based on the car of each list

17:20 falkor2: I have, and I have code with mm on github

17:20 let me explain

17:20 hiredman: funkenblatt: very doable

17:21 falkor2: I want to be able to do something like this ((new StringBuffer "bla") (add "ble") (add "bli"))

17:21 The result being a SB "blablebli"

17:21 the-kenny: falkor2: doto?

17:21 falkor2: maybe, let me reread doto

17:21 hiredman: ,(doto (StringBuilder.) (.add "a") (.add "b"))

17:21 clojurebot: java.lang.IllegalArgumentException: No matching method found: add for class java.lang.StringBuilder

17:22 hiredman: bah

17:22 ,(doto (StringBuffer.) (.add "a") (.add "b"))

17:22 clojurebot: java.lang.IllegalArgumentException: No matching method found: add for class java.lang.StringBuffer

17:22 the-kenny: ,(doto (StringBuilder.) (.append "a") (.append "b"))

17:22 clojurebot: #<StringBuilder ab>

17:22 hiredman: right

17:22 the-kenny: ,(.getString (doto (StringBuilder.) (.append "a") (.append "b")))

17:22 clojurebot: java.lang.IllegalArgumentException: No matching field found: getString for class java.lang.StringBuilder

17:22 the-kenny: ...

17:22 hiredman: the-kenny: toString

17:22 or just str

17:22 the-kenny: ,(.str (doto (StringBuilder.) (.append "a") (.append "b")))

17:22 clojurebot: java.lang.IllegalArgumentException: No matching field found: str for class java.lang.StringBuilder

17:22 hiredman: the-kenny: str is not a method

17:23 funkenblatt: well in any case looks like my interpretation of what he wanted was completely wrong

17:23 hiredman: http://gist.github.com/222974

17:23 the-kenny: hm.. I think falkor2 knows what we mean

17:23 falkor2: I think doto is probably enough. Newbie questions, sorry

17:24 My objective is to be able to create tree like structures in an easy fashion

17:24 (think lots of swing components embedded in one another)

17:25 the-kenny: Maybe something like clojure.zip?

17:25 (I'm not sure what you want to do)

17:26 hiredman: swing is very imperative

17:26 I don't you want to use zippers for interacting with it

17:26 doubt

17:27 the-kenny: hiredman: I thought about creating and traversing the tree structure with zippers

17:27 falkor2: Mainly I am trying to construct tree like structure of Java objects in an easy way (think a JFrame which contains a Menubar, which contains menus, and so on and so forth)

17:27 Trying to devise a way with little boillerplate code

17:27 hiredman: the-kenny: zippers are a functional tree editing construct

17:28 there would be a significant mismatch for bidirectional swing<->zipper

17:31 falkor2: I am going to research doto, thanks. My final objective is to have a dynamic way to construct Java tree-like structures easily.

17:32 hiredman: you migh do some kind of batched convert to zipper, edit, update ui

17:34 falkor2: I am going to have a look, thanks for the tips.

17:42 cow-orker: ,char?

17:42 clojurebot: java.lang.Exception: Unable to resolve symbol: char? in this context

17:42 cow-orker: why is this so....?

17:43 hiredman: because the function does not exist

17:43 the-kenny: cow-orker: My repl doesn't lnow this function either.

17:43 KirinDave1: Man I updated lein and broke it

17:43 cow-orker: sure, but why?

17:43 KirinDave1: I spend like 5x as much time futzing with lein as I do actually coding.

17:43 cow-orker: ,integer?

17:43 clojurebot: #<core$integer_QMARK___5623 clojure.core$integer_QMARK___5623@78fac9>

17:43 cow-orker: ,vector?

17:43 clojurebot: #<core$vector_QMARK___4488 clojure.core$vector_QMARK___4488@346801>

17:43 hiredman: cow-orker: no one has bothered to write it

17:43 cow-orker: etc etc .... but no char?

17:43 ok, fair enough :)

17:44 hiredman: (partial instance? Character)

17:44 KirinDave1: Is "lein new _name_" or "lein help" broken for everyone or just me?

17:45 hiredman: ,((partial instance? Character) \a)

17:45 clojurebot: true

17:45 hiredman: ,((partial instance? Character) 1)

17:45 clojurebot: false

17:45 technomancy: KirinDave1: help is broken due to a Clojure bug if lein has been AOT'd.

17:45 KirinDave1: technomancy: Same deal for new?

17:45 technomancy: KirinDave1: not that I know

17:46 KirinDave1: technomancy: "Could not locate leiningen/new__init.class or leiningen/new.clj on classpath", you know?

17:46 cow-orker: hiredman: thanks. Was looking at core.clj and just wondered if there was something special wrt characters. Guess not :)

17:46 technomancy: KirinDave1: you're on 1.0.0-SNAPSHOT and have updated your bin script?

17:47 (new didn't exist in 0.5.0)

17:47 KirinDave1: Oh, well

17:47 When i pulled from the url in your repo

17:47 i got 0.5.0

17:50 technomancy: Following the directions in the mailing list seems to work better. :)

17:52 Chousuke: technomancy: good work with leiningen btw. It seemed to me to appear out of thin air and now I see mentions of it everywhere :P

17:52 technomancy: KirinDave1: right; the readme points to with the stable branch

17:52 Chousuke: thanks! it's obvious now that it's addressing pain that a lot of people feel.

17:52 Chousuke: now Clojure itself needs to start using it.

17:53 :P

17:53 technomancy: chicken, meet egg.

17:56 funkenblatt: delicious delicious egg

17:56 man now i'm hungry

17:59 KirinDave1: Man, I just have no luck with lein.

18:09 technomancy: KirinDave1: I'm a bit busy right now, but there's a mailing list for leiningen: http://groups.google.com/group/leiningen

18:45 ambient: clojure-mode from ELPA is telling me that clojure-install is deprecated. what should I use instead?

18:48 technomancy: ambient: M-x slime should download Clojure if swank-clojure is installed.

18:49 ambient: nvm, i was a bit reading impaired. technomancy.us/swank-clojure seems to be the way

18:50 technomancy: ok, ty

18:52 it installed version 1.0.0 :(

18:53 and i dont even know where to

18:53 technomancy: ambient: sounds like you want option 2 then

18:53 _ato`: ambient: ~/.swank-clojure

18:55 I also had to move swank.jar into ~/.clojure to get M-x swank-clojure-project to work :\

18:59 KirinDave1: Man, too much time spent trying to get this to work. :\

18:59 I am just gonna go back to lein 0.5.0

18:59 Good thing I have lots of time today with my 800000 installs of windows.

19:00 _ato`: KirinDave1: yeah, best to stick with stable version unless you want to hack on lein itself.

19:01 KirinDave1: _ato: Probably should remove the .jar tho

19:01 It seems completely broken.

19:01 Referring to a method that does not exist at invocation, etc. etc. :)

19:02 _ato: yeah, you probably know but they're installed under: ~/.m2/repository/leiningen/leiningen/

19:02 KirinDave1: Yes.

19:02 The 1.0.0-SNAPSHOT invokes main when I think it means to invoke "-main"

19:04 technomancy: no, it got renamed to "main" in master; that's correct. we're no longer gen-classing.

19:23 tomoj: is there something wrong with "java -cp lib/* clojure.main" in a swank-clojure-project-style project?

19:23 qed: wow I need to learn Java

19:23 tomoj: oh, yes, of course

19:23 needs to be quoted

19:24 qed: I've been secretly hoping this whole time learning clojure that I'd be able to completely ignore Java

19:24 but it looks like a dirty necessity

19:24 tomoj: yup :/

19:24 qed: To what extent seems to be the question

19:24 tomoj: they taught me java here at school, luckily. but I still haven't forced myself to learn ant or maven or..

19:25 _ato: KirinDave1: ah.. I just realised what the problem is, technomancy's snapshot is 4 days out of date

19:26 tomoj: packaging seems to be the dirtiest part to me, maybe new clojure tools will help hide that from us :)

19:27 qed: it'll get better

19:27 technomancy: _ato: I guess I should put a note that self-install should not be relied upon for snapshot versions

19:28 it's so easy to get out of sync

19:28 _ato: technomancy: yeah, probably a good idea to chuck a check in the lein script as well that spits out a warning if the version ends in snapshot

19:28 qed: i do all of my clojure/swank/slime setup manually

19:28 it just seems cleaner that way, no offense technomancy

19:32 ambient: this bothers me, to use clojure efficiently there still remains a significant threshold for not-so-smart people

19:33 tomoj: isn't there clojurebox or something?

19:34 ambient: certainly. i'm just lamenting that in my view, there's no "perfect" development environment yet, in which i would feel comfortable in, without wanting some random feature or convenience

19:34 i could make emacs such, but in my experience, it becomes with a significant burden

19:43 chouser: I'm hopeful. Lisp was not an acceptable lisp, and then came clojure.

19:43 emacs is not an acceptable emacs, but maybe something will come along.

19:44 technomancy: lexical scoping and threading in emacs 24!

19:44 * technomancy crosses fingers

19:44 chouser: hm

19:44 really?

19:44 technomancy: chouser: there's talk of it

19:45 chouser: with those, it might make an acceptable clojure compilation target.

19:45 technomancy: possibly coroutines instead of threads; that's fine w/ me

19:45 chouser: I've thought about that, believe me. =)

19:46 hiredman: best to start now

19:46 clojure subset to elisp compiler

19:46 "translator"

19:46 technomancy: might be fun to compile directly to elisp bytecode

19:47 hiredman: that would be even better

19:47 chouser: no point in starting pre-cinc

19:47 hiredman: I wasn't aware there was elisp bytecode

19:47 chouser: not a full clojure port

19:47 more like code gen guided by feed in clojure forms

19:47 technomancy: hiredman: someone ported a destructuring version of let already; it's pretty nice

19:48 hiredman: emacs :(

19:48 qed: gah I get so confused at this Creating & Compiling Java Classes in Clojure section of Stuart's book

19:49 _ato: qed: with anything in particular?

19:49 funkenblatt: i thought emacs has had destructuring bind in the 'cl package for a while

19:49 qed: i worked through this section last night _ato -- im going to try my luck again. If i have an issue ill ask though, thanks :)

19:51 is the (.. class-or-inst form & forms) special form kind of like (->)?

19:51 _ato: yes

19:52 technomancy: funkenblatt: not with hashes

19:52 funkenblatt: ah

19:52 _ato: qed: it came from before the (.foo obj) notation was introduced IIRC. Better to do (-> obj (.foo) (.bar)) rather than (.. obj (foo) (bar)), as you can also use clojure functions with ->

19:53 qed: ok _ato -- here's where I get confused, and this might just be my java ignorance, but the (proxy class-and-interfaces super-cons-args & fns) is scary to me

19:53 ah right _ato that makes sense

19:53 _ato: hehe it is scary!

19:53 class-and-interfaces = classes and interfaces you are subclassing/implementing with proxy

19:54 super-cons-args = arguments to the superclass' constructor, so if you're subclassing class Foo and need to pass in some args like: (Foo. 1 2 3) this is where you'd put them

19:55 both of them should be vectors

19:55 qed: okay so far so good

19:55 _ato: and fns is jus the fns you want to override. So if you want do override. (.foo obj 1 2 3), you'd put (foo [x y z] ...) there

20:08 qed: _ato: i think what is confusing me is...and this might sound ridiculous...but...why?

20:08 like...what are we doing essentially by using proxy

20:09 tomoj: qed: are you totally new to java? or you know a bit?

20:09 qed: I know some Ruby, I took some AP Java in high school, a semester of it

20:10 tomoj: well in ruby you can make a subclass and override some methods

20:10 qed: MyController < ApplicationController

20:10 something like that?

20:11 tomoj: yeah, but..

20:11 I guess it's sortof like a ruby singleton class maybe

20:11 you just get a single instance of this new class

20:12 so like if you want to make a JFrame instance but override some methods, instead of creating a new class MyJFrame and instantiating it, like you would in java, you can just proxy JFrame

20:12 you get an instance of an anonymous subclass with your overridden methods

20:12 qed: oh okay okay, i think i see where this is going

20:13 hiredman: (except extending JFrame like every java gui tutorial does is a horrible idea)

20:13 qed: (def print-element-handler (proxy [DefaultHandler [] (startElement [uri local qname atts] (println (format "Saw element: %s" qname)))))

20:13 _ato: yeah

20:14 qed: so we are making an anonymouse instance of DefaultHandler and overriding startElement?

20:14 hiredman: you are missing a ]

20:14 qed: ah yeah, so i am

20:14 _ato: qed: it's basically because many java libraries force you to subclass one if their types in order to use their API

20:14 hiredman: _ato: if you are lucky, one of their interfaces

20:15 qed: so what is [uri local qname atts]

20:15 hiredman: the arguments to the method

20:15 _ato: it's the arguments passed to .startElement

20:15 qed: do they need to be named exactly like the the method names them?

20:15 hiredman: proxy generates a class

20:15 qed: nope

20:15 qed: so i could just do q1 q2 q3 q4

20:15 _ato: no, it's just like (defn startElement [uri local qname attrs] ...)

20:15 yeah

20:16 except that it creates a java method

20:16 instead of a clojure function

20:16 qed: sure, okay

20:16 _ato: (method meaning it's attached to a class instead of being "global" like a function)

20:16 hiredman: proxy stubs out the java methods in the generated class, and just passes the arguments off the to clojure fn created from the proxy form

20:16 qed: thanks guys, im gonna get back to playing with this -- just for fun, does anyone have an easy example of a Java class/method I could use proxy on?

20:16 hiredman: ACtionListener

20:16 qed: im gonna try to write a couple of them

20:16 hiredman: ActionListener

20:17 FileFilter?

20:19 tomoj: hiredman: got disconnected, was the verdict horrible or not horrible?

20:19 qed: like: (def action-performed (proxy [ActionListener] [] (actionPerformed [event] (println (format "Performed %s" event)))))

20:20 tomoj: I think the only time I've ever used proxy was for a KeyListener

20:21 hiredman: tomoj: verdict on?

20:21 tomoj: which overrode keyPressed to call a handler-fn on the event

20:21 hiredman: qed: are you familiar with java's anonymous classes?

20:21 tomoj: oh, is proxying swing classes always horrible?

20:21 or did you just mean JFrame in particular

20:21 qed: hiredman: im familiar with Ruby's

20:22 hiredman: does ruby hava anonymous classes?

20:22 qed: the "ghost" class, singleton class, eigenclass, uniclass, etc.

20:22 tomoj: ruby has anonymous classes?

20:22 qed: yes

20:22 tomoj: oh, that's sorta like proxying but backwards I think

20:22 when you proxy you make an anonymous class and then instantiate it once

20:22 hiredman: http://blog.jayfields.com/2008/02/ruby-creating-anonymous-classes.html

20:23 tomoj: with the singleton class you've got an instance of some class and then you can stick your overridden methods in for just that instance, so, same effect I guess

20:23 hiredman: anyway

20:23 yeah, proxy creates an instance of an anonymous class

20:23 tomoj: in ruby proxy'ing would be unnecessary since we don't have to dance around to satisfy java's type system anyway

20:24 hiredman: well, it creates an anonymous class, and then returns an instance

20:25 qed: so it creates this anon class, and then an instance of it with my overridden methods, i guess im still struggling to see applicable scenarios not having worked with Java much at all

20:25 that's really where im really trying to get clarification, some examples of this in action

20:25 tomoj: well, for example, swing wants you to give it a KeyListener to listen to key events in the GUI

20:25 _ato: qed: java doesn't have first class functions

20:25 you can't pass a function to another function in java

20:26 tomoj: I don't want to make a java class which subclasses KeyListener, so I just proxy it

20:26 _ato: so you basically use anonymous classes or subclasses instead

20:26 tomoj: yeah, in clojure I'd just be able to pass a fn to call on the key event I suppose

20:27 Runnable too, eh?

20:27 qed: Callable/Runnable yeah

20:27 _ato: when you say fn in java, you mean method, no?

20:28 we're essentially creating an anonymous function from some Java method?

20:28 _ato: yeah, it doesn't have functions and it's methods aren't first class, they don't exist as objects themselves. You can't pass them around. It doesn't even have function pointers. (leaving aside reflection, which doesn't really count)

20:29 tomoj: eh

20:29 I think we're essentially doing some little dance to make up for the fact that java can't do that

20:29 qed: so we're sort of creating an abstract version of a java method

20:29 so we can use it all over the place in clojure

20:30 tomoj: where you would pass a fn in clojure, you instead pass a singleton of some anonymous class

20:31 java code you're interoping with wants some object which extends/implements certain classes/interfaces - it doesn't care that clojure is dynamic

20:31 qed: is there a way to get the methods for a Java class in my REPL?

20:31 tomoj: so you use proxy to make a one-off subclass/implementation

20:31 c.c.repl-utils has show

20:32 if you're using slime you should be able to use the slime inspector as well

20:32 like C-c I Math

20:32 qed: awesome, that's a big help

20:33 okay okay, this is starting to make real sense now

20:33 _ato: What I find really funny is a lot of java folks have been against adding closures/lambda expressions to java because they're "too complex". So instead you've got to do to this annoying subclass / anonymous class dance which actually turns out to be harder and more complex.

20:34 tomoj: I remember really enjoying learning about anonymous/inner classes because they seemed so esoteric

20:34 qed: We're just making some version of a Java method which implements a Class/Interface, so we can fake Java into talking to our version of it which we create with a proxy

20:34 _ato: qed: exactly

20:34 tomoj: I guess maybe they're much easier to implement in java, though?

20:34 qed: tomoj: yeah i really enjoyed the ruby metaprogramming stuff

20:34 very fun

20:36 tomoj: I had heard rumors about closures coming to java, though

20:37 qed: okay so I have (def get-month (proxy [Date] [] (getMonth [month] (println (format "The month is %d" month)))))

20:37 what am i doing wrong there?

20:40 tomoj: getMonth doesn't take a parameter

20:41 so "month" is not what you think it is, I think

20:43 ,(.getMonth (proxy [Date] [] (getMonth [] (println "foo") 3)))

20:43 clojurebot: java.lang.RuntimeException: java.lang.IllegalStateException: Var null/null is unbound.

20:44 tomoj: ,(import 'java.util.Date)

20:44 clojurebot: java.util.Date

20:44 tomoj: ,(.getMonth (proxy [Date] [] (getMonth [] (println "foo") 3)))

20:44 clojurebot: java.lang.RuntimeException: java.lang.IllegalStateException: Var null/null is unbound.

20:44 tomoj: huh.

20:44 qed: there we go

20:44 tomoj: well, that works fine for me, prints foo and returns 3

20:44 though that's a pretty strange example :)

20:45 qed: (def print-crazy-date (proxy [Date] [] (toString [] (str (. (java.util.Random) nextInt)))))

20:45 (. print-crazy-date toString)

20:45 err forget a . after Random

20:46 forgot*

20:46 tomoj: crazy indeed

20:46 qed: hehe

20:49 okay this is making more and more sense.. (.start (Thread. (proxy [Runnable] [] (run [] (println "I ran!")))))

20:50 Thread. wants something that is Runnable, so we're giving it what it wants

20:51 tomoj: yep

20:51 hiredman: http://groups.google.com/group/clojure/browse_thread/thread/4303a1a0bc4bdfa5?hl=en <-- good question

20:51 tomoj: though I think agents make all that unnecessary in clojure, luckily

20:51 but maybe if you're interoping with some library that wants Runnables..

20:51 hiredman: clojure Fns are Runnable

20:51 qed: #()

20:52 and Callable

20:52 hiredman: ,(ancestors (class #()))

20:52 clojurebot: #{java.lang.Object clojure.lang.IMeta clojure.lang.AFunction clojure.lang.Obj java.io.Serializable clojure.lang.AFn java.util.concurrent.Callable java.lang.Runnable java.util.Comparator clojure.lang.IFn clojure.lang.Fn :clojure.contrib.generic/any clojure.lang.IObj}

20:52 tomoj: well then I guess all that is unnecessary no matter what

20:52 qed: (.call #(println "foo"))

20:52 ,(.call #(println "foo"))

20:52 clojurebot: foo

20:53 tomoj: (.start (Thread. #(println "foo"))), nifty

20:53 qed: yeah definitely

20:53 hiredman: (future (println "foo"))

20:54 qed: ,(future (println "foo"))

20:54 clojurebot: #<core$future_call$reify__7719@624159: nil>

20:54 qed: ,(seq (future (println "foo")))

20:54 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$future_call$reify__7719

20:54 tomoj: I still have never used future

20:55 qed: ,(future-call #(println "foo"))

20:55 clojurebot: #<core$future_call$reify__7719@1937976: :pending>

20:55 tomoj: ,(let [the-future (future (println "foobar"))] [@the-future @the-future])

20:55 clojurebot: [nil nil]

20:56 tomoj: guess clojurebot doesn't want to print that

20:56 qed: why two calls to @the-future?

20:56 tomoj: but it only prints once :)

20:56 qed: it gives me nil twice

20:57 tomoj: because it still only prints once

20:57 yeah, but only prints once

20:57 (println returns nil)

20:58 qed: (let [the-future (future (str "foo!"))] [@the-future @the-future])

20:58 ,(let [the-future (future (str "foo!"))] [@the-future @the-future])

20:58 clojurebot: ["foo!" "foo!"]

20:59 qed: ,(let [the-future (future (str "foo!"))] [@the-future the-future])

20:59 clojurebot: ["foo!" #<core$future_call$reify__7719@19c1908: "foo!">]

21:02 tomoj: ,(time (let [the-future (future (Thread/sleep 1000) "foo")] [@the-future @the-future @the-future]))

21:02 clojurebot: ["foo" "foo" "foo"]

21:02 "Elapsed time: 1030.109 msecs"

22:11 arohner: I have on the order of 1000 instances of clojure maps that I scan through, looking up values. If I convert that to a deftype that implements IPersistentMap, will things get faster?

22:12 chouser: the clojure maps all have the same keys?

22:12 if so, you should see a substantial speedup

22:15 arohner: chouser: yes, they all have the same keys, and do no assoc/disassoc

22:15 thanks

22:19 chouser: yeah, you should get an inlinable java method call instead of the hashmap algorithm implementation

22:35 arohner: oh, but they don't implement IFN, so I can't do (instance key)

22:36 is that planned/ a good idea?

23:01 cark: arohner : did you try (keyword instance) ?

23:01 arohner: cark: yes, that works

23:01 but my existing code uses (instance keyword) everywhere. I was hoping a deftype that implemented IPersistentMap would be a drop in replacement

23:03 cark: but wouldn't you loose the performance characteristics if this was done this way ?

23:04 ohwell anyways i don't have this version of clojure installed yet =P

23:05 oh i see your post

23:07 _ato: cark: (keyword instance) is actually faster for deftypes

23:08 it's as fast as a java field access

23:08 qed: You know I just realized that all of this channel is logged and my stupidity will forever be cast in stone.l

23:09 _ato: yeah, isn't it great. In 5 years time when you're an almightly Clojure god you can look back and think... "ah... how I have improved!" :-)

23:10 cark: mhh but if you include the IPersistentMap interface in your deftype, doesn't it behave like a struct-map ?

23:10 qed: _ato: haha you are by far the most positive person I've met in here -- I have to say I really appreciate your patience

23:10 kzar: qed: Yea I asked a question in here the other day, then I googled the problem and found what I said in the results..

23:10 qed: kzar: ahahaha

23:11 kzar: "Sweet this guy has the same problem... oh wait"

23:11 qed: To the internet: If you come to IRC and ask _ato, you will learn.

23:12 _ato: cark: hmm, you could well be right. I'm not sure, I haven't played with that enough

23:12 cark: looks like i might have to test it too =)

23:13 qed: And on top of that, _ato is humble, he didn't even take the opportunity to toot his horn.

23:13 God damnit, _ato. What are you made of, man?

23:14 kzar: I bet you are the same person, you just opened up bitchx in a shell and started bigging yourself up

23:14 _ato: hahaha

23:14 qed: hahahaha

23:14 _mst: outed!

23:14 I'm _ato and so's my wife :P

23:14 qed: i am really offended you would think I'd use BitchX

23:14 wtf is it, 1997?

23:15 cark: hey i'm using mirc !

23:15 qed: that's right, get the shame you feel out into the open

23:15 you can only learn from this experience

23:15 _mst: another one for the IRC logs :)

23:16 qed: actually something ive taken to showing my future employers -- or at least mentioning in interviews is that if you google me you will find me, at age 13, on the vuln-dev mailing list

23:17 asking if it is "okay" to extort money from a local ISP for a hole I found in their system

23:17 that shit is never going away

23:18 in fact, they mirrored it...twice

23:18 and vuln-dev takes precedence over my crappy blog, so my 13 year old extortion scheme still reigns supreme in my google results

23:20 * qed sighs

23:23 _ato: heh, if you google my name, which seems to be fairly common you will get: "The father of brainstorming" and "like Jesus, except I'm not dead."

23:25 qed: there's another guy in my state who is a drug addict and got arrested for statutory

23:26 i need to be very clear on my middle initial

23:59 KirinDave1: I'm writing a program and I feel like I'm doing it wrong.

Logging service provided by n01se.net