#clojure log - Oct 19 2008

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

0:00 bitbckt: ah, you're right

0:00 asbjxrn: (filter #(< % 10) [ 1 11 2 14])

0:00 bitbckt: the take is "taking" one ahead

0:00 but... not returning?

0:00 as the filter is not returning anything past that boundary?

0:01 asbjxrn: It keeps searching the sequence for the next number smaller than 10.

0:01 Which it will never find as the sequence is steadily increasing.

0:02 bitbckt: ah, I see.

0:03 duck1123: oh well, I've solved the problem, and now I've learned something :)

0:04 bitbckt: duck1123: it's a good day.

0:12 AWizzArd: why does (. System.out.println "Hallo") produce an error?

0:17 Chouser: try: (.println System/out "Hallo")

0:19 AWizzArd: ic

0:21 is there already some kind of absolute value function in clj?

0:22 Chouser: (Math/abs x)

0:22 so no, but it's easy to get to Java's.

0:22 AWizzArd: great

0:22 why is it (.println System/out ...) but not (.abs Math)?

0:23 Chouser: static method vs. instance method

0:23 out is a static field of the System class

0:23 abs is a static method of the Math class. Thus System/out and Math/abs

0:24 println is an instance method of the System/out object, thus (.println System/out)

0:25 rottcodd_: but it's still possible to do (. Math (abs -1)), is that bad style?

0:25 Chouser: that's an older style. I think it's being phased out, but I'm not sure.

0:26 Also works: (. Math abs -10)

0:26 AWizzArd: so which is the newer one?

0:27 but (System/out/println "moo") ==> error

0:27 Chouser: newer: (Class/meth arg) for static and (.meth obj arg) for instance

0:27 AWizzArd: ok, thanks

0:27 Chouser: right, println is an instance method, so don't try to use /

0:27 asbjxrn: I liked the (. style.

0:28 Oh, well.

0:28 AWizzArd: it's still there it seems

0:28 asbjxrn: But if it's phased out...

0:30 I kinda agree that too many ways to do stuff is bad, easier on the reader if there is one common way of doing things.

0:35 AWizzArd: currently the reader does not allow things like: (defn 3-or-more [guys] ...)

0:35 symbols may not begin with a number

0:36 also dots in symbols cause problems... one couldn't name range "from..to"

0:37 (defn from..to [f t] (range f t))

0:46 n8 n8

1:09 duck1123: I prefer the (. Class method) style

1:14 anyn: how do I do something like this in clojure: Log _log = new Log(ATalk.class);

1:14 ?

1:14 where ATalk.class is inside of the class definition for ATalk?

1:17 Chouser: (defn log (Log. ATalk)) perhaps?

1:18 ATalk.class in Java is to get the Class instance representing ATalk, right?

1:19 anyn: right, but since most of the app logic that I'm recreating (for an exercise to learn) is inside of the class ATalk, I'm getting rid of the class and just doing all it's logic in the root namespace.. should I try to put it all in a function somehow?

1:21 Chouser: probably not -- sound like you're on the right track.

1:23 sorry, that should be "def" not "defn" above.

1:24 I don't suppose anyone knows of a way to set a public field on a Java instance?

1:24 oh, (set!) does it. hm...

1:25 anyn: I suppose I could, for each method that the java app uses the logging facility, do a (let [log (Log. thisFunctionName)] and do a new (.warn log "stuff happend") each time

1:27 Chouser: you want a new instance of Log for each clojure fn?

1:28 anyn: I suppose it'd have a slightly different effect. each fn would probably spit out a different log file (if I understand this logging facility correctly)

1:28 Whereas, I guess this java class spits out one log file for the whole class

1:29 no biggie, I'll probably just forgo the logging all together and print to the console

1:29 Chouser: I suppose you're a lisper moreso than a java person?

1:30 Chouser: no, more C++ and ruby.

1:30 so I've had lots to learn. :-)

1:32 gotta go -- good luck!

1:32 anyn: gah

1:32 ok, later

1:38 toanyone: So I'm trying to translate a java class to a clojure program. When a class has a bunch of class variables, would it be wise to put those variables in a map like {:myFile nil :myContact nil :myBirthday nil}. Then, have functions like (def doStuff [myFile] ((doInsideStuff) {:mybirthday newValue}))

1:39 which returns a new map.. and then I can just merge the returned value into my map with a ref-set or something?

1:41 I mean, (defn doStuf

1:50 duck1123: is there a way to get a sequence of the functions that are defined. (perhaps in a given ns)

1:59 rottcodd_: duck1123: yes http://clojure.org/namespaces

2:01 duck1123: thanks

2:03 anyn: How do you do a "while (true) { socket.accept }" in clojure?

2:04 or just "while (true) {...}" for that matter

2:05 rottcodd_: loop and recur

2:08 eg. (loop [] (do-stuff) (recur))

2:10 anyn: ah

2:12 hmm, is there a "break" keyword to get out of a loop?

2:12 rottcodd_: put the recur in a conditional

2:13 anyn: i see

2:15 rottcodd_: another way to approach your doStuff function would be to do (assoc myFile :my-birthday new-value)

2:15 then you don't have to merge in the ref-set

2:15 anyn: (defn while [test do] (loop [test do] (if (not test) (recur test do))))?

2:16 yea, you mean inside the function? and return the whole map?

2:16 rottcodd_: yes

2:16 anyn: ok

2:18 rottcodd_: also, you can look into struct-maps for better performance

2:43 anyn: can you implement java interfaces in clojure? and how would you create the required methods?

2:44 scook0: anyn: check out the "proxy" macro

2:45 anyn: yea, I know about proxy, and have used it once or twice, but...

2:46 I've used it for event listeners

2:48 Here, I've got this large class that implements a "session" class, which requires certain methods.. I've done away with the larger class and broke the methods down into functions.. I'm guessing those functions will do their jobs, but they wont tie back as methods into the interface

2:52 I guess I could create on function that proxies the session interface, then implements the respective methods, which in turn just point out to the other functions in my ns?

2:54 H4ns: anyn: did you look at the proxy macro?

2:59 anyn: H4ns: yes. I'm only so so at reading the docs, but yea.

3:02 H4ns: anyn: i'm not sure if i understand your problem, but with proxy you can create a class that is used as a proxy so that java can call back into clojure functions

3:10 anyn: H4ns: Yea, sorry.. It's just such a confusing class. The class implements "SessionListener" .. in a connect() method, it does _session.setSessionListener(this) .. in the run() method it has a "_session.sendMessage(..." in there. And then, further down, it implements the required methods. I've turned the connect() method (which had the 'this' reference) into defn myConnect .. and made session.setSessionListener(this) into (.setSessionListen

3:12 so now the myConnect function has been registered as the listener for the "SessionListener" interface

3:13 do I have to add the proxy that implements the methods in the same function?

3:15 er, to the same function? that registers with mySession?

3:15 very confusing

3:21 seems like java methods usually translate to clojure functions (which are java classes) and a java class usually ends up being an entire clojure namespace (in terms of file size). So translating between the to isn't necessarily intuitive (for a newb).

3:23 I guess I need to create some sessionProxy function that talks to the interface and delegates to the other functions.

3:52 joha1: any one using chimp with clojure here? Trying to assign F5 to EvalFile() in .vimrc, but vim can't find the chimp function. I've tried several variants of chimp:EvalFile() and so on, but no luck so far.

4:08 Lau_of_DK: Morning gents

4:35 I might be lagging in my understanding of datastructures again, but if I have a list of lists, that I want to splice (?) so that I can work with the numbers individually, how to I go about this?

4:35 Like, lets say I want to multiply all ints by 2, why doesnt this work

4:35 user=> (permutations [1 2])

4:35 ((1 2) (2 1))

4:35 user=> (map #(* % 2) (permutations [1 2]))

4:36 ...and more importantly, how do I fix

4:42 and this is not what I need :)

4:42 user=> (map #(str %) (permutations [1 2]))

4:42 ("clojure.lang.PersistentList@8d94bf13" "clojure.lang.PersistentList@8d94bf53")

4:42 kotarak: Lau_of_DK: you get (* (1 2) 2). Why should * know about lists?

4:44 (map (fn [[x y]] (list (* x 2) (* y 2))) (permutations [1 2]))

4:44 or: (map (fn [x] (map #(* % 2) x)) (permutations [1 2]))

4:48 Lau_of_DK: Oh, thats a really clever way of doing it, didnt know about [[x y]] syntax

4:48 thanks

4:48 And kotorak, I was supposed to give you some feedback on that set/vector optimizing stuff we talked about right?

4:50 kotarak: You could also use a zipper, which works for arbitrary nested lists:

4:50 (loop [loc (seq-zip (permutations [1 2]))]

4:50 (cond

4:50 (end? loc) (root loc)

4:50 (branch? loc) (recur (next loc))

4:50 :else (do

4:50 (edit loc * 2)

4:50 (next loc))))

4:50 Lau_of_DK: yes. did you do some benchmark?

4:50 Lau_of_DK: yea, i'll show you my notes

4:50 test1: strings, fdigit

4:50 (test-frac 500 1000): "Elapsed time: 75177.45724 msecs"

4:50 test2: set, w/o fdigit

4:50 (test-frac 500 1000): "Elapsed time: 17426.179424 msecs"

4:50 score: Improved 430% from original

4:50 test3: set+vector, w/o fdigit

4:50 (test-frac 500 1000): "Elapsed time: 2140.255575 msecs"

4:50 score: Improved 3512% from original 814% from test2

4:50 H4ns: lisppaste8: url

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

4:51 kotarak: Lau_of_DK: wow. :)

4:52 Lau_of_DK: yep, was a good tip :)

4:56 okay, kotorak, it has to be flexible with the amount of args, lets say I have

4:56 ([ 1 2 3 4 ] [ 1 2 2 3]) and I want (1234 1223) to be my output

4:57 (map (fn [[x]] (map #(Integer. (str %)) x)) (permutations [1 2 3]))

4:57 shouldn't this do the trick ?

4:57 it doesnt....

4:57 :)

5:00 kotarak: (map #(Integer/parseInt (apply str %)) (permutations [1 2 3]))

5:00 Lau_of_DK: ok, now holding fast unto the "teach a man how to fish" principle, how did you arrive at that ?

5:01 kotarak: Ok. You want to concatenate the digits: (str 1 2 3 4) => "1234"

5:02 You get it in a list: (1 2 3 4) => (apply str (1 2 3 4)) => "1234"

5:02 You get it in a list of lists ((1 2 3 4) ...) and want a list of concats: (map ... ((1 2 3 4) ...)) => ("1234" ...)

5:03 Insert Integer stuff at right point as necessary...

5:04 Start with a small problem. build around your solution.

5:04 Lau_of_DK: Ok, good tips - Im thinking your intuition is a little more fine tuned than mine, but I understand what youre saying

5:05 btw, that approach wrapped in a couple of filters solved euler-41 in about 1 second

5:05 thanks for taking the time kotarak :)

5:05 kotarak: np :)

5:05 Whatever euler-41 is..

5:05 Lau_of_DK: http://projecteuler.net/index.php?section=problems&id=41

5:08 kotarak: btw. my zipper example above is actually broken....

5:09 Lau_of_DK: you broke it?

5:16 lisppaste8: kotarak pasted "zipper multiplying all leafs with two" at http://paste.lisp.org/display/68799

5:16 kotarak: Lau_of_DK: the correct version looks like this.

5:35 Lau_of_DK: I wish I could Lisp like that :)

5:36 kotarak: Like what?

5:37 Lau_of_DK: Its also SICP like, you can read it instantly, and it makes alot of sense, yet its hard to arrive at those solutions I think

5:39 asbjxrn: Uh.. Swing class for popping up a message?

5:39 kotarak: Yes. But when you are there, it a) so much fun and b) you ask yourself why didn't see it in the first place. One time I shrunk my code by around 8 screen pages, with the same functionality but much clearer. I asked myself afterwards, what I did in the first version.

5:39 Lau_of_DK: asbjxrn, JOptionPane

5:39 haha

5:39 Yes kotarak , I've been there

5:39 asbjxrn: Thanks.

5:40 Lau_of_DK: You can also compare my way of computing infinite fractions with Hoecks, thats about the same difference, and his is 4x faster

5:43 kotarak: But in the end it's all about experience.

5:43 Lau_of_DK: And wits I think

5:43 kotarak: Our student worker only thinks on objects. "Uh.. We have to derive a class, blablabla"

5:44 When I show him the clojure solution in three lines, he's totally surprised.

5:44 It's because he doesn't think that way.

5:45 Lau_of_DK: Kinda how I felt after years of C and then later C#. When I switched to Linux I got into SBCL, which was a complete and utter mind-opener. Then when I was drowning in the frustrations of non-proprietary CL frameworks, I found Clojure :)

5:48 asbjxrn: For me it was the library situation that drew me to Clojure, plus the cross-platformness of jvm.

5:48 Lau_of_DK: And not Lisp?

5:48 asbjxrn: I'm still more productive in CL.

5:49 (Doesn't take much...)

5:49 Lau_of_DK: k

5:49 asbjxrn: Funny thing, I wanted to write a program that reads midi in from external devices.

5:51 Apparently midi in is not something java does all that well by itself. The most likely approach is to use midishare/portmidi which is the same libraries I used in CL. Midishare is even a spinoff of a CL project (Common Music) I think....

5:52 Lau_of_DK: So its drawing you back in :)

5:54 kotarak: Clojure excited me again about Lisp. I always preferred Scheme, because "it's a Lisp-1" or however it is called. But the 1000 implementations put me off. And Clojure has this library advantage. I just like it. :)

5:54 asbjxrn: Not really, I've also gotten rid of my PC, and I don't have lispworks for OS X.

5:57 Lau_of_DK: I never even dug into Scheme because I heard it was mostly a toy for University students :P

5:58 kotarak: I worked on an interpreter for it... But never got far. :|

6:02 Lau_of_DK: An interpreter for Scheme ?

6:03 kotarak: Yes.

6:03 Lau_of_DK: Written in which language?

6:03 kotarak: C

6:03 Lau_of_DK: :)

6:03 asbjxrn: There's your problem.

6:03 Lau_of_DK: Wybiral wrote a Python interpreter in SBCL

6:04 asbjxrn: Everyone knows that scheme interpreteres are writtein in scheme.

6:04 kotarak: asbjxrn: This was more than ten years ago. I didn't know anything else. (Not to talk about language design... ) But it was fun. :)

6:14 lisppaste8: Lau_of_DK annotated #68789 with "How about this?" at http://paste.lisp.org/display/68789#2

6:38 asbjxrn: Is the namespace idiom still (in-ns 'foo) (clojure/refer 'clojure) ?

6:41 hoeck: asbjxrn: its currently (ns 'foo)

6:41 oh, no, just (ns foo)

6:44 asbjxrn: Thanks. That does seem to work.

6:47 thomaslee: hi all

6:47 hoeck: hi

6:50 thomaslee: I'm messing around with gen-class, just trying to get my head around a few things ... a fundamental one that's got me a little stumped is how I would implement a setter in Clojure ... e.g. (defn MyClass-setFoo [this foo] (...))

6:51 and I guess a sub-question here would be how do I declare member data for an instance of MyClass ... would I *need* to? :P

6:55 hoeck: thomaslee: clojure discourages you to build mutable objects, but admits that its sometimes necessary

6:56 kotarak: thomaslee: you can only have one member, the state. Then you can do something like: (defn MyClass-init [x] [[]�(ref {:foo "default" :bar x})]) (defn MyClass-setFoo [this foo] (dosync (commute (. this state) :foo foo)))

6:56 hoeck: so you can pass a ref to genclass

6:57 kotarak: (commute assoc ....) actually

6:59 thomaslee: hoeck: yeah, I know it's not encouraged but I'm interested to know how it would work for interop purposes :)

6:59 kotarak: great, thanks very much

7:00 hoeck: thomaslee: yeah, sorry for the disclaimer there :)

7:01 thomaslee: meh. totally understand, even appreciate it. :)

