#clojure log - Sep 15 2009

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

3:07 Fossi: hi

3:08 harblcat: hiya

3:19 LauJensen: Good morning gents

3:23 arbscht_: hello

5:39 ChrisPS: Lisp without parentheses?

5:42 arbscht_: ChrisPS: I don't understand

5:42 ChrisPS: There is an article at news.ycombinator.com

5:42 something called Lispin

5:43 arbscht_: hm, the linked page won't load for me. does it have anything to do with clojure?

5:43 ChrisPS: The site seems to be inaccessible right now, but there is google cache

5:43 clojure is a lisp

5:44 personally, I like the parentheses

5:44 as it makes navigation easier, due to the sexp's

5:48 arbscht_: this looks like every other futile attempt at eliminating parens from a lisp. I'm not sure what more can be said of it

5:49 anyway, other lisps are generally off topic here. they tend to have their own channels :)

5:49 ChrisPS: I don't know, it doesn't really trouble me, sorry for the off-topic

5:50 arbscht_: some folks tried inventing syntax for clojure that reduced the use of parens. iirc, that didn't stick

6:05 Chousuke: I like the second comment on the news item :)

6:06 just change the colour to match the background and the parens disappear :P

6:06 arbscht_: heh

6:19 adityo: good afternoon folks

6:20 how would i write this in clojure new QName("http://apache.org/hello_world_soap_http", "SOAPService");

6:22 got it :)

6:22 jdz: (new QName "http://..." "SOAPService")?

6:34 liwp: or (QName. "http://..." "SOAPServervice")

6:34 if I could spell, that is

6:34 powr-toc: Hey... I need to extend a java class in Clojure and set an instance variable within the super class... How do you do this?

6:35 AWizzArd: Which lib would you use for reading pdf files?

6:37 jdz: do you prefer calling (new SomeClass ...) over (SomeClass. ...)?

6:37 clojurebot: new Class(x) is (Class. x)

6:37 jdz: i usually use new

6:37 but simetimes, when using -> macro, it's convenient to use the dotted syntax

6:38 liwp: IIRC the current favourite / idiomatic style is (Class. x)

6:38 jdz: well, the dot is easy to miss you know

6:38 liwp: yeah, I agree

6:38 I tend to forget to write it when I'm creating objects, i.e. I write (Class x) and then the compiler is angry at me

6:42 ,(String. "foo")

6:42 clojurebot: "foo"

6:48 powr-toc: still can't find any mention of setting protected member variables in super classes you extend with either proxy or gen-class

6:48 does anyone know if this is possible?

6:48 liwp: powr-toc: I haven't used proxy myself do I don't know. I think it's been asked on the mailing list a few times so it might be worth searching through the archives

6:49 also, the was some trick in searching the group... someting like "use the top level group search and pass in your search term and the group name"

6:56 powr-toc: liwp: hmmm still can't find anything :-(

6:57 I would have thought you'd be able to access/set member variables in a binding form or something

7:08 LauJensen: When I do (range 1000), is 0 calculated? Or is the head also lazy ?

7:10 liwp: ,(let [xs (map println (range 10))] 1)

7:10 clojurebot: 1

7:10 liwp: seems to be lazy

7:10 ,(let [xs (map println (range 10))] xs)

7:10 clojurebot: (nil nil nil nil nil nil nil nil nil nil)

7:10 liwp: or then I did something silly...

7:11 ,(doall (let [xs (map println (range 10))] 1))

7:11 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer

7:11 liwp: ,(doall (let [xs (map println (range 10))] xs))

7:11 clojurebot: (nil nil nil nil nil nil nil nil nil nil)

7:11 0 1 2 3 4 5 6 7 8 9

7:12 liwp: ,(let [xs (map println (range 10))] xs 1)

7:12 clojurebot: 1

7:12 liwp: ,(let [xs (map println (range 10))] (doall xs) 1)

7:12 clojurebot: 1

7:12 0 1 2 3 4 5 6 7 8 9

7:13 LauJensen: Thanks, I reached the same conclusion

7:14 liwp: IIRC that was the goal of Rich's fully lazy sequences that happened some time ago

7:14 I.e. in the past head was eager

7:15 but I might be wrong

7:16 LauJensen: No thats exactly how I remembered it also

8:10 weissj: If I have a list of lists, and i want to create a map where the keys are the 1st item in the inner lists, and the values are the inner list, how do i do that in a functional way? ie ((:a 1 2 3) (:b 2 3 4)) -> {:a (:a 1 2 3), :b (:b 2 3 4)}

8:10 dabd: hi, is it possible to use Jersey from clojure?

8:11 I am writing a bunch of RESTful web services using Jersey and I hate Java...

8:11 jdz: if Jersey is Java, then you can use it, yes

8:12 *is in

8:13 fullets: weissj: (into {} (map (fn [x] [(first x) x]) [[:a 1 2 3] [:b 2 3 4]]))

8:13 dabd: Jersey is Java but it relies heavily on annotations and it is not obvious for me how to use it from clojure

8:14 say in Jerse

8:14 weissj: fullets: ah, so simple :) thanks

8:14 dabd: y you define an annotated class and several methods how can you do it from clojure?

8:14 weissj: was trying to figure out how to add 2 items at a time, "into" is what does it

8:15 Fossi: weissj: should be possible with zipmap as well

