#clojure logs

2008-10-06

01:23sawjigdoes gensyms protect from all potential evil of macros?
01:23sawjiglike shadowing other variables and such?
01:24sawjigalso, where can i find the source code for "builtin" macros like when and when-not?
01:25blackdogboot.clj for your second question
01:28sawjigty
01:57sawjigis the use of backquoe discouraged in clojure? i see in boot hickey uses (list form) a lot, not graham-style macros
02:29Lau_of_DKMorning gents
02:29Lau_of_DKCan somebody direct me to the simplest approach to making an executable .jar file with Clojure code in it?
02:59yangsxH4ns: can you send manual.pdf to me? I'm unable to download any files from the clojure group :)
03:24Lau_of_DKblackdog down, you in ?
03:25sawjigis there no string-libraries in clojure?
03:26sawjigif wanting to work with strings, what is the best way?
03:27sawjigand how do i set default indent to 4 chars?
03:28Lau_of_DKCant you use Javas stringmanipulation routines?
03:37sawjighow can i do multiple-value-bind?
03:38Lau_of_DKcan you give an example of what youre trying to accomplish? mvb doesn't ring any bells with me
03:45sawjiguser=> (def spam #{:egg 12, :ham 4}) #'user/spam user=> spam
03:45sawjig#{4 :egg 12 :ham}
03:45sawjiguser=>
03:45sawjigwhen i do (get spam egg) i get an error
03:46sawjig(get spam :eqq) returns :egg not the value
03:52sawjignoone used Maps?
03:54Lau_of_DKuser=> (def spam (hash-map :egg 12 :ham 4))
03:54Lau_of_DK#'user/spam
03:54Lau_of_DKuser=> (get spam :egg)
03:54Lau_of_DK12
03:54Lau_of_DK#{} gives you a HashSET and not a map
04:00Lau_of_DKYou can check your constructs with (class spam), which would tell you its a persistantHashSet
04:22sawjighttp://hpaste.org/10933
04:22Lau_of_DKHas anybody here got an idea of how to implement a ListSelectionEvent ?
04:23sawjigwhy is splitall not splitting more than once? try (splitall "hellola" \l)
04:26Lau_of_DKI think you need to place (recur) within a loop or for statement
04:29Lau_of_DK(nevermind about the listener)
04:46sawjighttp://hpaste.org/10934
04:46sawjigstill not working
04:57sawjigi thought clojure supported polymorphism, why not + for cons?
05:00sawjigi am trying to add some stuff in boot.clj, do i ahve to recompile it then? because after i have done so i cant use it in the repl
05:01sawjigor i ahve to add it in some other file too?
05:37leafwsawjig: use user.clj
05:53sawjigleafw: where is user.clj? cant find it in src and not src/jvm
06:21leafwsawjig: you create it. And put it in whatever you want. Place it in the instantiation directory.
06:22leafws/it in /in it/
06:22Lau_of_DKCan someone here point me to some info that will let me create an executable .jar file with clojure code in it ?
06:31Lau_of_DKCan someone here point me to some info that will let me create an executable .jar file with clojure code in it ?
06:33sawjigis the instantiation dir /src or just /clojure?. clojure.jar is in /clojure but boot is in /src
06:36sawjigdont i have to point something to this file? or is user.clj looked for by the interpreter automatically?
06:36sawjigah wow it worked
06:37sawjigi put it in /clojure
06:38hoecksawjig: it must be somewhere in the classpath
06:40leafwLau_of_DK: user jar cf MyThing.jar my_script.clj MyMainClass.java , where the main class launches an interpreter that reads the clojure scripts included in it.
07:32Lau_of_DKIm not getting the .jar setup, rhickey, is there a place where I can put my main .clj in clojure.jar to make that file executable so that it fires up my program ?
07:43sawjig http://hpaste.org/10941
07:44sawjighow do i do if i want python-like ifs?
07:44sawjiglike if his is true do that and have several ina row
07:44sawjigwhen doesnt help here, i dont want to nest
07:46rhickeysawjig: are your tests exclusive, or do you want them all to run?
07:46sawjigi want all to run
07:46rhickeyand if they pass you want a side-effect?
07:48Lau_of_DKrhickey, did you catch my question about .jar?
07:48rhickeyLau_of_DK: user.clj will be loaded by default
07:49sawjiguser.clj is very nice, i like how to open and hackable clojure is.
07:49sawjigrhickey: yes i want a sideeffect then
07:49sawjigi mean i could to this, but not in a clean way
07:50sawjigif could nest a hwole bunch of ifs i guess
07:50sawjigbut thats not very clean
07:51rhickeysawjig: http://groups.google.com/group/clojure/msg/f7a1b33e2886008c
07:55sawjigthanks rick
07:57sawjigcould you perhaps have a quick look at http://hpaste.org/10943 and tell me why splitAll doesnt work?
07:59rhickeywhat is it supposed to do?
07:59rhickeyat first glance I can say if you are using reverse you are probably not leveraging Clojure's data structures
08:02rhickeythere's only one call to reverse in boot.clj and it's not to fix up a recursive return value
08:03rhickeyalso please paste for this channel here:
08:03rhickeylisppaste8: url
08:03lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
08:12lisppaste8qwer pasted "tiest" at http://paste.lisp.org/display/68037
08:12sawjig^^
08:32lisppaste8hoeck annotated #68037 with "split" at http://paste.lisp.org/display/68037#1
08:42Lau_of_DKrhickey, practically speaking, how do I add my user.clj to the clojure.jar file ?
08:56Lau_of_DKisnt there a flat-map or flatten function in clojure ?
08:58sawjigisnt (defn f [& x]...) meaning optional params?
08:58sawjigor it is multiple?
08:59cemerickLau_of_DK: try mapcat
08:59Lau_of_DKcemerick , thanks
08:59cemericksawjig: there are no optional params, & x indicates rest parameters, and the name that the rest of the parameters are bound to within the fn
09:00Lau_of_DKcemerick , mapcat did the exact trick, thanks alot
09:00cemerickLau_of_DK: np
09:36rhickeyok - maps are now Maps
09:37drewrAwesome!
09:37drewrThat's going to greatly simplify some serialization code I've written.
09:38rhickeyit was a pretty extensive change, so let me know if you encounter any glitches
09:38drewrWill do.
09:41sawjigcan i raise an error somehow? define my own?
09:41drewrsawjig: (throw (Exception. "msg"))
09:41drewrYou can subclass java.lang.Exception too, of course.
09:53Chouserclojurescript/avoid-java-in-boot.patch is now updated to work with the latest clojure svn
09:54rhickeyChouser: ok - that was fast!
09:54Chouser:-) git auto-merges pretty well.
10:06sawjigwhat is the point with conj? isnt it just (conj b a) instead of (cons ab) ?
10:07sawjigcan i cons to the end of a list somehow?
10:07Chouserconj is polymorphic -- when used on a vector, it adds on the end.
10:07Chouserwhen used on a list, it's just like cons
10:08Chouseryou can also use conj on sets and hashes
10:09Chouserhttp://clojure.org/data_structures click on "Collections" in the table of contents
10:09sawjigok cool
10:09sawjighickey said before he only used reverse once in the implementation of clojure. but i find myself needing to reverse a lot when using recursion
10:09sawjigis that bad technique then or is there some way to cons to the end?
10:10rhickeysawjig: if you use vectors your data will be in the right order
10:10Chouserif you're using lists and reverse a lot, there's a good chance you can use vectors and not need to reverse -- will be faster and less code
10:19sawjigwell im working on lists and strings and need to return the same type that was passed...
10:21ChouserI hardly ever use lists in clojure. are you sure you need to?
10:21Chousereven so, you could build a vector while recursing and convert to a list (or seq) before returning it.
10:42sawjigdoes that create the same performance-penalty?
10:42sawjigas reversing
10:44lisppaste8sawjig pasted "reversing" at http://paste.lisp.org/display/68046
10:45sawjigsome examples ^^ using reverse
10:46drewrWhat's tl?
10:46cemericksawjig: no -- creating a seq from a vector is essentially free, whereas reversing a list is O(n)
10:48sawjigtl=tail=first,hd=head=rest
10:48sawjigcemerick: ok thanks ill use that instead then
10:49drewrsawjig: Yeah, but what is the symbol "tl" in your code mean?
10:49drewrDid you redefine rest?
10:50sawjigit means rest
10:50sawjigi defined it in user.clj
10:50sawjigbecause i hate writing long names...
10:50sawjig(defn tl [xs] (rest xs))
10:50drewrOK.
10:50drewrI would use idiomatic Clojure instead though.
10:51sawjigyes renamed it, rest is still there. i know some might hate that but i like them to have equal length(liens up nicely) and be short sinc eu use them so much
10:51H4nsvery hard to get code reviewed which uses a different vocabulary.
10:51ChouserI pretty rarely use first or rest, either. Between destructuring and high-order functions, I rarely need to type out "first" and "rest"
10:51sawjigyes true
10:52sawjigok illkeep thta in mind, im a lisp-noob so i prob write some primitive and dumb stuff
10:52H4nssawjig: first off, do not redefine the vocabulary. get an autocompleting editor if you hate typing things too often
10:53drewrsawjig: Read boot.clj.
10:53Chousersawjig: no worries -- people around here are generally quite willing to help if you're willing to learn.
10:53H4nssawjig: second: don't try to optimize until you know what you need to optimize
10:53cemericksawjig: it's just a matter of learning the idioms -- not really a question of dumb or primitive
10:55abrooks_Hrm. 63 of the files in Subversion have *nix (LF) style EOL, 52 have DOS (CRLF) style EOL. I noticed this while looking at the recent rev 1052 diff which spans a lot of files.
10:56abrooks_We should probably set svn:eol-style native on all the source files.
10:57Chousersawjig: drop-last is already in boot.clj -- doesn't it complain when you try to def it?
10:58Chouseranyway, you might want to look it up in boot.clj; it doesn't use reverse
11:03sawjigdrop-last isnt in boot clj but i have clojure_20080612, has it been added lately? i downloaded some time ago but havent played with it until now
11:04sawjigH4ns, i can add auto-completing in emacs right?
11:05H4nssawjig: yes - M-/ completes something that you typed, considering all currently loaded buffers. that is enough for me, but you can allso set up explicit completion dictionaries. never did that.
11:13Chousersawjig: latest release is 20080916 or you can use svn
11:17tom`hi all, I'm trying to get clojure working with slime, but I keep getting NoClassDefFoundError
11:18drewrtom`: While doing what?
11:18tom`swank-clojure-jar-path is set to the location of clojure.jar
11:18tom`starting slime (M-x slime)
11:18H4nslisppaste8: url
11:18lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
11:18tom`I can paste-bin the inferior lisp output if it'llhelp
11:19drewrtom`: If you start slime with M-- M-x slime, can you choose clojure as your dialect?
11:19lisppaste8H4ns pasted "Clojure related section from my .emacs" at http://paste.lisp.org/display/68049
11:20sawjighowdo i turn [(\h \e \l \l) (\o \space \t \h \e \r \e)] back into a string?
11:20lisppaste8tom pasted "problem starting slime, *inferior-lisp* output" at http://paste.lisp.org/display/68050
11:20H4nstom`: that, with path strings tweaked to suit, works for me on windows, macos, freebsd
11:20lisppaste8drewr pasted "My SLIME config" at http://paste.lisp.org/display/68051
11:20Chousersawjig: (map str thing)
11:20H4nstom`: with swank-clojure from git, cvs slime and svn clojure
11:21tom`H4ns: I'm using all those, clojure starts fine when I run it from shell
11:21tom`I'm on Ubuntu if that makes any difference
11:21Chousersawjig: oh, or maybe (map #(apply str %) thing)
11:22H4nstom`: from looking at the error message, i'd say the path to your clojure.jar is not correct
11:22tom`drewr: Yes, it's the only option right now
11:22H4nstom`: i'm using swank-clojure-binary because i have some additional classpath settings to make and want to use the same settings on the shell and with slime.
11:22tom`H4ns: I've verified that is correct (and fully expanded using expand-file-name)
11:23tom`will try swank-clojure-binary
11:24drewrtom`: I use a custom version of http://github.com/jochu/clojure-extra/tree/master/sh-script/clojure.
11:25sawjigin cl i cn do (reduce '* '(1 2 3)) -> 6, can i do something like that in clojure instead of suing (fn[...)
11:25tom`I've just set it to a sh script containing "java -cp clojure.jar clojure.lang.Repl src/clj/clojure/boot.clj" which is the line I use to boot it from the command line
11:25drewrsawjig: user> (reduce * [1 2 3])
11:25drewr6
11:25sawjigok but on a list?
11:25drewruser> (reduce * '(1 2 3))
11:25drewr6
11:26sawjighey wtf i thought i tried that lol
11:26drewrClojure's a lisp-1, so you don't have to quote the function.
11:26tom`ok, I set swank-clojure-binary to that script but I still get the exact same error which seems a bit odd. Do I have to do anything specialto make it use swank-clojure-binary
11:27drewrtom`: OK, that's fine. Do you change to the clojure directory before that command?
11:27tom`drewr: good point, that'll be it won't it. Let me just go fix that
11:28drewrcd /path/to/clojure && exec java -cp ...
11:29H4nsi'd rather use an absolute path for the jar and let clojure start in whatever directory i'm currently set to in emacs.
11:29sawjigdrewr: is there scanl (=scanleft = reduce and return all the intermediate values)
11:30drewrH4ns: I would too.
11:31drewrsawjig: Like Haskell's? http://www.zvon.org/other/haskell/Outputprelude/scanl_f.html
11:31sawjigyes like haskells
11:32sawjigi wrote it,poste d before, just wondering if it wad there already, scan/dorun does soemthing else
11:32drewrI'm no functional prog expert. How is scanl different from map?
11:33tom`I switched to using the clojure startup script from the coljure-extra git
11:34tom`I can now run it using ~/clojure/clojure from any directory and it works fine
11:34tom`but I still get the same error in slime :(
11:34drewrC-h v swank-clojure-binary
11:35H4nstom`: are you sure that your script is executed when you start slime in emacs? did you restart emacs?
11:35sawjig(drewr: scanl is reduce and all the intermediate values
11:35sawjigso (scanl + 0 '(1 2 3 4)) -> (1 3 6 10) or (0 1 3 6 10)
11:36drewrOoh, this is cool: http://www.haskell.org/hoogle/?hoogle=scanl.
11:36tom`H4ns: will try retstarting emacs now, I was just shutting down slime then reloading
11:36drewrWe need a Cloogle!!
11:36tom`back in sec (accessing irc via emacs)
11:36sawjighow do i convert from vector to list?
11:37drewrsawjig: (apply list [1 2 3])
11:38H4nstom`: works now?
11:38tom`yep, restarting emacs did it
11:38tom`thanks for the help
11:38H4nstom`: good. i spent the last 10 days wrestling with these kinds of issues, so i can feel the pain :)
11:38tom`bloody computers :p
11:39drewrBurn the lot of 'em!
11:40tom`how have you guys found the slime support in Clojure? I'm looking into it as a possible alternative to CL for a new project and slime is one of the most important factors (it's going to involve lots of exploratory programming)
11:41H4nstom`: it works, but it is not as mature as cl support. i find it not so useful to explore whatever the platform provides, but that may not be an issue for you
11:41H4nstom`: a real down side is the lack of support for *1, *2, *3
11:42blackdognew versions of clojure do havethat
11:42blackdog*1 etc
11:42H4nsblackdog: it is slime that does not have it, i think.
11:42blackdogah ok
11:43tom`thanks, I'll carry on trying it out
11:44H4nsi'm not sure if M-. is supposed to work. i'm not at the point where i would miss it, but soon will be
11:44tom`I do like the look of Coljure, my biggest complaint about CL is that it's not enough of a functional style language
11:45sawjighow do i convert [ 1 2 3] to (1 2 3) and (\h \e \ l \l \o) to "hello" ?
11:47blackdog(apply str `(\h \e))
11:49drewrtom`: I think if you don't have much history with CL, then going with Clojure is a no-brainer.
11:50drewrIf I was really productive in CL it would have been a much harder switch for me.
11:50drewrI'm your typical Lisper that ends up reaching for Python when he needs to get things done, but with Clojure I find I don't have to do that.
11:50sawjighow do i backquote on windows?
11:51alectom`: Clojure and SLIME have worked well for me coming from a CL environment. It's not perfect, but it's good enough, and the swank-clojure maintainer is *extremely* responsive and helpful.
11:51drewrsawjig: What do you mean? Entering the backquote character?
11:52sawjigyes
11:52sawjig`
11:52sawjigah
11:52drewrWhat's wrong with Windows?
11:52sawjigits not linux?
11:53drewr(That was a very contextual question. :-))
11:53sawjigso how do i convert from vector to list?
11:53sawjig(apply list...) doesnt work since list well lists things
11:53danlarkinsawjig: I think drewr means that backquoting on windows is the same as backquoting anywhere else
11:54sawjigwell i found out how
11:54drewrsawjig: I don't know what you mean. (apply list [1 2 3 4]) => (1 2 3 4)
11:54tom`are there any good printable docs? All I can see right now is the wiki
11:55drewrtom`: There's a PDF in the Google Group.
11:56tom`thanks, didn't even know Google Groups had a file section
12:07tom`When I get an error in the slime repl it doesn't let me go into debug or even tell me which file the error is in, am I doing something wrong?
12:13drewrYeah, since SLIME uses the clojure.lang.Repl, I think it can't figure out where the code occurred.
12:13drewrs/code/error/
12:16tom`doesn't that get really impossible? Not having a debugger is one thing, I can live with that, but not even knowing which file the error is in...
12:16sawjigwhy does rest [1 2 3] return the list (2 3) and no the vector [2 3] ?
12:17drewrsawjig: It's not a list. It's a vector that implements ISeq.
12:17drewrThe seq abstraction is the key to much of Clojure.
12:18drewrtom`: Yes, it can get frustrating. That's one of the biggest shortcomings of Clojure right now.
12:18sawjigconj on a vector is O(1) right?
12:18drewrtom`: Although, Java people seem to do just fine with their tricks. I don't share their background.
12:21tom`that is a bit of a pity, I assume that it's quite hard to get that functionality working otherwise it would have already been done
12:21tom`that will probably be the clincher though, I think I'd go mad trying to cope with it
12:22cemerickwhile clojure error reporting isn't the greatest, I've never seen a situation where the stack trace doesn't pass through the offending code's file/line number
12:23sawjig(conj (rest [1 2 3]) 4) -> (4 2 3)
12:23tom`cemerick: I'm not getting a stack trace, is it just because I've got something set up wrong then?
12:24drewrtom`: No, that's not normal. I've found that some errors with swank have stopped producing stack traces. I think it's a bug.
12:24drewrMaybe not with clojure.
12:24cemericktom`: I don't use emacs, but perhaps it's dropping clojure.lang.Repl's stdout/stderr on the floor?
12:25sawjiglet [[h t] (split s delim)], is that patternmatching osmehow?
12:25tom`ok, that's not so bad then, any idea what I might be able to do to fix it?
12:25cemericksawjig: yes, that's destructuring
12:25cemericktom`: not a clue, sorry :-) I know there's some emacs users floating around, though.
12:26tom`I'll try the mailing list
12:30sawjighow can i get the typeof something?
12:30rhickeysawjig: (class x)
12:30sawjiglets say i have a function that takes a string lsit or vector and i want to return the same type that was passed so drop-last "hello" returns "hell" and not (\h \e \l \l)
12:32sawjig(apply (class "hello") '(\h \e)) results ina ne rror though
12:32Chousersawjig: (\h \e) is probably a seq on a String. If you use the java methods of String, you'll get Strings back instead of seqs
12:33rhickeyfor types other than string, (into (empty x) (map f x))
12:33Chouserbut if you don't want to do that, you can use (apply str '(\h \e))
12:33rhickeyfor string, you'll have to apply str to the result
12:34Chouser(class "hello") returns java.lang.String, which is not callable, so that's why it doesn't work with apply.
12:34cemerickrhickey: interface injection would eliminate that divide, yes?
12:35rhickeycemerick: maybe
12:36rhickeythe problem is strings are not a persistent data structure - they are immutable but not persistent
12:36rhickeyapply str uses a StringBuilder internally and is fast and efficient
12:37rhickeybut treating strings like IPersistentCollections would have to full copy on write
12:38cemerickI've been working on digesting some of the "results" from the JVM summit of late.... :-)
12:39lisppaste8sawjig annotated #68046 with "scanl apply class" at http://paste.lisp.org/display/68046#1
12:40sawjig^^ (apply (class x) y) doesnt work though if y is a vector and x is a list
12:41rhickeysawjig: classes are not functions
12:42sawjigso how could i do what want without cheecking a whole lot of cases?
12:48lisppaste8Chouser annotated #68046 with "scanl via reduce?" at http://paste.lisp.org/display/68046#2
12:48sawjigand can i define + for strings?
12:51sawjigcool but now it still returns a list
12:52sawjigclass clojure.lang.APersistentVector$Seq
12:52Chouserit returns a seq on a vector
12:52Chouserright
12:52Chouserhow is that bad?
12:52sawjigactually but i cant conj to the end of it
12:53sawjig(conk (1 2 3) 4) -> (4 1 2 3) instead of (1 2 3 4)
12:53sawjigconj ^^
12:53Chouserright, you'd need a vector to conj on the end. Simplest is to wrap in vec: (vec (scanl ...))
12:54Chouserthat's not the fastest, though, since it's building up a vector internally. You'd just have to rewrite it so it doesn't have the extra leading value (which I skipped using "rest")
12:54sawjigbut why cant i have it return a vectoe if pass a vector?
12:55Chouseryou can
12:55sawjigand i cant do (apply (class x) y) so i have t check if class x = someclass apply someclass y
12:55Chouserwhy do you keep trying to call a class?
12:56ChouserWhat do you expect it do to? Do you want (into (empty x) y) or something?
13:00sawjigif i do (scanl + 0 [1 2 3]) i want [1 3 6] back if i do (scanl + 0 '(1 2 3)) i want (1 3 6)
13:01sawjigah yes into works
13:02sawjigoh well if i conjs to a list it get sreversed so it doesnt worka y way
13:03Chouserof course conjing onto a list reverses it, that's the direction that lists grow. If you didn't want it reversed, wouldn't you use a vector?
13:03kotarakHmmm... What is the Sequential interface for?
13:03Chouserconjing onto a set puts things in random order. These are the features of the data strctures you're using.
13:05sawjigyes i know, im just thinking about a way to get what i want
13:05Chouserkotarak: http://clojure.googlegroups.com/web/chart.png
13:06Chouserkotarak: I think it just indicates if a collection is going to retain its order (like a vector) vs. not (like a set)
13:07lisppaste8rhickey annotated #68046 with "lazy scanl" at http://paste.lisp.org/display/68046#3
13:08kotarakChouser: well, yes. I know this chart. But what is Sequential for? It's empty. I would expect seq() there (which is my understanding of "seq"uential). And an ISeq is not Sequential? I suspect a deep misunderstanding of ISeq on my side.... :(
13:10Chouserkotarak: well, there are things for which seq work that are not themselves sequential (like sets and maps)
13:10rhickeykotarak: it is a marker interface, all implementors indicate they are essentially sequential - i.e. lists, vectors, seqs
13:10ChouserBut I am surprised ISeq is not Sequential, nor is IndexedSeq
13:11rhickeyChouser: they could be, all implementations of them are
13:11Chouseroh, IndexedSeq is just an interface, I see.
13:13kotarakOk. A set is not Sequential, but a seq of a set is. When all seqs are Sequential, why is then ISeq not?
13:14Chouserkotarak: as rhickey just said, it could be -- all the classes that actually implement ISeq also implement Sequential.
13:14kotarakJust asking, because it caught be surprise.
13:14rhickeykotarak: that shouldn't matter, since you can only ask a concrete thing if it is sequential and they all are
13:14rhickeyso would only be a convenience thing for implementors of ISeq - it has been requested
13:14Chouserhm, there are a lot of nested classes missing from that chart.
13:14kotarakI implemented a class with ISeq and it blew up with nth.
13:15rhickeythere you go :)
13:15rhickeyI'll fix, just a sec
13:15kotarakrhickey: :) geeshh... you are support in its essence. :)
13:17rhickeykotarak: it's up - rev 1053
13:17kotarakrhickey: cool, thanks. :)
13:17rhickeynp
13:18kotarakAre there any plans to migrate other functions as nth, get, etc. to multimethods like pr?
13:19rhickeykotarak: probably not, for perf reasons since they are so primitive
13:19rhickeyalso I don't want the semantics to spiral out of control
13:20rhickeypeople have gotten some really bad habits from monkey patching in other languages I think
13:20kotarakok. Would have been nice. (Did a test balloon with nth and it seemed to work fine, but performance should of course not be sacrifised....)
13:21rhickeyNice Clojure compliment from Cliff Click: http://groups.google.com/group/clojure/msg/241b23524bd585a1
13:22Chouserupdated http://clojure.googlegroups.com/web/chart.png
13:27kotarakOh. Btw, may I vote for gen-class to require the namespace, not the file directly?
13:36scgilardiregarding the idiom "(into (empty x) (map f x))", it works nicely in a lot of cases. One thing to watch out for is when it's applied to a list, the results are in reverse order from the original.
13:38Chousersure, but if you peek and pop, you'll get things in the same order as you put them in, whether it's a list or vector.
13:38pjb3makes sense, assuming it is just conjing each item in the seq into the empty list
13:39scgilardiIf it were abstracted into a function, perhaps subclases of Sequential could use a vector internally and then either return it or convert it to the input type as appropriate.
13:40Chouserbut into also works on sets, sorted maps, hash maps ... I think you have to pick if you want polymorphism or not.
13:40ChouserIf not, say (into [] ...) and get it in the order you want.
13:41scgilardiright, this came up in trying to write a polymorphic version. Whenever order doesn't matter (hash) or enforced by the data structure (sorted) or if it's a vector, the answer is unsurprising.
13:42rhickeyscgilardi: I think no one should be surprised at things getting added to the front of a list - remember into works with a populated target as well
13:45rhickeyso if I poured some more things into a large list I wouldn't expect them to be appended, with all the copying that would entail
13:45scgilardiright, I'm not criticizing into, just noting that when I first saw "(into (empty x) (map f x))" returns its result in the same type of container that it was give, I took it to mean that if "f" were "identity", I would get a result "=" to what was passed. That's almost always true, but not for list. Hence the "something to watch out for".
13:46rhickeyscgilardi: I think it might be interesting to have ctor, like empty, that would return a corresponding contructing fn
13:46rhickeyconstructing
13:47rhickey(apply (ctor x) (map f x))
13:47rhickeyor something
13:47scgilardiah neat, yes that looks like it would work nicely.
13:48rhickey((ctor x) (map f x)) ?
13:49scgilardiright, that would be better I think. ctor takes seq and makes a collection from it.
13:49Lau_of_DKEvening gents
13:49scgilardiHeya, Lau
13:49rhickeyscgilardi: might make a nice multimethod
13:50cemerickFWIW, 'ctor' isn't exactly common verbiage (though I love the idea)
13:50rhickeyname suggestions welcome
13:50Chouser"new"
13:50scgilardihehe
13:51rhickeyChouser: but it returns a fn
13:51Chouserah, good point.
13:52rhickeythe problem with polymorphic new is it has to be reflection based
13:52cemerickinit?
13:52Chouserfoo.constructor returns a function that creates a new instance of foo's class. In JavaScript.
13:53scgilardiyes, "constructor" does have a strong prcedent for this role
13:54scgilardi(ctor is short for constructor in C++ circles)
13:54rhickeywhere I used to hang out, apprently :)
13:54rhickeyapparently
13:54cemerickscgilardi: yeah, I discovered that not too long ago (not ever having been in the C++ pool)
13:55scgilardirhickey: do you recall who wrote the "javadoc" function that (I think) I saw posted here?
13:55rhickeycgrand
13:55cemerickGiven the necessary presence of the constructor notion in Java, I'd say that using "constructor" would be overloading the term too much.
13:55scgilardicgrand: thanks for that. I think it's great. Please consider making it a contrib.
13:56scgilardi"factory" is possible.
13:57cemerickyeah, factory is good
13:58scgilardigotta run. thanks
13:58rhickeybut what if the default _did_ call the constructor (had to force myself to type that out) reflectively
13:59cemerickconstructor isa factory?
13:59Chouserin Javaland, a factory is a static or instance method, completely different from a constructor, right?
14:00cemerickChouser: virtually always static
14:00cemerickA constructor is really just a special method on an instance
14:01dudleyfctor isn't just a C++ term
14:01scgilardiChouser: right, and we're talking about a function here that given an exemplar, returns a new one of those. Hmmm, it's an empty-clone.
14:02scgilardi(ctor x args) could create the object and then call its constructor with the args
14:02rhickeyscgilardi: not really, empty is that, this is a fn that makes an instance given stuff
14:03scgilardi(right
14:03scgilardiso it's a lot like "new", but takes an object instead of a class
14:03drewrChouser: Thanks for the class diagram!
14:03rhickeyI think it could take a class as well
14:03Chouserand returns a function instead of an object
14:04scgilardiright, ok.
14:04Chouserdrewr: :-) sure
14:04scgilardiwhat does javascript call that? they do new by cloning something that exists, don't they?
14:05dudleyfscgilardi: I wish
14:05rhickeythe more primary notion takes a class, as you could build the other from (ctor (class x))
14:06Chouserfunction Foo(){}; foo = new Foo(); foo.constructor == Foo
14:06scgilardibut there's a name for this kind of non-class-based object orientation... it escapes me at the moment.
14:06dudleyfprototype-based
14:06Chouserscgilardi: prototypes, but that's not what this is.
14:06scgilardiok
14:07scgilardithanks for the word. it doesn't have to drive me crazy not knowing it now.
14:08Chouserthat has to do with inheritence, where instead of pointing to a parent class, your derived class points to a prototype -- an instance of the parent.
14:10blackdog"make" ?
14:11scgilardiI think if this new thing takes arguments and calls constructors, ctor or factory work. (ctor (class x)) looks a lot like "new (class x) [args]". As a special form, new could be overloaded to do this. any merit?
14:12Chouserif it's returning a function, "maker" would be more accurate than "make", while if it's actually calling the constructor perhaps "new" could work.
14:12Chouser...although my earlier mention of "new" was definitely meant as a joke!
14:12rhickeynew has to map to actual constructors, and isn't extensible, this is a pseudo ctor - create something from a collection of other things, subject to interpretation as a multimethod
14:13rhickeyI don't want people to start doing a lot of reflective construction
14:14scgilardiwouldn't the target class still need a constructor that accepts "a collection of other things" (in this case) or "other things" in general?
14:14scgilardiin C++ a copy constructor that accepts seq (in this case)
14:14rhickeyscgilardi: all of the Collection classes already do, but if a multimethod you could do whatever you want
14:15Chouseryou could insert a 1-second delay to discourage its over-use
14:15scgilardi:)
14:15rhickeyreflection already does that, no?
14:15Chouserreflection + multimethod gets you close
14:16rhickeythe point of using a multimethod is you could make it fast
14:16rhickeypredefine for all collections and you might not need any others
14:16rhickeystring version could use a StringBuilder internally
15:11lisppaste8gnuvince pasted "Slow string accumulation" at http://paste.lisp.org/display/68062
15:13rhickeygnuvince: see slurp in boot.clj
15:18gnuvincerhickey: (let [u (new URL "http://www.yahoo.com")] (slurp (. u openStream)))?
15:20gnuvinceNo, that doesn't work.
15:21Chousergnuvince: I think he meant you can look at how it builds a string faster.
15:21rhickeygnuvince: I meant look at the source for slurp, slurp doesn't read from urls
15:21gnuvinceOK.
15:25Chousergnuvince: (apply str (line-seq (ds/reader (.openStream (URL. "http://www.yahoo.com")))))
15:26ChouserI got the ds namespace like this: (ns user (:require [clojure.contrib.duck-streams :as ds]))
15:27Chouseroh, you can actually drop the .openStream bit -- ds/reader will do that for you
15:30gnuvinceI must be doing something wrong somewhere, because it takes 8 seconds to fetch 3 comics while my original Python program fetches 20 in 3 seconds
15:31Chouserhuh, you can leave out the URL ctor as well: (apply str (line-seq (ds/reader "http://www.google.com")))
15:32rhickeydon't you want a with-open in there?
15:32Chouseroh, I suppose I do.
15:33Chouser(with-open r (ds/reader "http://www.google.com") (apply str (line-seq r)))
15:34Chousergnuvince: your python wasn't going in parallel or anything, right? :-)
15:34gnuvinceChouser: it was.
15:34Chouseroh, and your clojure is too?
15:34gnuvinceChouser: I'm trying to at least.
15:34gnuvinceCan't say I'm succeeding
15:36Chousergnuvince: you could stick some println's in, like before and after each page is fetched -- ought to be able to see whats in parallel, and perhaps where the delays are.
15:36rhickeyget the with-opens in there or your connections aren't getting closed
15:39gnuvincerhickey: I did.
15:39gnuvinceFollowed the code of slurp almost verbatim.
15:40rhickeyyou aren't doing Chouser's line-seq stuff?
15:40rhickeyapply str wraps all the stringbuilder junk
15:41gnuvinceNo, I don't have the contrib directory.
15:42ChouserUnless you know otherwise, I'd be suspicious of startup time -- some people have reported as much as 4 or 6 seconds in some configurations.
15:42rhickeyeverything except ds/reader is default Clojure, just put your reader there
15:43gnuvinceChouser: doing my testing in the REPL
15:46gnuvinceDo you guys want to see the whole thing? I could be *way* off.
15:50Chousergnuvince: feel free to paste it.
15:51lisppaste8gnuvince pasted "Comic fetcher" at http://paste.lisp.org/display/68064
15:56gnuvinceHow does that look?
15:57scottjIs clojure-contrib included in clojure or do you have to download it separately from its SF page?
15:57abrooksscottj: http://sf.net/projects/clojure-contrib
15:58abrooks(It's separate.)
16:00wwmorgangnuvince: you might get better performance if you use the byte array input stream read methods instead of the single byte method
16:01duck1123_if I have a clojure script in a file that I execute using the shebang trick, does that compile it every time, or is something cached?
16:01Chouseryou want send-off instead of send, since fetch-comic can block.
16:01duck1123_and if the former, can it be compiled for later use?
16:01Chouserduck1123_: compiled every time. There's currently no way to "cache" compiled clojure code.
16:02scottjabrooks: thanks. There are no installation instructions right?
16:02Chouserscottj: just unpack it somewhere and add clojure-contrib/src to your java classpath.
16:02gnuvinceChouser: is an agent the correct type of reference to use?
16:03abrooksscottj: Not that I'm aware of just use ant/mvn the same way you build Clojure and do what Chouser said.
16:03abrooks^of^of --
16:03Chouseryou don't have to build clojure-contrib at all, afaik.
16:04abrooksChouser: Really? Hm. I did.
16:04abrooksI guess you wouldn't have to. I build a jar and point my classpath to that.
16:05abrooksMuch better to point to the live files though...
16:06jaohas clojure an equivalent to scheme's letrec or cl's labels?
16:09Chouserjao: you can put a name a fn so: (fn foo [] ... (foo ...))
16:09Chouserhopefully the clojure makes sense even if my english didn't.
16:10jaoChouser, mutually recursive ones?
16:10Chousergnuvince: yeah, I think an agent is fine
16:10gnuvinceOK
16:10Chouserjao: no, that name is only good inside the fn
16:10gnuvinceAnd I think the reason it is slow is that www.comics.com seems to load *really* slowly on this machine.
16:11Chouserfor mutual recursion, I think you may need (def foo) (defn bar [] ...) (defn foo [] ...)
16:11gnuvinceOn another machine (with a different ISP), the entire source loads instantly
16:11jaoChouser, i see. thanks.
16:12Chousergnuvince: using send instead of send-off means you were using a pool of threads sized based on your number of CPUs.
16:12gnuvinceand with send-off?
16:14kotarakjao: but mutual recursion is not a good idea in Clojure due to the limitations of the JVM concerning TCO.
16:16jaokotarak, which is a pity :)
16:16Chousersend-off gets threads from a pool that grows as needed.
16:16kotarakjao: according to Rich a lot of people complained at the JVM Summit. Maybe there will be some change soon. :)
16:17Chouserkotarak: good point, although using lazy-cons or something similar can still require the (def foo) but not threaten the stack.
16:17kotarakChouser: yep. have to work more with lazy-cons, me thinks...
16:20Chousergnuvince: so you're happy with your code's performance now?
16:20jao(although i think mutual recursion would be useful even without TCO in some cases; after all, CL doesn't ensure TCO and has labels.)
16:23gnuvinceChouser: I'll try the code on my machine at home and see if it's indeed something with my workplace's network that's causing the delay.
16:28Chousergnuvince: I don't think that's parallel. You're sending fetch-comic to the same agent, so it'll do them in series.
16:29Chouseryou'd need a new agent for each fetch-comic, and probably a ref to help you coordinate the results.
16:29gnuvinceagents to send-off x fetching threads and use commute to accumulate them into a vector?
16:30Chouseryeah, I think that would do it.
16:30gnuvinceOK.
16:30gnuvinceI'll look into it.
16:30Chouser(doseq c coll (send-off (agent nil) (collect-comic c))) or something
16:31Chouserwhere collect-comic would call fetch-comic and do the dosync commute stuff.
16:31gnuvinceIs this channel logged on ircbrowser.net or something?
16:31Chouserhttp://clojure-log.n01se.net/
16:32gnuvinceGood
16:32gnuvincethanks
16:32gnuvinceIn case I need to review this conversation.
16:33wwmorganchouser: does (collect-comic c) belong in its own S-expression there?
16:35wwmorganor would (doseq c coll (send-off (agent nil) collect-comic c)) make more sense?
16:35Chouserwwmorgan: nope, you're right.
16:36Chouseror perhaps (send-off (agent c) collect-comic)
16:49scottjgnuvince: I would be interested in seeing your finished code.
18:03danlarkinSo in boot.clj (http://clojure.svn.sourceforge.net/viewvc/clojure/trunk/src/clj/clojure/boot.clj?revision=1052&view=markup) on line 1267 the filter function is defined. Why won't that blow the stack, since it will recurse without using recur
18:05rhickeydanlarkin: that call is in a lazy-cons, which suspends the expression until needed
18:06danlarkinbut when I evaluate it with a huge list doesn't it have to keep all that stack info around?
18:07rhickeydanlarkin: there's no stack info, filter returns without that second call happening. Later, if someone calls rest, that call will be made, retuning another lazy cons. They don't build up on the stack, there is no recursion
18:16danlarkinah ha, I think I understand. (rest (filter ...)) is a clojure.lang.LazyCons datastructure, it doesn't just call up the (cons..)
18:49alecI'm trying to get Lucene working from Clojure. There's a class Field.Index under org.apache.lucene.document, but when I (import '(org.apache.lucene.document Field.Index)), I get a class not found error. Fiddling with it a bit doesn't help me load the class, and I'm guessing it's the '.' in there. Any suggestions?
18:50rhickeyField$Index
18:50alecthanks, that worked!
18:51alecI don't see that on the Java interop page; is there somewhere else I should have looked?
18:52rhickeyno, it's just a Java thing, that's the real JVM name for a nested class
19:49lisppaste8johnwayner pasted "gen-class with main issue" at http://paste.lisp.org/display/68077
19:51johnwaynerI'm trying to figure out how to define a main for a gen-class, but I can't seem to get it to work.
19:51johnwaynerI've tried looking through the gen-class function, but I can't quite figure out what the problem is.
19:53johnwaynerAlso, I was wondering if there's a reason gen-and-save-class doesn't create the directory structure. It seems simple enough which is why I think there must be a more compelling reason. (.. file getParentFile mkdirs)
19:53johnwayner
19:53Chouserjohnwayner: try (defn Test-main ...)
19:54johnwaynerI tried that... But I'll try agin
19:54Chouserhm, not sure...
19:54johnwayneryeah, same result
19:57Chouserworks for me
19:57Chouserno, something's screwy. hang on
20:04Chouserok, I'm seeing your error.
20:04ChouserI don't think I've ever used :main correctly.
20:05johnwaynerthere's not much on the web that I could find
20:05johnwaynerwhat do you see?
20:06Chouserexactly what you posted.
20:06johnwaynerOhhhhh
20:07johnwaynerI thought you meant that you saw what I was doing wrong :)
20:07Chouseralso I put (prn :loaded) in the .clj, and I'm not seeing that, so I don't think it's finding the .clj file correctly.
20:07Chouserah, sorry. :-/
20:08johnwaynerwhat do you mean by finding the .clj file? When does it do that? Does the class file need to find the clj?
20:09johnwaynerIf so, I've completely got the purpose of gen-class all wrong :)
20:10Chousergen-class generates a little stub .class -- the implementation of each generated method just turns around and calls the clojure function in the .clj file.
20:10Chouserthis allows you to swap out implementations at runtime, just like regular clojure functions.
20:10johnwaynerhmmm....
20:13johnwaynerjeez... it says that right there in the first paragraph of the doc string.
20:14johnwaynerI've copied my Test.clj to the .class location but I'm getting the same result still.
20:14johnwaynerI'm assuming that's what you did in the first place :)
20:15Chouserok, :main is broken. But not broken enough to be causing your problems.
20:16johnwaynerha
20:16ChouserI honestly didn't know what it was for, so thanks for your example. :-)
20:17Chouserok, so until gen-class is fixed, the name of the fn should be just "main"
20:17Chouserstrike that
20:17Chousergah, I'm confusing myself.
20:19johnwaynerThanks for your help. I've got to run for a while, but I'll check back later. Please just respond here if you come up with anything.
20:19Chouser"Test-main" is right, it's the error messages that are wrong.
20:19Chouserjohnwayner: ok, np.
20:20johnwayneroh...I should try that now that I know that the clj is needed...
20:20johnwaynerhey hey
20:21johnwaynerairty issue...but it found the fn
20:21Chouseroh!
20:21Chouserwell, you're ahead of me then.
20:21johnwaynergot it
20:21johnwaynerchanged it to no args
20:22johnwaynerI'll annotate.
20:22lisppaste8johnwayner annotated #68077 with "fixed." at http://paste.lisp.org/display/68077#1
20:23Chousergreat, thanks.
20:23johnwaynerthank you!
20:23johnwaynerI was in left field with my thinking about all this.
20:23johnwaynerOk... gotta run.