7:02 Lau_of_DK: hoeck, I am most impress0red by your fraction. I think I actually understand it now

7:02 Although - I dont get (at all) why it runs 4x faster than mine

7:05 hoeck: Lau_of_DK: its the same algorithm, and its good news, it means lazy-seqs aren't that slow

7:06 Lau_of_DK: and you benched it against my final version which does range 500 - 1000 in about 2 secs

7:07 hoeck: the one that uses vector and set and fdigit

7:07 Lau_of_DK: thats the one

7:07 so yours does 500 fractions in that range in 0.5 secs?

7:09 thomaslee: kotarak, so an equivalent getter would be something like (defn MyClass-getFoo [this] (get (deref (. this state)) :foo)) ?

7:10 kotarak: thomaslee: yes or just ((deref (. this state)) :foo), get is not strictly necessary

7:11 thomaslee: kotarak, cheers!

7:16 hoeck: Lau_of_DK: yes

7:17 Lau_of_DK: hoeck, my hat is off to you sir

7:20 hoeck: Lau_of_DK: i'm not using any strings

7:21 Lau_of_DK: hoeck, no, the most impressive thing about your solution (from my pov) is that you totally escape all this conversion madness that I got myself into

7:22 hoeck: why did you do that this way? (converting integers to strings and back?)

7:23 Lau_of_DK: Only way I knew how, because I was getting error messages in the REPL that I couldnt make head or tail from, so I knew that x->str->desired-type always works :P

7:26 and also, because I hadnt found quot, which I can see you make good use of

7:27 hoeck: yeah, just inserted `quot' into your fraction-function, now you're 30% faster than me :)

7:27 Lau_of_DK: Weeeeeeeeeeeeeeeeeee

7:27 :)

7:28 How do you like them apples Hoeck? You beat yourself at your own game

7:30 * hoeck silently deletes `quot' from lau's fraction function

7:31 Lau_of_DK: haha, Its improved 29251% from the original function