8:16 don't know which would be nicer

8:16 depends on your usecase i guess

8:17 fullets: Fossi: that's much nicer, imo at least

8:17 (zipmap (map first blah) blah)

8:18 liwp: dabd: AFAIK clojure does not support annotations at the moment, so I think you're out of luck unless there is some other way to plug into Jersey

8:18 Fossi: sounds like jersey and clojure wouldn't be such a nice match

8:19 dabd: liwp: okay that's the impression I got from skimming through the Java Interop section of the manual: that it is not possible to define annotations

8:21 liwp: ,(let [xs [[:a 1 2 3] [:b 4 5 6]]] #(zipmap (map first %) %))

8:21 clojurebot: #<sandbox$eval__2969$fn__2971 sandbox$eval__2969$fn__2971@f67d81>

8:21 liwp: ,(let [xs [[:a 1 2 3] [:b 4 5 6]]] (#(zipmap (map first %) %) xs))

8:21 clojurebot: {:b [:b 4 5 6], :a [:a 1 2 3]}

8:21 liwp: that's not very nice at all actually...

8:22 I was trying to get away from repeating xs in the map and zipmap

8:22 dabd: maybe Java annotations could be implemented through clojure metadata

8:22 liwp: yeah, that would be the way to do it

8:23 in the end you need to change the compiler to add the annoations to the class file and AFAIK people don't really want to touch the compiler ;)

8:31 Mortah: I hear you guys are a friendly bunch, good work :D

8:38 dabd: liwp: an alternative would be to change gen-class so it generates annotated classes and methods

8:39 liwp: dabd: gen-calls doesn't go via the clojure compiler?

8:39 dabd: liwp: yes it does sorry

8:40 liwp: dabd: I'm sure annotations will get added at some point, but so far there hasn't been a lot of demand AFAICT

8:41 Chouser: I don't know much about annotations or rhickey's plans for dealing with them, but gen-class is Clojure's big hammer for cruddy Java interop where named classes are required -- it seems the natural place to add annotation support, if any, and nobody would have to touch the compiler.

8:41 I just rewrote a small .clj file yesterday into a small .java file to support junit 4 annotations.

8:41 As it turns out, Clojure wasn't buying me much there.

8:42 Jomyoot: Is Conjure or Compojure more promising?

8:43 liwp: Chouser: so is new new going to make gen-class obsolete?

8:43 Fossi: Jomyoot: i guess that depends what you are used to

8:43 Jomyoot: I am used to rails

8:43 Chouser: liwp: not at all

8:43 Jomyoot: But I am wondering which one will have more users

8:44 want to use something that will have more active users

8:44 Fossi: Jomyoot: don't know. compojure works nicely for us as kind of a cl-who clone

8:44 Jomyoot: have you looked at conjure?

8:45 Fossi: and even if it doesn't attract a lot of users, it's pretty much feature complete because it's so simple

8:45 dabd: Chouser: if you end up using gen-class to write Java code with lisp syntax you might as well use Java directly

8:45 Chouser: new new (a.k.a. reify) is a native Clojure structure that will fully supported on other hosts (C#, JavaScript, etc.)

8:46 in other words, not primarily a Java interop structure. gen-class and proxy are meant more for interop with Java libs that have unfortunate designs.

8:46 liwp: Chouser: ok

8:48 Chouser: is this correct, new new allow you to extend an existing class whereas gen-class is used to define a new class which optionally extends an existing class?

8:51 Chouser: liwp: yes, that's one of the differences. There are several.

8:51 back in a minute.

8:52 Chousuke: liwp: I think everyone would prefer if you only implemented interfaces rather than extending existing classes (unless abstract) :)

8:56 liwp: Chousuke: if you don't want me to extend your classes / methods, you should declare them as final :)

8:57 weissj: If i have a list of items and i want a list with the nth item removed, how do i do that

8:57 do i have to use filter (or remove)?

9:01 Chousuke: liwp: the problem is even having classes that others might want to extend ;)

9:01 liwp: Chousuke: you mean in Clojure or in OO languages?

9:02 Chousuke: I suppose it depends a bit on the language

9:03 Chouser: weissj: neither vectors nor lists support efficiently removing an item in the middle, so yes you'll end up having to an O(n) walk

9:04 weissj: Chouser: ok thanks

9:04 Chouser: weissj: probably most efficient to use a vector, two subvecs, and conj them.

9:06 weissj: Chouser: yeah, all my vectors are 4 items long, and i just want to remove the 2nd item, so i can conj the first with a call to drop

9:06 Chouser: oh! actually, destructuring might be nice if they're that small.

9:06 (let [[a _ b c] v] [a b c])

9:07 weissj: Chouser: ok, i will try that, thanks!

9:08 liwp: Chouser: have you seen Guy Steele's talk at ICFP'09? http://research.sun.com/projects/plrg/Publications/ICFPAugust2009Steele.pdf

9:09 he talks about concurrency friendly data structures, i.e. representing things like lists as trees so that you can parallelise operations on them

9:09 he introduces first conc lists (concatenation lists) and then talks about finger trees later on

9:10 Chouser: yes, I've looked through that. Clojure's vectors are actually trees internally

9:10 liwp: yep

9:10 I was just wondering if you can do all of that with just finger trees, i.e. if you have finger trees is there any use in conc lists

9:10 Chouser: so rhickey wrote some parallel ops to work on the vectors.

9:10 liwp: ahh, I haven't see those

9:11 is that what's in clojure.parallel?

9:11 Chouser: I never use them, so I don't remember. looking now.

9:12 I think clojure.parallel is still using the forkjoin.ParallelArray, so that's not it.

9:12 liwp: ok

9:12 the docs talk about creating a parallel array from a collection, so it must be something else then the standard vector

9:13 Chouser: as, there's a 'par' branch

9:13 "added clojure.par ns with pvmap and pvreduce"

9:13 liwp: cool

9:14 Chouser: so those work on regular clojure vectors, leveraging the tree structure.

9:15 liwp: I guess the 32 object fanout helps in avoiding splitting up the work too thinly

9:15 Chouser: yep.

9:16 as for finger trees, I guess I don't know the theory well enough yet. They should be able to useful for doing all the things described in those slides.

9:16 concat is efficient, etc.

9:17 liwp: that's what I'd expect, but the slides did not really state it explicitly and I don't know finger trees well enough to work it out for myself (the paper is at home on the TODO pile)

9:17 Chouser: cached monoids are used heavily in finger trees

9:18 liwp: there's a nice blog post about finger trees in haskell which explains with a few examples how the functionality changes when the monoid is changed

9:18 really cool

9:19 Chouser: my finger trees support Clojure's seq abstraction (ISeq) directly. That is, calling 'rest' on a finger tree gives you a new finger tree, amortized O(1) time.

9:19 liwp: http://apfelmus.nfshost.com/monoid-fingertree.html

9:21 Chouser: looks like there are slightly different performance profiles between finger trees and conc lists. Like first is O(1) for ft, appears to be avg O(log n) for conc, vs. concat O(log n) for ft and O(1) for conc

9:22 liwp: heh, now that you mention it, it seems obvious :)

9:23 Chouser: really? nothing about ft's have been obvious to me. :-P thought I think I'm starting to get a sense of how they really work now.

9:23 liwp: and rest is O(log n) for conc as well, right? Only concat is O(1)

9:24 Chouser: I think so, though in practice I'm not sure how it will always turn out.

9:24 liwp: Chouser: the conc list bit was the obvious bit, i.e. concat is O(1) and first is O(log n)

9:25 Chouser: That is, ft rest is slightly worse that O(1) and it uses delay to make it as good as possible. conc rest speed will depend on how the list was built I think (depth of left path may be short)

9:25 liwp: Chouser: I guess if you have an unbalanced conc list, then you might effectiely have a linked list and rest would be O(1) again

9:25 Chouser: right

9:25 liwp: Steele conveniently left out the balancing of conc lists from the slides

9:25 Chouser: heh

9:26 liwp: what do you do with fingertrees? do you need to rebalance?

9:26 Chouser: yeah, that's a nice feature of ft -- no rebalancing

9:26 liwp: ok

9:26 does that lead to pathological cases?

9:27 Chouser: I don't know. I wouldn't be surprised if the worst cases were O(log n) when you were hoping for amoritized O(1). But maybe it's not even that bad, not sure.

9:27 ankou: does clojure not even show line numbers or file at syntaxerrors like "unmatched parentheses" or is it a problem with slime?

9:28 liwp: ankou: I think it's a slime issue - I've only ever used slime myself

9:29 I also use paredit mode so it's hard to miss parens

9:30 ankou: I get an Message of an Exception with a backtrace of the reader but no line number of the error itself is included in the exceptionmessage

9:30 liwp: ankou: yep, that's quite common with clojure error messages

9:30 ankou: really annoying :\

9:30 liwp: ankou: have a look at the stack trace, if that's available, usually there's a clue there

9:31 i.e. one or more stack frames mention your source file and line number

9:31 Chouser: I get: java.lang.Exception: Unmatched delimiter: ) (<file name>:<line number))