7:49 thomaslee: kotarak: I'm seeing "No matching field found: state for class MyClass" ... is the state of an object always implicitly called "state" ? or am I doing it wrong? :P

7:50 kotarak: you have to declare it in gen-class with :state. You can call it whatever you like.

7:50 thomaslee: ah right, thanks

7:51 the documentation's a little screwy ... the :state option seems to be appended to the end of the documentation for :factory -- I missed it first time through.

7:52 kotarak: use (doc gen-class) there it's not screwed.

7:52 thomaslee: nice ... thanks for all the help

8:03 sorry kotarak, one more thing: I'm getting a ClassCastException, presumably because setFoo is declared as returning void in :methods, but in actual fact is returning a non-void value due to the behavior of commute ... what's the most logical way to deal with that?

8:03 ugh, "returning void" ... excuse the crap terminology

8:04 kotarak: (do (commute ...) nil) or declaring the setter to return Object, I think.

8:18 thomaslee: kotarak: that seemed to do the trick. Also wound up having to use #(merge % {:foo foo}) in place of ":foo foo" for the setter call ... the value doesn't otherwise seem to be saved to the state

8:20 kotarak: o.O no?

8:21 thomaslee: nope ... not quite sure what was happening. Entirely probable I was doing something wrong, but the merge approach worked off the bat.

8:21 The actual setter implementation looks like this: (dosync (commute (. this state) #(merge % {:cents cents}))) nil)

8:23 kotarak: (dosync (commute (. this state) assoc :foo foo)) does not work?

8:23 thomaslee: ah I missed the assoc first time through

8:23 I'll give that a shot

8:24 yep, that works great

8:24 sorry, I must've misread/misunderstood

8:24 kotarak: pfuu.. World saved again. ;)

8:24 thomaslee: haha ... bit more readable :)

8:25 kotarak: thomaslee: I miswrote initially.

8:26 thomaslee: kotarak, ah I see now

8:27 kotarak: thomaslee: yeah, so I'm also kind of "guilty" if one wants to call it like that...

8:27 thomaslee: kotarak: I'd still be scratching my head if it weren't for your help, so I'm not about to go laying blame ;)

8:43 is it possible to provide a name to defn dynamically in a macro? Something like `(defn (format-string "%s-%s" ~a ~b) (...)) ?

8:44 s/format-string/format/

8:44 kotarak: you do something like this: `(defn ~(symbol (str a "-" b)) ....)

8:50 Pupeno-G: Hello.

8:51 So, there are essentially two web frameworks for Clojure, Webjure and Compojure, right? Webjure seems to write a Java-style web application, but using Clojure and Compojure seems a more from-the-scratch approach; am I right?

8:52 s/from-the-scratch/from-scratch/

8:56 tWip: define Java-style

8:57 Pupeno-G: tWip: with Servlets and other stuff I don't yet understand or know about.

8:58 tWip: I haven't checked compojure, but I made webjure work with servlets because that is the de-facto way Java web apps are deployed

8:58 taking advantage of existing infastructure on app servers

8:59 you don't need to write a single line of Java-code if you write a webjure app

9:02 Pupeno-G: I think I'd like to give webjure a try, but the last time I've tried to understand the Java Webapp world, I've read like 150 pages of Sun's Java EE manual or something like that without a single line of code... when I woke up I just went back to Django. Any recommendations on how to approach it?

9:03 tWip: There is an installation page on the webjure wiki now, you could check that

9:04 thomaslee: http://pastebin.com/d730b2d21 -- I'm seeing "Can't use qualified name as parameter: com.deskchecked.clojure.interop/this" ... what am I doing wrong here?

9:04 tWip: if you have maven installed, the process of getting the demos up and running is quite simple

9:05 thomaslee: http://pastebin.com/db311b01 -- updated code with capitalize implementation and syntax highlighting

9:05 Pupeno-G: tWip: ok, that might be a good starting point. I'll just install maven, thankfully there's a package for my OS.

9:07 thomaslee: all that code is obviously in the namespace that's being complained about in the error message, but I'm curious as to why it's trying to bind "this" to that namespace.

9:07 achim_p__: thomaslee: symbols inside syntax-quote automatically obtain ns prefixes

9:08 try a normal ' quote

9:10 thomaslee: a normal quote where? in place of the backtick/syntax-quote?

9:13 achim_p__: no, just for the "thisses": "this" -> "~'this"

9:14 but it's probably better to use gensym to generate a unique symbol

9:15 thomaslee: ah, brilliant - thanks very much

9:15 achim_p__: i.e. "this" -> "this#" (#-suffixes are a shorthand for gensym)

9:16 thomaslee: achim_p__, why's that? in case make-setter is invoked within another function declaring "this" ?

9:24 achim_p__: thomaslee: in your specific case, it doesn't matter, as far as i see - it's just a thing i accustomed to doing when writing macros, to avoid hard-to-debug name clash errors. plus, i find it easier to read than ~'anything

9:28 thomaslee: achim_p__, sure, understood. Thanks for the tip.

10:55 anyn: Lau_of_DK: I want to see this fraction code...

10:55 Lau_of_DK: http://paste.lisp.org/display/68739 <---3 versions

10:56 As they stand, #3 is the fastest

10:57 AWizzArd: hi

10:57 Lau_of_DK: Heya

11:02 arbscht: hm, looks like lisppaste is down

11:02 anyn: hmm. paste.lisp.org is having a hard time

11:02 I concur

11:02 there it is

11:13 that's deep stuff

11:33 Lau_of_DK: user=> (trunc [1030])

11:33 ["1030" "103" "10" "1" "" ["030" "30" "0" ""]]

11:33 Gents, how do I convert all these to Ints as concisely as possible?

11:35 AWizzArd: How do I test for bar being not a collection, so, no string/list/map/vector/set? CL's (atom bar)

11:36 duck1123: (not (seq? bar)) maybe?

11:37 AWizzArd: no, seq? tests only for lists

11:37 (not (seq? [1 2 3])) ==> true and (not (seq? '(1 2 3))) ==> false

11:38 duck1123: (nil? (rest bar))

11:39 fyuryu: you can use derive for PersistentVector and others and then use isa?

11:40 AWizzArd: fyuryu: what do you mean?

11:40 fyuryu: AWizzArd: http://groups.google.com/group/clojure/browse_thread/thread/9cc9926de1bdb128

11:40 AWizzArd: I could also do something like (not-any? #(% bar) [seq? vector? string? map? set?]) ;-)

11:41 fyuryu: AWizzArd: because I don't think there is something like atom

11:42 AWizzArd: I think the same, at least by skimming through the api and boot.clj I didn't find it, and also no (col? bar)

11:43 fyuryu: AWizzArd: didn't know about not-any?, when did that happen?

11:44 AWizzArd: I don't know when it was added

11:44 fyuryu: AWizzArd: ok, not important ;-) just thinking to myself

11:47 AWizzArd: duck1123: (nil? (rest 5))

11:48 duck1123: yeah, I noticed that

11:58 Chouser: there is (coll?)

11:58 string is not a Collection -- is that ok?

12:15 fyuryu: Chouser: great, I was at the repl, but thought to myself:

12:15 Chouser: "no, I bet there is no coll?" ane didn't evet try it

12:19 AWizzArd: there is no col? yet

12:19 we should add it to the svn

12:19 Chouser: why is a string not a collection?

12:19 fyuryu: coll?

12:20 AWizzArd: It surely is not a very generic one as it can only eat chars, but one can see it as a bag/collection full of them

12:20 I personally like col? more fyuryu

12:21 anyn: If I'm converting a large java class into clojure (where, you know, most methods become functions) and said large class implements many interface methods, some of which are callbacks, with logic distributed throughout... what's the preferred way to manage that?

12:24 it's weird. the class implements "SessionListener" and one method registers the class with a session with _session.setSessionListener(this); ... while other methods implement some session listener methods, like "messageReceived" .. so, when the implementation of an interface is spread across the whole class, how does one translate that?

12:26 I can't proxy in every function, cause those various functions won't be recognized as the registered SessionListener in the session collection, right?

12:34 brb

12:45 arbscht: Lau_of_DK: I presume you want to map Integer/parseInt to the strings, but how do you want to treat ""?

13:02 duck1123: has anyone here ever solved euler-12 in clojure? If so, do you know how long it took?

13:04 StartsWithK: hi

13:05 what is the state of aot compiler?

13:20 Lau_of_DK: arbscht, I've fixed it, thanks

13:20 the trick was to avoid those ""'s

14:00 Chouser: StartsWithK: AOT compiler isn't ready yet, but I'm under the impression it's close.

14:02 AWizzArd: collections can hold anything. If you want to treat a string like a seq, you may: (seq "foo")

14:06 StartsWithK: Chouser: thanks

14:09 Chouser: anyn: you may need something like: (defn make-thing [] (let [somestate ...] (proxy [Listener1] (foo ..refer to somestate...)) (proxy [Listener2] (bar ..refer to somestate..)))

14:10 AWizzArd: Chouser: I want to argue that a string is a collection.

14:11 It's a typed collection and can only contain chars, as opposed to generic/dynamic collections which can hold any objects.

14:12 Chouser: well it may be a collection, but it's not a Collection.

14:12 It's a Java class, and so Java has set the rules for interacting with it.

14:18 AWizzArd: I am talking from the view of Clojure. Do you think one can't see it as a collection but instead as an atom?

14:19 It may be very well a Java String under the hood. But I would like to abstract that implementation detail away.

14:19 duck1123: wouldn't that mess up the ability to use a clojure string as a java string unmodified?

14:22 AWizzArd: I just mean that I see a string as a container datatype, and not something atomic like a number or character. Under the hood it's just zeros and ones, but I don't care. For me it's important that I know a string can contain a number of atomic objects, in this case: characters.

14:25 lisppaste8: Lau_of_DK pasted "Speed/Java-heap/Help" at http://paste.lisp.org/display/68822

14:25 Lau_of_DK: Okay, you old-school clojure-bred ninjas. Why does this fail so badly ?

14:28 AWizzArd: Argh, why putting the parameter list not in the line of (defn function [parameter here] ...)?

14:29 Lau_of_DK: because thats not 1337

14:29 according to wikipedia :P

14:30 AWizzArd: I'm feeling ice cold now after I saw that ;-)

14:30 duck1123: does it bother anyone else that the doc-string goes before the param list?

14:30 AWizzArd: me :-)

14:30 Lau_of_DK: look, you guys are missing the point, I wasnt asking for cosmetic tips here, I need this to compuete quicker and without blowing any heaps, any input on tht? :)

14:31 AWizzArd: but Lau felt so free to put the parameter vector into the next line even when his functions had no docstring

14:32 Lau_of_DK: lol

14:32 arbscht: duck1123: it doesn't bother me. in fact, it makes sense, because a function can have multiple signatures

14:32 duck1123: I'm just used to elisp, where the order is reversed

14:33 AWizzArd: in common lisp it's also different

14:33 arbscht: could you give an example of what you mean by multi signatures?

14:34 you mean like (defn str ...) in boot.cjl?

14:34 or (defn concat ...) in boot.clj?

14:34 kotarak: AWizzArd: (defn foo ([x] :one) ([x y] :two)) (foo :x) => :one, (foo :x :y) => :two

14:35 arbscht: AWizzArd: yes, those are such examples

14:35 AWizzArd: okay, so destructuring functions.. yup, for those it makes sense, I agree

14:35 kotarak: No. It's not destructuring. It's different arity.

14:36 (defn foo [[x y]] ..) this is destructuring

14:36 AWizzArd: yes, you are right

14:36 duck1123: Lau_of_DK: sorry, my clojure isn't to the point yet where I'm even quite sure what that code is doing, let alone why it fails

14:38 Lau_of_DK: I know that the trunc isnt very pretty, but this is what it does

14:38 user=>(trunc [123])

14:38 (123 23 3 21 1)

14:38 or to put it another way

14:38 123

14:38 23

14:38 3

14:38 123

14:38 12

14:38 1

14:43 hircus: Lau_of_DK: this for Project Euler? :)

14:43 Lau_of_DK: Yes sir

14:43 AWizzArd: Lau_of_DK: what do you expect trunc to be doing for (trunc [12345])?

14:44 Lau_of_DK: 12345

14:44 1234

14:44 123

14:44 12

14:44 1

14:44 and then from the other side as well

14:44 2345

14:44 345

14:44 45

14:44 5

14:45 hircus: not familiar with Clojure's lazy sequences -- would filtering a lazy seq give a lazy seq or an eager one?

14:45 Lau_of_DK: Would still be lazy

14:45 AWizzArd: Is this part of the task? Or why do you test these strange things for being a prime?

14:45 Lau_of_DK: http://projecteuler.net/index.php?section=problems&id=37

14:46 hircus: Lau_of_DK: seems like you're better off eagerly computing primes up to a certain point

14:46 Lau_of_DK: I have no way of knowing what that point might be

14:47 hircus: when doing an earlier problem (sum of all primes < a million, IIRC) I found that Haskell's lazy prime number sieve became too slow

14:47 Lau_of_DK: k

14:47 hircus: true. so I guess you can keep retrying as long as the number of primes you find is less than 11

14:48 Lau_of_DK: Thats a good idea

14:48 hircus: haven't tried that problem yet, though. how many have you done?

14:48 Lau_of_DK: I need a quick reboot, then I'll get right on it

14:48 I dont know, it blew the heap before I could see. The last number is 3797, and theres only 1 more known to man, I imagine its quite high

14:50 duck1123: hircus: if that was 10, I just did that last night ~10 sec done lazily

14:51 achim_p__: lisppaste8: url

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

14:53 hircus: duck1123: ah. I don't have the non-working Haskell code anymore though. but I might just not be writing it in the proper way; Haskell is tricky to write fast code in

14:54 duck1123: this is what I came up with: http://clojure-euler.wikispaces.com/Problem+10

14:54 Chouser: hm, I apparently abandoned projecteuler after problem 36

14:54 duck1123: I was trying problem 12, but it was taking forever

14:55 never did find an answer, it was slowing down my computer too much

14:55 lisppaste8: achim_p pasted "???" at http://paste.lisp.org/display/68825

14:56 achim_p__: can anybody help explaining what's happening there? i just don't see it

14:56 hircus: duck1123: problem 12 took me quite fast in clojure

14:57 I used unchecked operations since the resulting numbers won't really get too big

14:57 duck1123: hircus: do you happen to have your code, I want to see what I was doing wrong

14:57 hircus: duck1123: sure. pastebin?

14:57 duck1123: that works

14:58 lisppaste8: hircus pasted "Euler #12" at http://paste.lisp.org/display/68826

14:59 Lau_of_DK: hircus, feel free to contribute: http://clojure-euler.wikispaces.com/

15:00 achim_p__: (= #{1 4} #{2 3}) ; => true - now it makes sense again!

15:00 Lau_of_DK: glad you worked it out achim_p__ , I was lost

15:01 achim_p__: mmh, they aren't exactly equal, are they?

15:01 Lau_of_DK: if you add them together they are

15:02 achim_p__: then we had to have (= 4 3), because 7 = 7

15:02 Lau_of_DK: if the comparison is just based on sum, then it makes sense

15:02 try {10 2} {8 4}

15:02 achim_p__: why should a comparison be based on a sum?

15:02 Lau_of_DK: bug maybe? :)

15:02 hircus: Lau_of_DK: cool, will do

15:03 found another Clojure Euler project at Google Code but the code there was atrocious

15:04 whoever ran it reimplemented things like even? and did the world's slowest exponentiation function

15:05 Lau_of_DK: Well, things can also be improved upon, so its probably a good idea just to consolidate on wikispaces

15:06 hircus: yup, I agree that a Wiki is actually a good place for things like this

15:06 Lau_of_DK: I think the "Optimal toolkit" will be sweet. Specially if people are diligent in bencmarking their stuff

15:06 hircus: should we rename the problems to all have three digit numbers, so that they sort properly?

15:06 Lau_of_DK: Good idea

15:07 I dont know who owns it, I think it was started by achim_p, so I cant really decide anything, but it sounds good

15:07 achim_p__: can anybody reproduce this equality?

15:07 bitbckt: achim_p__: came late to the game. which?

15:07 hircus: Lau_of_DK: ok, just applied

15:07 Lau_of_DK: achim_p__, I'd love to help, but Im still waiting for my filter to return

15:07 achim_p__: (= #{1 4} #{2 3}) ; => true

15:08 AWizzArd: (= #{-100 -50} #{-210 60}) ==> also true :-)

15:08 hircus: achim_p__: same here

15:08 bitbckt: nope, false here

15:08 hircus: bitbckt: which Clojure build are you on?

15:08 achim_p__: bitbckt: which revision?

15:08 bitbckt: I'm on the 9/16

15:08 just about to say, lol

15:08 hircus: I'm on an SVN checkout from a few days ago. looks like new bug

15:09 achim_p__: okay, thanks for your feedback!

15:09 bitbckt: of course.

15:10 hircus: Lau_of_DK: using Python, the 11th number you're looking for is under 1 million :)

15:10 bitbckt: git bisect to the rescue...

15:11 Lau_of_DK: hircus, I cant except anything coming from Python, sorry

15:13 hircus: Lau_of_DK: hehe. well, I can port the code to Clojure real quick

15:13 Lau_of_DK: Please do so

15:17 achim_p__: http://www.bitbucket.org/shoover/clojure-mirror/changeset/9a6760cf79b9/#chg-src/jvm/clojure/lang/APersistentSet.java

15:17 might be this change that breaks it

15:18 Lau_of_DK: Considered posting it to the Google group so Rich could have a look ?

15:18 bitbckt: achim_p__: 49a1829 looks like the first bad commit

15:18 r1052 in the SVN repo

15:19 from the comments: unified equality and hashCode semantics for sets/maps/lists with java.util

15:19 Lau_of_DK: hircus, I have a working clojure solution now,

15:20 bitbckt: heh... you found it first

15:20 damnit ;-)

15:20 achim_p__: bitbckt: :) thanks! you used git bisect?

15:20 bitbckt: yessir

15:20 I didn't script it, since there were so few commits... it goes slower

15:21 * bitbckt makes excuses

15:21 Lau_of_DK: bitbckt, want me to get you that violin?

15:21 bitbckt: hehe

15:21 Lau_of_DK: :)