9:31 liwp: slime won't even inject the code with a missing paren for me...

9:32 ahh, never mind - my test app killed my JVM...

9:32 it's very annoying when people bind the Swing close app button to System/exit...

9:34 ankou: Chouser: the same thing just without the extra information. I could find the file with the help of the stack trace however loading this file directly didn't give me more information

9:51 liwp: do people use a user.clj file in their classpath?

9:52 and if so, what's in it?

9:53 Chouser: I don't. My startup script puts -i $HOME/.clojure/repl-init.clj on the java command line

9:54 lisppaste8: Chouser pasted "repl-init.clj" at http://paste.lisp.org/display/87096

9:54 liwp: Chouser: do you use slime?

9:54 Chouser: no

9:54 liwp: are you using the raw repl or one of the IDE plugins?

9:55 Chouser: rlwrap + repl in a terminal

10:03 weissj: ok i should know this but how to turn a seq of strings into a concat'd string

10:03 (str (interpose "," '["a" "b"]))

10:03 "clojure.lang.LazySeq@1e636"

10:04 Chouser: apply

10:04 weissj: Chouser thx

10:53 Fossi: weissj: for that case there's str-join as well

10:53 in contrib

10:54 Chouser: also contrib str-utils2/join

11:08 weissj: Fossi: yeah i think that was the one i was thinking of thanks

11:09 avital: what is used here for pasting code?

11:10 crios: http://paste.lisp.org

11:11 avital: ok cool so i was trying to use map on a hash map and since hash maps are collections as pairs the return value is not a hash map but rather a sequence of pairs

11:11 so i wrote this instead

11:11 http://paste.lisp.org/display/87103

11:11 is there any better way to map a hashmap?

11:12 in my implementation map-map receives a function and a map, the function gets two arguments (key and value) and returns a sequence of length 2 containing the new key and value

11:12 Fossi: (map (fn [k v] (println k v)) {:a 1 :b 2})

11:12 ,(map (fn [k v] (println k v)) {:a 1 :b 2})

11:12 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--2982$fn

11:13 Fossi: ups

11:13 ,(map (fn [[k v]] (println k v)) {:a 1 :b 2})

11:13 clojurebot: (nil nil)

11:13 Chouser: ,(into {} (for [[k v] {1 1, 2 2}] [(* 2 k) (* 3 v)]))

11:13 clojurebot: {4 6, 2 3}

11:13 avital: that might work but if you actually want a return value from map it won't end up a hash map.

11:13 oh what

11:13 wait

11:13 what

11:13 what is into?!

11:13 Fossi: yeah, into then

11:15 Chouser: (into target source) is (reduce conj target source), only faster

11:16 avital: wow amazing

11:16 ok

11:16 thanks

11:17 Chouser: ankou: you're not the first to write map-map, but with into, for, zipmap, etc. I'm not sure people need map-map.

11:18 avital: Chouser: Not sure what you mean by "people need". If anyone feels that it makes his/her code simpler, more intuitive, etc. let them do it.

11:18 Chouser: oh sorry, mis-directed post there.

11:19 avital: My intuition says: If you can run map on maps, it should return a map. If not, then either it needs to be replaced or map-map should be part of clojure

11:21 Chouser: 'map' is always consumes a seq lazily, returning a lazy seq. Having it return a map or vector would be a poor fit, I think -- that's exactly what 'into' is for, pouring a (possibly lazy) seq into a strict collection.

11:22 as for a separate map-map: http://google.com/search?q=clojure+"defn+map-map"

11:23 hm, some of those "map-map"s do different things.

11:24 Jomyoot: How can you quickly convert from Java HashMap to Clojure Hash?

11:25 Chouser: Jomyoot: you need it to actually be persistent?

11:25 Jomyoot: not really

11:25 either way is fine

11:25 Chouser: Jomyoot: clojure maps implement java map, so you may be able to just use it directly

11:26 ,,(into {} (java.util.HashMap. {:a 1, :b 2, :c 3}))

11:26 clojurebot: {:a 1, :b 2, :c 3}

11:26 Jomyoot: cool

11:26 Chouser: there's a clojure map to a java map and back again. :-)

11:27 Jomyoot: What about a templated HashMap

11:27 Chouser: Jomyoot: doesn't matter

11:28 Java generics are just a java compile-time check -- after the .java's been compiled, the collections don't care about their template params anymore

11:52 lisppaste8: raphinou pasted "untitled" at http://paste.lisp.org/display/87104

11:53 raphinou_: here's a little paste about a question about the (defn my-func [args & more] ...) way of defining a function and handling the more var

11:54 if second arg passed is a list, i would like more to be equal to that list. And I'm not sure what's the best way to do that...

11:54 Chousuke: I don't think that's a good idea :/

11:54 anyone who wants the second argument to be a list can use apply anyway

11:55 I guess you could overload it for two arguments to check whether the second argument is a list or not.

11:56 eg (fn foo ([x y] (if (seq? y) (concat x y) (concat x [y]))) ([x & more] (concat l more)))

11:57 oops

11:57 the l should of course be x :P

11:58 or hmm

11:58 Chouser: ,(fn foo ([x y]) ([x & xs]))

11:58 clojurebot: java.lang.Exception: Can't have fixed arity function with more params than variadic function

11:58 Chousuke: oh damn

11:58 (defn foo [x & more] (concat x (flatten more)))

11:58 raphinou_: chousuke: I agree it's not a good approach, but it's a question that popped up when wrtiting a test for such a function. To save time I put the more to be passed to the function, which is also the expected result , in a "variable" I could reuse

11:59 Chouser: don't use 'more', it's a builtin

12:00 raphinou_: Chousuke: ha, I didn't know that!

12:01 Chousuke: Chouser: wait, more is?

12:01 (doc more=

12:01 clojurebot: EOF while reading

12:01 Chousuke: (doc more)

12:01 clojurebot: No entiendo

12:01 Chouser: Chousuke: oh, nope. sorry. that's the name of the method 'rest' calls.

12:01 Chousuke: heh. confusing :P

12:02 Chouser: yeah. there are a couple interface methods that kept early names.

12:02 'conj' calls 'foo.cons()' and 'rest' calls 'foo.more()'

12:03 * rhickey off to Microsoft

12:03 raphinou_: ok!

12:03 Chouser: rhickey: good luck!

12:03 rhickey: thanks!

12:04 raphinou_: off to microsoft? for clojure?

12:04 Chouser: yeah, he's speaking

12:05 raphinou_: he, cool

12:06 Chouser: raphinou_: anyway, you're sure you can't just use apply? it's the correct solution, and usually convenient.

12:06 raphinou_: Chousuke: looking further at it

12:07 Chousuke: actually, first trying to get the test pass with the "& others" arguments ;)

12:07 Sir_Diddymus: Hi all... I've extended a Java class (with :gen-class and :extends) and all is fine and works like expected. Now I need to call a protected final method of the superclass (from inside my extended class) - is there really no way do this? Or did I just not find it how to achieve this?

12:08 Chouser: raphinou_: otherwise, I don't think you can do better than (defn foo [x & xs] (let [xs (if (coll? (first xs)) (first xs) xs)] [x xs]))

12:09 Sir_Diddymus: did you look at :exposes-methods ?

12:11 Sir_Diddymus: Chouser: yup... but maybe I didn't use it correctly. And I thought I can only access overridden methods of the superclass that way? At least that is what the API docs specify...

12:12 Chouser: and well, since the protected method is final, no override possible... :\

12:13 Chouser: I think that's a red herring. ignore the stated purpose and look at what it does.

12:13 I *think* it'll work for you.

12:14 Sir_Diddymus: hmm... k... than I probably just did something wrong. I thought I tried that...

12:14 Chouser: :exposes-methods creates new public methods that can call protected methods of the superclass

12:14 yeah, gen-class is a bit tricky to use right. :-/

12:15 Sir_Diddymus: yup. probably wrong syntax or something.

12:19 Chousuke: aa

12:19 oops.

12:24 Sir_Diddymus: nope, still doesn't work. :(

12:24 Chouser: lisppaste8: url?

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

12:24 Chouser: Sir_Diddymus: shows us what you've tried?

12:25 Sir_Diddymus: k... sec...

12:30 lisppaste8: Sir_Diddymus pasted "calling a protected final method?" at http://paste.lisp.org/display/87106

12:32 lowlycoder: is there any reason to use clojure from git instead of the latest stable?

12:32 Chouser: Sir_Diddymus: what error do you get?

12:33 Sir_Diddymus: This is the signature of the method: protected final void beginInsertRows(com.trolltech.qt.core.QModelIndex parent, int first, int last)

12:33 This is the error:

12:34 java.lang.IllegalArgumentException: No matching method found: beginInsertRowsSuper for class name.space.XStoreListModel

12:36 Chouser: Sir_Diddymus: do you have repl-utils from contrib?

12:36 Sir_Diddymus: Somehow I can't believe that it shouldn't be possible. Would be a real bummer though, if it really didn't work.

12:36 yeah, i think so...

12:36 Chouser: try (show name.space.XStoreListModel)

12:36 Sir_Diddymus: after loading the class?

12:37 Chouser: sure, or just have compiling it.

12:38 that should list all the defined methods.

12:39 and should allow you to see if beginInsertRowsSuper is generated at all, or if it's the arg types causing problems.

12:42 stuartsierra: ~seen dysinger

12:42 clojurebot: dysinger was last seen quiting IRC, 790 minutes ago

12:42 Sir_Diddymus: nope... no begin* method found.

12:43 ok, compiled it again to be sure, but not listed.

12:46 I thought that I read somewhere that the combination "protected final" is the problem. But that would practically mean, that frameworks like Qt aren't (fully) usable.

12:55 icylisper: how to get a list of all functions defined in a given namespace ?

12:57 tmountain: icylisper: ns-map ?

12:58 icylisper: ah thanks. will check

12:58 tmountain: np

13:00 icylisper: um-, dont see how i can filter the defns.

13:03 tmountain: looks like ns-interns is actually better for what you want

13:03 icylisper: or maybe ns-publics

13:03 tmountain: user=> (ns foo)

13:03 icylisper: thanks :)

13:04 tmountain: foo=> (defn sum [a b] (+ a b))

13:04 user=> (ns-interns 'foo)

13:04 {sum #'foo/sum}

13:04 np, I'm figuring this out as I go, so I'm wrong a lot ;-)

13:04 Chousuke: icylisper: (filter (fn [[k v]] (fn? v)) (ns-interns 'whatever))

13:04 tmountain: yeah, that looks good

13:04 Chousuke: oh but wait

13:04 it's vars

13:05 you need (deref v)

13:05 icylisper: ah.

13:05 Chousuke: (or @v :P)

13:05 icylisper: cool. thanks Chousuke.

14:02 crios: clojurebot: logs?

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

14:17 crios: sir_diddymus, your problem can be related to the ticket http://www.assembla.com/spaces/clojure/tickets/126-abstract-superclass-with-non-public-accessibility ?

14:18 Sir_Diddymus: crios: thanks, taking a look...

14:20 crios: check this also: http://groups.google.com/group/clojure/browse_thread/thread/d1fbdb7450b46dee/b5539e4a21c411c6?pli=1

14:20 unluckly I'm too much newbe on Clojure , to be of any help to you :)

14:24 Sir_Diddymus: hm... I'm not really sure if both of them apply, since I have a derived class and inside of that, I'm trying to call a protected final method of the superclass. I can call public methods from the abstract superclass just fine.

14:24 Chouser: that second link is solved with :post-init

14:25 the first I don't think applies

14:25 Sir_Diddymus: Well, to be correct, the public method I can call are in the abstract base class, as well as the superclass...

14:25 Chouser: I've got a stand-alone example that reproduces the problem.

14:25 Sir_Diddymus: s/method/methods/

14:28 crios_: this patch? http://code.google.com/p/clojure/issues/detail?id=45

14:28 Chouser: maybe something's wrong with my .java

14:28 oh. duh...

14:28 crios_: yes

14:29 crios_: 'this' and 'super' Java keywords cannot be used into Clojure interop. code?

14:30 Chouser: 'this' and 'super' are not special words in clojure (expcept for 'this' inside 'proxy' forms)

14:31 Sir_Diddymus: crios_: when extending a class, the first parameter in the methods (overridden as well as :exposed) get set to "this", you can call it however you want, as far as I know...

14:31 Chouser: Sir_Diddymus: maybe I've just misunderstood gen-class and mislead you. Maybe exposes-methods just doesn't work on protected methods.

14:32 Sir_Diddymus: Chouser: yeah, that's what a gathered from reading the API docs. And by trying. ;)

14:33 lisppaste8: Chouser annotated #87106 ":exposes-methods not for protected?" at http://paste.lisp.org/display/87106#1

14:33 Chouser: time to check the code.

14:34 if not past time :-/

14:40 crios: if i well remember, protected methods can be accessed just by subclasses. How clojure "proxy" the classes? by delegation?

14:41 i mean, when you compile myns.pityme you get a its proxied subclass?

14:41 or a clojure object which delegates to myns.pityme?

14:42 Chouser: gen-class produces a subclass with a bunch of methods. Each method listed in :methods or defined as public by a superclass, you get a little method that delegates to a defn in the given namespace.

14:43 but you can use :init, :post-init, :exposes, and :exposes-methods to generate more methods that don't deletgate to defns in the same way, but hook other code directly into the generated class.

14:43 crios: ok

14:44 Chouser: ok, from the code, gen-class only considers for :expose-methods methods that are "non-private"

14:46 it specifically excludes methods that are named "finalize" or are final.

14:47 (or a few other things)

14:47 I wonder if that clause for excluding final methods really makes sense for :exposes-methods.

14:48 crios: finalize?

14:49 maybe when clojure exposes that methods with expose-methods, would give you a chance to "override" them?

14:50 a sort of overriding, i mean

14:50 Chouser: well that's the thing -- you're not overriding a final method, just providing a way to call it.

14:51 this list of non-private methods is used for a few other things -- I wonder if 'final' is good to exclude from those, but not :expose-methods

14:53 oh, it's a Range. Not sure what that is.

14:54 sorry, wrong window.

15:11 Sir_Diddymus: so :exposes-methods is definitely not the way to go. But shouldn't I be able to just use the method, since protected methods are accessible to subclasses in Java world? Hm...

15:12 Chouser: your clojure fn is not *in* the subclass, it's called by the subclass.

15:12 with reify you could call it directly

15:13 I think your best bet for now would be to write a subclass in .java that has a public method that calls the protected one, and then subclass that (using either proxy or gen-class)

15:14 and/or bring it up on the group and see if others have solved this problem. I wouldn't be surprised if this leads to a tweak of :exposes-methods

15:15 no matter how much rhickey hates protected methods, they won't just go away. :-)

15:16 Sir_Diddymus: ugh... not pretty. ;) Yeah, that's what I wondered. I mean ok, it's Java and not all to lispy, but then again this should crop up more than once - especially with GUI frameworks.

15:17 already wrote a message to the group...

15:18 anyway, thanks for the help...

16:18 LauJensen: Gentlemen, I hope you enjoy the read: http://www.dzone.com/links/scala_vs_clojure_lets_get_down_to_business.html

16:22 triyo: LauJensen: link to the actual post doesn't seem to work

16:23 says "Looks like you have a problem here sir/madam...."

16:23 LauJensen: argh

16:24 Chousuke: why don't you just link directly to the blog post? :P

16:24 strlen: http://bestinclass.wordpress.com/

16:25 that's where the post is

16:26 ugh that blog post is wrong

16:26 scala will do tail recursion

16:26 not TCO

16:26 LauJensen: strlen, try it, will bork at 3600! just like Clojure

16:26 strlen: and that isn't written in a way that it will do tail recursion

16:27 LauJensen: But anyway, the DZone link works, you just need a hard refresh

16:27 strlen: LauJensen: it can do a true tail recursion

16:27 Chouser: ah, I didn't catch that!

16:27 * Chouser is ashamed

16:27 strlen: the way that code is written in scala though -- on that page

16:27 isn't tail recursion

16:27 one sec

16:28 clojure will do tail recursion using 'recur'

16:28 Chouser: strlen: you're right that TCO wouldn't fix that algorithm.

16:28 strlen: now you can't do true TCO

16:28 as in

16:28 it will only do tail *RECURSION*

16:28 not tail call optimization which is different as it works across functions

16:30 LauJensen: Oh okay, I didn't make that distinction

16:30 strlen: but both scala and clojure do tail recursion. clojure does it using 'recur' as clojure is dynamically typed (and there's no invokedynamic yet)

16:30 Chousuke: LauJensen: technically, Clojure doesn't have lazy evaluation. it only has lazy seqs.

16:31 function parameters and such are still strict

16:31 LauJensen: Chousuke: I know, #scala is going on the same thing right now

16:31 strlen: you can also do future objects in scala for lazy evals

16:31 both languages are fun that's what matters :-)

16:31 Chouser: the examples both demo the correct transformation from non-tail to tail recursive structure

16:32 strlen: http://www.bluishcoder.co.nz/2006/07/scala-futures-and-lazy-evaluation.html

16:32 woiw that's ancient blog post

16:32 http://www.scala-lang.org/node/49

16:33 Chouser: 2006! Clojure didn't even exist

16:38 * drewr shudders

16:56 hiredman: it would be nice if range worked on characters

16:57 ,(map char (range (int \a) (int \e)))

16:57 clojurebot: (\a \b \c \d)

16:58 Chouser: ,(+ \a 1)

16:58 clojurebot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number

16:59 Chouser: (range \a \e \u0001) ?

17:00 Chousuke: hmm.

17:00 Chouser: :-)

17:00 hiredman: sure

17:00 I can understand (+ \a 1) not being valid, but (range \a \z) would be nice

17:01 Chousuke: ,(map char (range (int \か) (int \さ))); let's see what happens with non-ascii :P

17:01 clojurebot: (\か \が \き \ぎ \く \ぐ \け \げ \こ \ご)

17:01 Chousuke: ooh, it works.

17:02 though usually you wouldn't want the ones with the dots if you did that :)

17:02 Chouser: well, range calls + internally -- fix + and I think range would Just Work

17:02 Chousuke: it's kind of like getting aAbBcCdD...

17:02 hiredman: Chouser: or just split the code path

17:04 (if (instance? x Character) (make-int-and-call-range x) ...)

17:04 or something

17:18 LauJensen: Guys, feel free to drop a vote, I get the sense #scala isn't exactly going to help :) http://www.dzone.com/links/scala_vs_clojure_lets_get_down_to_business.html

17:23 Chouser: rhickey: landed?

17:27 LauJensen: Its been a good night on #scala

17:27 (23:27:34) mapreduce: LauJensen: I await part 3, Chuck Norris vs. Martin Odersky.

17:27 (23:28:06) LauJensen: "Chuck Norris doesn't do push ups - Rich Hickey won't let him"

17:27 I'll leave you with that, good night :)

17:47 dthomas: Before I write a quick little "walk nested maps [produced from JSON]" function, is there something already written that I should be using? I actually just need to get a sequence of map entries that match a given predicate, traversing the whole nest of maps.

17:48 Chousuke: does it have to preserve the structure?

17:48 if not, you could filter and flatten.

17:48 dthomas: I think no, not interested in the location of the matches within the tree.

17:49 Ah, flatten.

17:49 Chousuke: (doc flatten)

17:49 clojurebot: "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil."

17:49 Chousuke: hm

17:50 no namespace still ;/

17:50 c.c.seq-utils? :/

17:52 dthomas: Yeah, found it. (flatten some-map) => () isn't what I was expecting.

17:53 (Oh, (indexed), I wanted that the other day. Good to know it's there.)

17:57 Chousuke: hm

17:57 ,(flatten {:foo :bar :zonk {:a :b}})

17:57 clojurebot: ()

17:58 Chousuke: huh.

17:58 that has to be a bug :P

17:58 hiredman: Chousuke: if the namespace has been use'ed in the sandbox namespace, then you don't get namespace information

17:58 Chousuke: ,(flatten (seq {:foo :bar :zonk {:a :b}}))

17:58 clojurebot: (:foo :bar :zonk {:a :b})

17:59 hiredman: ~def flatten

17:59 Chousuke: dthomas: looks like you'll need your own function. take a look at tree-seq though.

17:59 hiredman: ,(doc sequential?)

17:59 clojurebot: "([coll]); Returns true if coll implements Sequential"

17:59 hiredman: ,(sequential? {})

17:59 clojurebot: false

17:59 Chousuke: ,(doc tree-seq)

17:59 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

17:59 hiredman: ^-

18:00 Chousuke: ,(tree-seq (comp map? val) seq {:foo :bar :foo {:a :b}})

18:00 clojurebot: java.lang.ClassCastException

18:00 Chousuke: oops.

18:01 ,(tree-seq (comp val map?) seq {:foo :bar :zonk {:a :b}})

18:01 clojurebot: java.lang.ClassCastException

18:01 dthomas: tree-seq, that looks promising.

18:01 Chousuke: ... okay I fail

18:02 mabes: can I coerce a vector into a a list of arguments? meaning.. if I have (def a [1 2 3]) and I want to call < on a so it would be (< 1 2 3), is that possible?

18:02 Chousuke: (apply < a)

18:02 mabes: Chouser: cool, thakns. just playing/learning clojure now- so sorry for the probably simple question :)

18:04 Chousuke: simple questions are fine

18:04 easy to answer so I can look like a wise sage or something :P

18:09 lisppaste8: beutdeuce pasted "Efficiency question" at http://paste.lisp.org/display/87136

18:18 Chousuke: beutdeuce: with reduce, * is a function call every time and you have a lazy seq too. in the explicit loop, there is no laziness involved and * can be inlined.

18:18 beutdeuce: is this git master or 1.0.0?

18:19 beutdeuce: 1.0 i believe

18:19 not the 1.1.0 snapshot

18:19 there are changes?

18:19 *significant* changes?

18:20 Chousuke: yes.

18:20 :)

18:20 beutdeuce: :) for example?

18:21 Chousuke: some performance improvements for reduce et al via chunked seqs, transients, hmm... reify coming soon I guess.

18:21 enough that I have lost track of it all :P

18:22 beutdeuce: sounds exciting

18:22 and it has been 2 years

18:22 hiredman: uh

18:23 nope

18:23 Chousuke: 2 years since what?

18:23 hiredman: 1.0 was months ago (5?)

18:23 Chousuke: oh and then there's the JDK forkjoin library thing which seemed rather impressive.

18:23 JDK7*

18:23 beutdeuce: sweet! and ya, i forgot about 1.0

18:24 is jdk 7 even mainstream?

18:24 Chousuke: but, help. my emacs is no longer treating my option key as alt :(

18:24 beutdeuce: nope, but the library is already available as a separate download for 1.6 too :)

18:26 beutdeuce: i should try that out. I read in an article somewhere (i forgot) about the vm becoming very efficient and overpowering c++ in various different areas it used to drag behind in.

18:27 is that sun java 7? or openjdk

18:30 ,(reduce (fn [n acc] (println (* acc n))) (range 5))

18:30 clojurebot: java.lang.NullPointerException

18:30 beutdeuce: ?

18:31 Chousuke: beutdeuce: I just tested

18:31 beutdeuce: on my computer the reduce version is actually faster.

18:32 hiredman: beutdeuce: println returns nil

18:32 Chousuke: but your loop is not optimised so that's not so surprising :)

18:32 beutdeuce: oh right

18:32 how much faster?

18:32 Chousuke: not much

18:32 beutdeuce: faster than tail-recursion in that example?

18:33 Chousuke: about 30-40ms on average

18:33 but hm, let me see if I can optimise the loop and see what that does.

18:33 hahah

18:34 I got an integer overflow

18:34 figures

18:34 beutdeuce: :P

18:34 Chousuke: looks like there's no getting around using bignums

18:34 so reduce wins :P

18:35 beutdeuce: Reduce | Recur || 1 | 0

18:35 say, anyone know how to get rid of that annoying emacs auto-paranthesis match?

18:36 Chousuke: auto-parenthesis?

18:36 annoying? :)