15:23 achim_p__: bitbckt: i don't really know git, but the bisect feature looks very cool

15:23 bitbckt: achim_p__: it works wonders

15:24 achim_p__: ... darcs and hg have it, too

15:27 achim_p__: ok, then i'll stick with hg. i'm slowly getting used to it. bzr was probably my favourite, in ease-of-use terms, but the only free hosting service was launchpad, which is a complete catastrophy in ease-of-use-terms :)

15:30 AWizzArd: achim_p__: do you think it could have to do ith the hash?

15:30 hircus: Lau_of_DK: ugh, turning an integer to a string in Clojure could be made a bit easier

15:31 Chouser: I think it's a typo.

15:31 hircus: Lau_of_DK: ah nevermind, misread something

15:31 bitbckt: achim_p__: you don't need validation from me, but I like hg, too. I use both on-and-off nearly everyday.

15:36 Lau_of_DK: Chouser, did you catch cgrand's update on his blog?

15:37 Chouser: Lau_of_DK: heh, nope.

15:38 lisppaste8: hircus pasted "stack problem computing primes" at http://paste.lisp.org/display/68828

15:39 hircus: any idea what's going on here? (not the Clojury way to do things, but it really should not fail, no?)

15:39 Chouser: achim_p__: nice catch -- I think I spotted the typo.

16:02 Pupeno: Can webjure be used with Glassfish instead of Jetty?

16:03 achim_p__: Chouser: cool, thanks for tracking it down!

16:08 sohail: I may have missed this in the reference, but what does #^ mean?

16:09 ah, nevermind. It's in the reader section

16:09 pretty f'in cool man

16:12 AWizzArd: In principle a Clojure developer does not need the java jdk (installed), right? The jre is enough?

16:14 Lau_of_DK: Yes

16:17 AWizzArd: And do we know what version of the jre is needed? Is 1.5.0_04 enough?

16:18 Lau_of_DK: I think so

16:18 I remember trying, I think it succeded

16:19 arohner: I'm running 1.5.0_16 here

16:19 bitbckt: JRE 1.5.0_16 works

16:19 heh

16:19 AWizzArd: good

16:26 sohail: just checking my understanding. If there is no singleton empty-list value, each empty-list value will return nil when asked to iterate, which is almost the same thing right?

16:29 arohner: isn't there a function to flatten a vector? i.e. [ [1 2] [3 4]] -> [1 2 3 4]

16:29 AWizzArd: (= () ()) ==> true and (identical? () ()) ==> true

16:30 sohail: AWizzArd, what are you showing there?

16:31 arbscht: arohner: (mapcat identity [[1 2] [3 4]]) => [1 2 3 4]

16:33 Chouser: or (apply concat [[1 2] [3 4]])

16:33 sohail: yes -- calling seq on any empty collection returns nil

16:34 arohner: thanks!

16:34 sohail: that doesn't really flatten nested lists

16:34 Chouser: arohner: there's also something in clojure.contrib if you want arbitrary depth flattening

16:34 sohail: err vectors

16:34 ah

16:37 AWizzArd: sohail: it seems there is a singleton empty list

16:39 sohail: AWizzArd, I think the reason is that immutable structures define = as value comparison, not identity

16:40 oh wait you did identical?

16:40 does that use .equals or java == ?

16:41 Reference comparison. Returns true if x is the same object as y, false otherwise.

16:41 k!

16:41 AWizzArd: I don't know java, but it is like Common Lisps eq

16:42 it makes sense that there exists exactly one empty list

16:43 sohail: what is (rest '(1)) supposed to give you?

16:43 arohner: I *think* that clojure lists share structure whenever possible

16:44 so the empty list is just a particular instance of lists sharing structure

16:44 sohail: has anyone tried to write a GUI using clojure?

16:44 AWizzArd: in Clojure I would suppose it should not give me anything, so nil would be cool

16:45 arbscht: many have

16:45 sohail: arbscht, have any examples?

16:45 AWizzArd: sohail: hehe, this one maybe: http://clojure.org/jvm_hosted

16:45 sohail: AWizzArd, ya I saw *that*

16:45 I meant a real one :-)

16:46 is enclojure written in clojure?

16:46 "enclojure is written predominately in Clojure."

16:46 arbscht: there are snippets here http://groups.google.com/group/clojure/browse_thread/thread/22e4696550b6c4fa

16:47 this is a little game in Swing http://blog.jalat.com/2008/10/game-clojure-version.html

16:48 sohail: hang on. you can do interactive GUI development? cool...

16:48 * sohail is using swank-clojure

16:48 AWizzArd: The guy for that game should have made it available as webstart or applet also

16:48 arbscht: I wrote a tiny implementation of Snake on Swing http://www.plt1.com/1070/even-smaller-snake/

16:49 AWizzArd: sohail: yes, you can change your gui from within clojure while your program is running

16:49 arbscht: where is the binary for that? ;-)

16:49 you could make it available by a mouse click

16:49 sohail: hmm, it killed the REPL when I hit ALT-F4

16:50 arbscht: depends on the default close operation of the frame

16:59 lisppaste8: achim pasted "lazy powerset enumeration" at http://paste.lisp.org/display/68832

16:59 achim_p__: anybody in for a game of clojure pingpong? ;) my first lazy seq - no doubt there is a better way

17:00 weird indentation

17:03 hircus: achim_p__: ping pong?

17:05 achim_p__: ah, it was golf, not ping pong (http://clj-me.blogspot.com/) - they're pretty close, white ball etc.

17:09 Lau_of_DK: lol

17:09 etc?

17:11 achim_p__: clubs

17:12 Lau_of_DK: if somebody has the time, would you mind writing clomacs ?

17:22 hircus: Clomacs would be really neat. probably more feasible than the Scheme port of Emacs :)

17:24 AWizzArd: suns java sdk in debians/ubunts package list is called openjdk?

17:24 arbscht: sun-java6-jdk or sun-java5-jdk

17:25 AWizzArd: uh, is their java different from the openjdk stuff?

17:26 arbscht: it's non-free

17:45 Lau_of_DK: http://clojure-euler.wikispaces.com/ <-- Counting 17 solutions now, everybody feel free to contribute

18:08 hircus: silly question, but how do I use the closure.set functions?

18:11 jao: hi. is M-. (find-source-location) supposed to work in slime for clojure?

18:13 AWizzArd: hircus: apply them on arguments

18:13 sohail: how do you use multimethods with structs?

18:13 hircus: AWizzArd: I can't get them imported, that's the problem

18:13 arohner: hircus: (use 'clojure.set)

18:14 sohail: it isn't obvious to me how to make (defstruct rectangle ...) use :shape as the dispatch function

18:14 hircus: arohner: aha. thanks

18:15 arohner: hircus: also look at (doc require)

18:17 sohail: anyone know how to convert the multiple dispatch example to use structs?

18:18 AWizzArd: can you be more specific?

18:18 sohail: AWizzArd, the one here: http://clojure.org/multimethods

18:18 I can't see how to set the :Shape key to always return :Circle or :Rectangle via defstruct

18:21 AWizzArd: the keyword itself can be used as a function

18:21 (defmulti blah count)

18:21 sohail: I know

18:22 AWizzArd: this means that whenever blah is called it's arguments will be applied to count

18:22 (blah something) will become: (count something)

18:22 this yields a result

18:22 (defmethod blah 3 [arg] "hallo")

18:22 and now you can say: (blah [10 20 30]) ==> "hallo"

18:22 sohail: but how would I define the rectangle struct so that rectangle always returns :Rectangle for that function?

18:23 AWizzArd: because (count [10 20 30]) yields 3

18:23 sohail: if I have my own make-rectangle, I can return {:Shape :Rectangle ... }

18:23 AWizzArd: yes

18:23 sohail: and so (:Shape (make-rectangle ...)) => :Rectangle

18:23 AWizzArd: and it must have an even number of elements

18:23 sohail: but how do I use defstruct to do that?

18:24 AWizzArd: (defstruct foo :name :age)

18:24 sohail: and..

18:24 AWizzArd: and now you can have a (def x (struct foo "Carl" 29))

18:24 (:age x) ==> 29

18:24 sohail: I got that

18:24 but I don't want the user to have to set :Shape, I want it to have a default value

18:25 StartsWithK: (defstruct rectange :Shape :x :y :w :h)

18:25 AWizzArd: now lets dispatch on the age

18:25 arbscht: you cannot set a default value when you define a struct. it's not a class

18:25 sohail: oh, are there classes too?

18:25 arbscht: no :)

18:25 AWizzArd: you have something much better

18:25 Paul Graham said already long time ago: functional programming + macros outperforms OOP

18:26 sohail: yeah don't worry, I get it

18:26 where is CLOJS ? :-)

18:26 or is it CJOS

18:26 AWizzArd: CLOS

18:26 arbscht: there are ad-hoc hierarchies which, admittedly, I'm not fully familiar with

18:26 see isa and derive

18:28 sohail: ok, I guess I'll look at it later

18:28 AWizzArd: When you create one million hash table objects that all share their keys and only differ in value, then you waste some memore. defstruct, as I understand it, enables you to create these one mio instances and they all share the keys (= the struct fields).

18:29 sohail: ok, that's fine

18:29 AWizzArd: do you feel now better about this example from the clojure site?

18:29 sohail: but I don't understand how I would implement any sane sort of multimethod based API without some support for default values

18:29 no

18:29 AWizzArd: let's make it 100% clear, but you need to tell exactly what is unclear

18:30 sohail: I mean, as long as the user can do: (struct rectangle :Shape :Circle ...) things can go pear-shaped

18:30 http://clojure.org/multimethods

18:30 AWizzArd: it has 16 lines... which of those are still puzzeling?

18:31 it = the example on that site you just posted

18:31 sohail: convert that to using structs... without the factory functions, the user can accidentally type (struct rectangle :Shape :Circle ...)

18:32 ok I gtg just now

18:32 bbl

18:37 AWizzArd: sohail: as I understand it you can't do this example with structs. If you have a (defstruct rect :wd :ht) and say (def x (struct rect 10 20)) then there is no way to find out that x is a rect. If you want to keep this info then you would need to do something like: (def x (conj {:Shape :Rect } (struct rect 10 20))) and never forget to conjunct these things whenever you create a rect.

18:44 StartsWithK: AWizzArd: But then :Shape key will not be shared

18:45 AWizzArd: StartsWithK: as I see the example from the Clojure site :Shape won't be shared anyway.

18:46 StartsWithK: AWizzArd: but example is not using struct

18:46 AWizzArd: right, so it can't share the key information.

18:47 the example from Rich does not make use of the data structure "Structured Map"

18:48 a struct is a table where you can have any number of lines where the columns have headlines (= "fields" of the struct)

18:49 StartsWithK: but is example how to use multimetods, nothing more, it's minimaln in that way

18:49 AWizzArd: yes, he uses multimethods, but I think sohail is trained in oop thinking and tries to find out how this example would look like if Rich had used structs.

18:50 StartsWithK: when you want to use struct, and you know :Shape key will use in every struct you create, then you should put it inside struct itself

18:50 will be used*

18:50 AWizzArd: StartsWithK: this would still be a leaky abstraction, as you would every time you create a rect have to say (struct Shape :rect 10 20)

18:52 StartsWithK: but you will get key shaing, struct have any other advantages

18:52 sharing*

18:52 i don't see how not sharing :Shape is more or less of leaky abstraction

18:53 AWizzArd: because you need to explicitly give the same argument whenever you create a rect

18:53 the example on the page shows how you only have to specific width and height

18:56 StartsWithK: (defn rect [wd ht] {:Shape :Rect :wd wd :ht ht})

18:56 AWizzArd: yes

18:56 StartsWithK: it gives :Shape every time you create rectangle

18:56 nicknull: is there a database lib shipping with clojure?

18:56 StartsWithK: and not only width and height

18:56 nicknull: there is sql lib in clojure-contrib

18:56 AWizzArd: nicknull: yes, the one from Java

18:57 StartsWithK: yes, this is right, and it is exactly what I said.

18:57 nicknull: lol

18:57 StartsWithK: nicknull: http://sourceforge.net/projects/clojure-contrib

18:57 AWizzArd: It is just not a struct

18:57 StartsWithK: AWizzArd: you sad " the example on the page shows how you only have to specific width and height"

18:57 AWizzArd: it is a hash map

18:58 nicknull: ty Clojure really is cool. so many alternative langs lack practicality

18:58 StartsWithK: and you have to specify :Shape to

18:58 AWizzArd: yes, and you have.. the function you posted takes 2 arguments, not 3

18:58 StartsWithK: but that is a factory function

18:58 AWizzArd: no, :Shape is always set to a symbol

18:58 right

18:58 and there is no defstruct in the example, so, no structured map, but a hash map instead

18:58 StartsWithK: so, you will have a factory function for your rectangle struct too

18:59 AWizzArd: (defstruct rect :hd :wd)

18:59 StartsWithK: only differance is your keys will get shared

18:59 there is nothing more struct will do for you

18:59 AWizzArd: (struct rect 10 20) ==> {:ht 10 :wt 20}

18:59 and not {:Shape :rect :ht 10 :wt 20}

19:00 StartsWithK: but if you want to dispach on shape type you will have to have :Shape key in there

19:00 AWizzArd: absolutely

19:00 and this is why I said to sohail that he can not use defstruct here

19:00 nicknull: but clojure got it all

19:00 StartsWithK: why not?

19:00 AWizzArd: show me how StartsWithK

19:01 Maybe I don't understand this mechanism well enough

19:01 I would like to see how you do it as sohail asked for

19:02 do the same example as in http://clojure.org/multimethods but you must not have factory functions

19:02 StartsWithK: (defstruct rectangle-struct :Shape :w :h) (defn rectangle [w h] (struct :Rect w h)) (defmulti area :Shape)

19:02 (defmethod :Rect ...)

19:02 AWizzArd: sohail explicitly disallowed functions..

19:02 you may not use defn

19:02 StartsWithK: how you mean no factory function

19:02 that makes no sense

19:02 AWizzArd: he wanted it

19:03 and I answered that this way this example can't be don

19:03 done

19:03 StartsWithK: yes, i was reading it

19:03 AWizzArd: of course it makes no sense, but this was what he asked for

19:04 rukubites: Hello, I am a common lisp programmer and I use Slime extensively. I am looking into using Clojure for an upcoming project, and I have clojure and swank-clojure installed. Unfortunately slime-eval-print-last-expression (C-j in *slime-scratch*) is failing, I think because it uses asynchronous evaluation. Is this a known issue or a regression? Is it fixable?

19:04 AWizzArd: and this means that if you have a (defstruct Rect :Shape :w :h) then you must always provide an argument for the :Shape key

19:04 StartsWithK: but, this is what i sad is wrong: (def x (conj {:Shape :Rect } (struct rect 10 20)))

19:04 becouse you don't get :Shape key sharing

19:05 AWizzArd: no StartsWithK, I explained a few lines before that the struct rect looks like this: (defstruct rect :w :h). As you see, no :shape key there.

19:06 rukubites: I really want to be able to adapt my workflow for working with clojure, and I use C-j all the time.

19:07 AWizzArd: StartsWithK: sohail was thinking in OOP terms. If Clojures struct where really a struct then saying (defstruct Rect :h :w) would be fine, because (struct rect 10 20) would yield an object on which you could do something like: (is-rect? (struct rect 10 20)) ==> true

19:08 StartsWithK: You sad: " If you want to keep this info then you would need to do something like: (def x (conj {:Shape :Rect } (struct rect 10 20))) and never forget to conjunct these things whenever you create a rect."

19:09 AWizzArd: yes, of course

19:09 StartsWithK: and i sad: But then :Shape key will not be shared

19:09 AWizzArd: and i agree

19:09 shared in the sense of StructMaps (the datatype)

19:10 and I also say: as this example stands on the website, there also is no sharing

19:10 rukubites: Anyone?

19:11 AWizzArd: rect always returns a fresh Map, but not a StructMap

19:12 :Shape :Rect is shared in the sense of being a key/value pair in that Map. But it is not shared in the sense of a StructMap, where the keys don't consume memory, but only the values.

19:12 rukubites: for me slime+Clojure works fine. But I never used your key combination, so I can't say anything about it

19:13 rukubites: AWizzArd: if it is convenient, can you test to see if it works? I downloaded all the code fresh today, and if it works, that would indicate a regression.

19:14 AWizzArd: what do I have to do?

19:17 rukubites: M-x slime-scratch , then in the buffer type (+ 1 1) and press C-j after the last bracket.

19:17 C-x C-e after the bracket works correctly.

19:17 AWizzArd: it says: "Evaluation aborted." after I pressed C-j

19:18 rukubites: Yes. Normally it inserts a newline and writes out "2" below the form.

19:18 Thank you.

19:18 I will email the list.

19:18 AWizzArd: I see

19:19 rukubites: It is the way I standardly develop, in a buffer. I don't really like using the REPL directly.

19:19 AWizzArd: I see, I never used slime-scratch

19:19 always do CL on the relp, since many years :-)

19:20 arbscht: it appears swank:eval-and-grab-output is unimplemented by swank-clojure

19:22 rukubites: Ahhh. I am not a slime/swank programmer per-se, do you know whether it is unimplemented because it is "hard" or because it is just "not done yet" ?

19:23 AWizzArd: no idea

19:23 rukubites: AWizzard: I like using scratch pads because it is easier to morph exploratory code into working functions.

19:23 arbscht: rukubites: I would say "not done yet"

19:24 rukubites: arbscht: That is promising. *heh* I could make it my "hello world" in Clojure.

19:26 Looking at the allegro implementation it doesn't look too hard.