18:36 beutdeuce: like, i cant close paranthesis until i delete whats between them

18:36 it doesnt let me

18:36 Chousuke: you don't want to get rid of that

18:36 trust me

18:37 just learn to use paredit instead

18:37 beutdeuce: paredit?

18:37 Chousuke: it's what the thing is called

18:37 beutdeuce: k

18:37 well

18:37 its just that it glitched, so i had an open paran, but i couldnt delete it cause it said it was unmatched, i didnt see where the closing one was

18:37 Chousuke: it's "structured editing". it doesn't let you write s-exps that are "broken"

18:38 beutdeuce: better now, restarted emacs

18:38 Chousuke: if you really have an unmatched paren, do C-q )

18:38 (C-q is "quote")

18:38 beutdeuce: k, thnx

18:38 Chousuke: anyway, paredit can do much more than just match your parens.

18:39 you can actually move around entire s-expressions.

18:39 without fear of breaking them.

18:39 beutdeuce: hmm, cool

18:40 Chousuke: the most common operations are barf and slurp: ctrl-leftarrow/rightarrow

18:40 and ctrl-k kills (cuts) a s-expression instead of a line

18:40 tomoj: arrows? blasphemy :P

18:40 Chousuke: tomoj: the real combo is something weird.

18:41 arrows are easier.