19:35 arbscht: I am not sure you are right. The function swank:eval-and-grab-output is implemented in swank.lisp, not in one of the implementation-dependent files.

19:35 But then, I guess a lot more would be done in swank-clojure.

19:35 (than if it was a CL implemantation.)

19:47 arbscht: rukubites: swank-clojure does not use swank.lisp. slime's implementation-specific arrangement only applies to CL

19:58 rukubites: arbscht: Yes, I came to that conclusion too, you're right, of course.

20:13 anyn: What is "AOT"?

20:14 ahead of time, got it

20:15 and it's purpose for clojure?

20:15 I'm guessing that would allow clojure to work on the android platform, right?

20:16 Chouser: anyn: AOT compilation would allow you to produce .class files, rather than just a running program, from .clj files.

20:16 anyn: right, android

20:16 anyn: right, deploy to jvm without the clojure.jar

20:16 right?

20:16 Chouser: also, delivering a clojure app with no Compiler or ASM libs.

20:16 anyn: right

20:17 Chouser: well, you'd still need the runtime classes from clojure.jar. The data structures and such.

20:17 anyn: which would be pretty sweet

20:17 Chouser: but it'd still be fair bit smaller than the current clojure.jar, which may help for mobile phones and such

20:17 anyn: does the jre come with a jit compiler anyway?

20:18 jre comes with hotspot, doesn't it

20:18 Chouser: also clojure currently uses a custom classloader whch can cause some deployment difficulties in some contexts, like applets.

20:18 anyn: ooooh

20:18 assimilation is key

20:18 Chouser: anyn: I think so, but that's to compile java bytecode to native instructions, right? we'd still want that. :-)

20:19 anyn: oooh

20:26 AWizzArd: shouldn't we be able to get Clojure programs running on mobile phones today?

20:44 pjb3: Is it documented somewhere how you use clojure contrib?

20:45 I assume you just download, make the jar, add it to your claspath

20:45 anyn: AWizzArd: yea, but the android has a stack-based jre... all code has to be precompiled to bytecode

20:46 i mean 'jvm'

20:48 not sure if javaME is compatible.. android is j2StandardEdition

20:48 Chouser: you don't need to make a jar

20:49 just svn-get clojure contrib and add clojure-contrib/src/ to your Java classpath

20:57 pjb3: then how do you load it once it's on your classpath?

20:57 require?

20:59 arohner: pjb3: yes, require or use

20:59 pjb3: (use 'clojure.contrib.sql)

21:00 pjb3: arohner: thanks

21:21 Chouser: pjb3: best is to use the ns macro, like (ns pjb3 (:require [clojure.contrib.sql :as sql]))

21:21 pjb3: Chouser: so what does that mean?

21:22 I would call pjb3/whatever

21:22 if whatever is a function in clojure.contrib.sql

21:23 Chouser: do that at the top of your file (or whenever in the repl) and you can call sql functions list (sql/with-connection ...)

21:23 s/list/like/

21:24 pjb3: what's the purpose of (ns pjb3 ?

21:24 Chouser: at the repl I usually say (ns user ...)

21:24 that's your own namespace, so new thing you define go there and won't conflict with anybody else's.

21:25 pjb3: why not do (require [clojure.contrib.sql :as sql])

21:25 Chouser: that's okay, though you have to quote the vector

21:26 if you're putting it in a file, though, using a single ns call at the top is idiomatic.

21:27 pjb3: sure, because that defines and sets the namespace, right?

21:33 Chouser: yep

22:04 AWizzArd: How are lists implemented in Clojure? Can concat add in constant time to the end of a list?

22:04 arohner: I think conj adds in constant time to the beginning

22:04 Chouser: AWizzArd: how would that be possible without mutation?

22:06 AWizzArd: Rich explained he used these crazy data structures that allow magic things. One can cons and conj stuff to huge sequences and Clojure does not need to make a full copy.

22:07 Chouser: :-) ok, good point.

22:07 arohner: right, so if I have the list a -> b -> c, you can make d -> a -> b -> c without modifying the original list

22:08 AWizzArd: arohner: it is unfortunately a bit more complex... all other vars that have a reference to that list must not see my change.

22:08 Chouser: I'm pretty sure the PersistentList is just a plain ol' singly-linked list. So no, concat would be linear time on one of the lists.

22:08 arohner: but if you want a -> b -> c -> d, you now have to modify the c cell

22:08 Chouser: AWizzArd: nope, arohner's right.

22:09 duck1123: don't vectors add to the end of the list though

22:09 arohner: duck1123: yes, vectors do

22:09 as a singlely linked list, 'a' has no idea that 'd' is pointing at it

22:09 AWizzArd: right, I agree

22:10 Chouser: anybody that had a ref to "a" keeps that, while anybody that added "d" (or anything else) sees their own addition plus the old list.

22:10 AWizzArd: but I don't know *if* it is a plain old linked list

22:10 Chouser: I'm pretty sure it is.

22:10 AWizzArd: If that is true and we have a list with, say, 2gb of data then consing 1 byte in front of it will result in a copying session of the 2 gigs.

22:11 maybe Rich was talking about hash tables then, where he implemented this magic stuff

22:11 arohner: PersistentList(IPersistentMap meta, Object _first, IPersistentList _rest, int _count){

22:11 super(meta);

22:11 this._first = _first;

22:11 this._rest = _rest;

22:11 this._count = _count;

22:11 }

22:11 Chouser: no, consing 1 byte on the front copies nothing. Trying to add something on the tail would require a full copy.

22:11 AWizzArd: Chouser: yes, that's what I meant

22:12 Chouser: AWizzArd: oh, sorry, I get head/tail mixed up pretty often.

22:12 So yes, if you want to cons one thing on the right-hand side, use a PersistentVector, where there's magic to keep it cheap.

22:12 AWizzArd: from this video it sounded as if he can add stuff to a map (= hash table) and need not to copy it if other vars have a reference to it

22:12 duck1123: what if you do something with lazy-cons, would that avoid making copies?

22:13 or is that all the same if you're putting it on the end

22:13 AWizzArd: And he was talking about having no cons cells anymore. So I thought lists are implemented in some other datastructure that will not always need to be copied.

22:14 arohner: I think that meant that the "cons interface" is abstracted away

22:14 Chouser: duck1123: no, you're onto something there. lazy-cat for example.

22:14 arohner: as a user, you deal with lists, vectors etc, not cons cells

22:15 AWizzArd: right

22:15 he probably just meant this abstract thinking about what lists are

22:15 Chouser: lists are cheap to add to one end, vector to add to the other.

22:15 arohner: and as we pointed out earlier, when you use lists efficiently, they don't have to always be copied

22:15 AWizzArd: from the posted code it looks though that it just is a linked list

22:15 Chouser: vectors allow "changes" anywhere in the middle, as do maps.

22:16 AWizzArd: Chouser: but how can that be done without copying?

22:16 Chouser: AWizzArd: for vectors and hash-maps?

22:16 AWizzArd: for vectors

22:17 adding something anywhere would need a fresh copy

22:17 of the full vector, no?

22:17 Chouser: vectors are not linked lists, they're a sort of tree, and when you make a "change", only a single path thru the tree needs to be copied, so much cheaper than copying the whole thing.

22:18 AWizzArd: okay, so not one-dimensional arrays?

22:18 Chouser: no, they're clever, magic little critters, not an array.

22:18 AWizzArd: this of course costs more for accessing elements

22:19 Chouser: yes, but still practically constant time

22:19 AWizzArd: So we have no arrays in Clojure?

22:19 Chouser: you can access Java arrays if you really want to.

22:19 AWizzArd: and those are "real arrays" then I guess?

22:19 Or has sun also banned them? ;-)

22:20 Chouser: yep. mutable, fixed length (I think), constant-time read and write, Arrays.

22:21 AWizzArd: Back in the 80ies we did not have all this stylish tree stuff on the C64. Plain arrays were cutting edge.

22:21 Chouser: :-)

22:21 AWizzArd: what kind of tree is it that Clojure uses under the hood for vectors?

22:22 Chouser: vectors and hashes have a similar implementation. There are a couple screencasts on "data structures" that I think contain some details.

22:23 watch those and read the code, and you'll be all set.

22:23 AWizzArd: okay, that was the video I didn't see so far

22:23 Chouser: Porting them to another language is optional, but very helpful.

22:23 :-)

22:23 AWizzArd: long discussion, and I am all the time talking about lists with usually +/- 5 elements *g*

22:24 I should not care much if I have to reverse it or add to the end

22:24 Chouser: :-) yep. Vectors of < 32 elements just copy the whole thing on any change.

22:24 nice fast blit, I would assume.

22:25 don't use reverse though, just use a vector. they work great.

22:25 AWizzArd: I need a list at the end - it's code that I generate

22:26 Chouser: a seq over the vector's not good enough?

22:27 AWizzArd: But is it not the same to reverse a list vs reverse a vector and then seq it?

22:29 Chouser: since conj'ing onto a vector puts things in the opposite order, you probably won't need to reverse it at all.

22:30 the seq on it still walks the right direction though.

22:31 (reverse (apply conj '() (range 5)))

22:31 (seq (apply conj [] (range 5)))

22:32 both produce (0 1 2 3 4), but the first creates a list and then copies tho whole thing (via reverse)

22:32 AWizzArd: in principle seq and reverse should have +/- the same efficiency... we need to run through the whole collection anyway

22:33 (into [] (range 5))

22:33 Chouser: reverse keeps the whole copy in memory, seq does not.

22:34 when you're talking about 5 or 10 items, the efficiency differences don't matter much. But using list and reverse is not idiomatic when vector would work.

22:35 AWizzArd: although consing up a list should be more efficient in general than inserting into a tree

22:36 otherwise we could do everything with a vector and always seq it in the end, if we really need a list

22:38 and one thing that sounds really strange is this: http://clojure.org/data_structures#toc53

22:39 "nth also works for Java arrays, and, in O(n) time, for sequences."

22:39 nevermind, I misread that *sigh*

22:47 rukubites: Somewhere above you guys implied that you can't compile clojure to .class files. I thought Clojure was further along than that. :-(

22:49 Chouser: why do you want .class files?

22:50 arohner: rukubites: rhickey is currently working on compiling to .class files

22:50 AWizzArd: you should ask yourself if you really need .class files in the coming few months... if this is critical then Clojure is not yet for you

22:51 but if you think that your life does not depend on it, then you shouldn't worry, as this will come

22:52 rukubites: Chouser: so I can write in Clojure and users of my software don't care that the source code is clojure.

22:53 I actually did some reasonably major work with ABCL to try to get something like that happening.

22:53 Chouser: they have no need to care. You can put everything you need into a .jar and deploy it.

22:53 rukubites: Libraries...

22:53 Chouser: you mean to provide a library, or to use one?

22:53 rukubites: Provide, of course.

22:54 Chouser: you can use gen-class to provide a .class file that turns around and calls clojure fns for all methods (and constructor, etc.)

22:56 rukubites: I guess that may well be good enough. I guess the same issue exists with Common Lisp, the only flavour that can compile down to a .so/.dll library is theoretically ECL.

22:57 Chouser: rhickey has already demonstrated producing .class files is possible, but he's still working out all the details. It'll come, and gen-class features will probably be rolled into it.

22:58 rukubites: Chouser, that does sound cool. :-)

23:00 Chouser: one of the nice things about gen-class (compared to regular java) is that you get clojure features on your class -- swap out method implementations at runtime and transaction aware object state changes.

23:15 AWizzArd: Chouser: woohoo, I have currying ready :-)

23:35 sohail: AWizzArd, you there?

23:35 AWizzArd: yes

23:35 sohail: ok so I saw the discussion

23:35 about :Shape + struct

23:36 AWizzArd: this discussion that followed was mostly for this other guy, as he didn't understand the difference between maps and structure maps

23:36 sohail: I see

23:36 AWizzArd: But is this example as it is written on the website 100% clear?

23:37 sohail: yes definitely

23:37 I was just trying to map the example to CLOS

23:37 but it seems the two don't quite map

23:37 which is unfortunate

23:38 AWizzArd: let's see

23:38 I think you can do it very much the same in clos

23:39 rukubites: I have a question that might be meaningless, but I'll give it a shot: Why make a distinction between let and with-local-vars?

23:40 AWizzArd: rukubites: Add (binding ...) to the discussion as well :-)

23:40 sohail: well for CLOS, I would have done (defclass shape ()) (defclass rectangle (shape) (<slot-defns>)) (defmethod area ((r rectangle)) ... )

23:40 AWizzArd: sohail: looks good

23:40 sohail: and then (make-instance 'rectangle :width w :height h)

23:40 rukubites: No I understand binding, I think. binding locally sets what in CL would be a special variable.

23:41 sohail: but for clojure, seems I gotta do the equivalent of (make-instance 'rectangle :width w :height h :metaclass (find-class 'rectangle)) (I made up everything after :height)

23:41 AWizzArd: rukubites: what is the difference between let and binding? Replace binding in this example with let: http://clojure.org/vars#toc1

23:41 walters: let is lexical, binding is dynamic

23:41 rukubites: I wasn't asking about binding...

23:42 I was asking about with-local-vars.

23:42 Is it that let interns variables?

23:42 AWizzArd: rukubites: but _I_ am asking about binding

23:42 sohail: just seems to me that clojure doesn't exactly have an object system

23:42 which is fine, I just need to get used to it

23:42 AWizzArd: sohail: that's correct. No OOP - it's a lucky day!

23:42 rukubites: AWizzArd: Wow you hijacked my question nicely then:

23:42 AWizzArd: ;-)

23:43 sohail: it's lucky as long as I don't write more or make code more buggy, but in this case, it seems I do

23:43 * AWizzArd is a free-rider

23:43 sohail: I think clojure will eventually end up having an object system layered over it

23:43 * sohail closes prediction window (one a day)

23:44 AWizzArd: sohail: you can build an object system anytime yourself..

23:44 you could implement clos in Clojure if you wanted

23:44 sohail: AWizzArd, ya... except it'll be slow as hell!

23:44 AWizzArd: I just see nothing which would be made easier by having an object system

23:44 we want to go away from that (oop that is)

23:46 walters: so if I shadow bindings with let then those variables will not change globally for the thread in which the let is running in, but with binding this would be the case?

23:46 sohail: AWizzArd, maybe

23:46 I just don't see how making the usage of multiple-dispatch MORE buggy helps though

23:46 arbscht: I've missed CLOS little in the time I've used clojure, but I don't try to write CL in clojure

23:46 sohail: arbscht, that's what I was looking for

23:47 rukubites: CLOS can be quite evil. People tend to use it when they should be using generic tools and passed functions.

23:48 AWizzArd: sohail: in what aspect did Clojure make the use of multiple dispatch more buggy?

23:48 rukubites: I prefer polymorphism by passing functions as parameters.

23:48 sohail: AWizzArd, the example I gave earlier

23:48 someone could just do {:Shape :Circle :width w :height w}

23:48 it doesn't help that clojure says nothing

23:48 rukubites: The above is a map?

23:48 AWizzArd: yes

23:48 sohail: that's the multiple dispatch example, yeah

23:49 AWizzArd: but what is the problem with it?

23:49 sohail: a circle doesn't have a width and a height?

23:49 rukubites: Yes it does

23:49 sohail: uh.

23:49 what?

23:50 in the example it sure didn't

23:50 arbscht: not if it's defined otherwise, say by radius. that's an arbitrary coincidence

23:50 right

23:50 sohail: yeah I mean seriously, talk about missing the forest

23:50 rukubites: SOrry, I was talking about circles, not the example. n/m.

23:51 AWizzArd: sohail: so you complain that someone could just build up his own map, without using the constructor functions provided and then call circle methods for things that are not really circles?

23:51 sohail: and iirc, an ellipse is defined using eccentricity

23:51 AWizzArd, pretty much, yeah

23:51 AWizzArd: this would give a run time error but could in principle be caught by the compiler

23:51 sohail: not really complaining, but pointing out

23:52 arbscht: how can the compiler be sure? generalized multimethods don't just dispatch on 'type'

23:52 AWizzArd: well, sohail knew it

23:53 so there exists a way to reason about code and come to this conclusion.. a compiler could in principle do anything a human can also know about code

23:53 sohail: arbscht, I guess what I am saying is totally separate from multi methods

23:53 i.e., I still have to get used to it ;-)

23:54 I mean to be honest, I use dictionaries quite liberally in Python but I find it quite annoying if it is done all over the place.

23:55 AWizzArd: sohail: you complain that there exists ways to cause runtime errors

23:55 this is well possible in Clojure, CL and Python

23:55 sohail: I point out that it doesn't need to be so seat-of-your-pants!

23:55 rukubites: I think that if objects are really just maps with no higher-level structures, they will be open to abuse. But this is (a) lisp, not a baby language.

23:56 * sohail goes back to the baby language

23:56 AWizzArd: have fun

23:56 sohail: I'm kidding

23:56 geez

23:56 rukubites: :-D

23:56 arbscht: I'm not convinced that encoding rules around your objects in functions is necessarily more prone to bugs

23:56 AWizzArd: well, it's a legitimit descision to not code in Clojure

23:57 sohail: all you need is some real smug weenies in here and your transformation to a lisp is complete

23:57 (again, kidding)

23:57 arbscht, you mean less prone?

23:57 or do you mean manually doing it in every function that manipulates said objects?

23:57 s/manipulates/uses/

23:57 arbscht: sohail: no, more prone. (defn rect ..) versus default values in CL-style struct

23:58 rukubites: *heh* a colleague of mine runs the blog smug lisp weenie.

23:58 sohail: rukubites, tilton?

23:58 AWizzArd: is (format ..) the best way to make a string out of a symbol?

23:58 rukubites: Yep

23:58 sohail: arbscht, sure, but that is how CL started isn't it

23:59 i.e., defstruct generated a bunch of functions

23:59 then people were like, "wtf this is silly" -> CLOS

23:59 * sohail does not know

Logging service provided by n01se.net