18:41 tomoj: C-(, C-), C-{, C-}

18:42 I don't like having to reach all the way over to the arrow keys :/

18:42 Chousuke: C-{ is impossible on my layout and C-( is nothing nice either.

18:42 tomoj: yeah

18:42 programmer's dvorak here so those are really easy :)

18:42 mDuff: tomoj, ...hmm; how is that to learn coming from traditional dvorak?

18:43 tomoj: mDuff: not too bad

18:43 I'm still not used to the numbers

18:43 beutdeuce: does println do *out* ?

18:43 Chousuke: beutdeuce: http://www.aaronfeng.com/articles/2008/03/23/barf-and-slurp-with-paredit

18:44 beutdeuce: nice

18:44 Chousuke: I don't think I'll be able to edit lisp code without that anymore ;(

18:45 tomoj: mDuff: I can't imagine at this point doing lisp (especially clojure, with its []s and {}s) with normal dvorak now

18:58 hlship: Question about getting patches, to clojure-contrib, accepted.

18:58 I attached a patch to ticket #24 about three weeks ago

18:59 I don't have commit access

18:59 who should I assign it to, to get the patch committed?

18:59 Or is there a special status?

18:59 http://www.assembla.com/spaces/clojure-contrib/tickets/24

19:47 emacsen: Hey. I have a question. This page: http://www.geotools.org/quickstart.html#quickstart says that I need to set up a maven project for java inclusion. How would that work with a Clojure program?

19:56 interferon: is there a clojure function that might be called "group-by" which takes a sequence and returns a map that groups the elements of the sequence by a function?

19:56 hlship: sorry .. had to leave; any answer to my prior question about patches?

19:58 Potplant: interferon: sure is. clojure.contrib.seq-utils/group-by

19:59 _mst: ,(clojure.contrib.seq-utils/group-by #(mod % 5) (range 20))

19:59 clojurebot: {0 [0 5 10 15], 1 [1 6 11 16], 2 [2 7 12 17], 3 [3 8 13 18], 4 [4 9 14 19]}

20:02 interferon: great!

20:02 thanks

20:03 and congratulations on parsing my mess of a sentence :)

23:53 danlarkin: wtb rich hickey :)

Logging service provided by n01se.net