2009-11-08
| 02:52 | somnium | (.size (MongoProxy.)) |
| 02:52 | somnium | oops |
| 03:05 | stephenj | ~def -> |
| 04:57 | ttmrichter | What's the command set for the 'bot here? |
| 05:01 | hiredman | clojurebot: how much do you know? |
| 05:01 | clojurebot | I know 467 things |
| 05:01 | ttmrichter | clojurebot: help |
| 05:01 | clojurebot | http://www.khanacademy.org/ |
| 05:02 | ttmrichter | Ah. |
| 05:02 | hiredman | :D |
| 05:02 | ttmrichter | And I'm assuming , and ~ are special prefixes? |
| 05:02 | hiredman | ~ is equivilant to clojurebot: |
| 05:02 | clojurebot | clojurebot is not a benchmarking platform |
| 05:02 | ttmrichter | ~ commands |
| 05:02 | clojurebot | excusez-moi |
| 05:02 | ttmrichter | And the ,? |
| 05:03 | ttmrichter | ,(add 1 1) |
| 05:03 | clojurebot | java.lang.Exception: Unable to resolve symbol: add in this context |
| 05:03 | ttmrichter | Oops. |
| 05:03 | ttmrichter | ,(+ 1 1 ) |
| 05:03 | clojurebot | 2 |
| 05:03 | hiredman | actually |
| 05:03 | hiredman | (+ 1 1) |
| 05:03 | clojurebot | 2 |
| 05:03 | ttmrichter | Beat you to it. :D |
| 05:03 | hiredman | notice the lack of , |
| 05:03 | ttmrichter | Oh, no I didn't notice that. |
| 05:04 | ttmrichter | So why is everybody putting , in front (including you)? |
| 05:04 | hiredman | (+ 2 3) |
| 05:04 | clojurebot | *suffusion of yellow* |
| 05:04 | ttmrichter | ,(+ 2 3) |
| 05:04 | clojurebot | 5 |
| 05:04 | ttmrichter | Somebody is an Adams fan, I see. |
| 05:04 | ttmrichter | (/ 2 3) |
| 05:04 | clojurebot | 2/3 |
| 05:04 | ttmrichter | (/ 2.0 3) |
| 05:05 | ttmrichter | ,(/ 2.0 3) |
| 05:05 | clojurebot | 0.6666666666666666 |
| 05:05 | ttmrichter | ,(/ 2 30) |
| 05:05 | clojurebot | 1/15 |
| 05:05 | ttmrichter | So is there a way to get a full set of instructions for clojurebot? |
| 05:05 | hiredman | not so much |
| 05:06 | hiredman | clojurebot: where are you? |
| 05:06 | clojurebot | http://github.com/hiredman/clojurebot/tree/master |
| 05:07 | hiredman | clojurebot: git 1c8e76b1a0e6616c780902a317a7ab9a8423288b |
| 05:07 | clojurebot | newnew is now reify |
| 07:55 | spuz | ,(filter seq '("abc" "" "def" "" "ghi")) |
| 07:55 | clojurebot | ("abc" "def" "ghi") |
| 07:55 | spuz | is that a good way to filter out empty strings from a seqence? |
| 07:57 | rhickey | ,(remove empty? ["abc" "" "def" "" "ghi"]) |
| 07:57 | clojurebot | ("abc" "def" "ghi") |
| 07:57 | rhickey | might be clearer |
| 07:57 | rhickey | also, quoted lists are not idiomatic, use vectors |
| 07:58 | tomoj | seems like remove empty? is a bit slower for some reason |
| 07:58 | rhickey | tomoj: good == clearest or fastest? |
| 07:59 | tomoj | in this case the difference in speed is not really significant |
| 07:59 | tomoj | 100-200ms on a 100000 element seq |
| 07:59 | tomoj | so, clearest :) |
| 08:00 | rhickey | something that is clearer and slower today might be faster tomorrow, but will still be clearer |
| 08:26 | spuz | rhickey: thanks |
| 09:00 | solussd | is wrapping a function that calls a function that calls alter on a ref in a dosync sufficient to call it in a transaction? I have f2 that needs to run in a transaction, it is called by f1. can i (dosync (f1)) ? |
| 09:01 | solussd | nevermind- laziness was getting me |
| 09:09 | chouser | folding defclass into deftype sounds very pleasant |
| 09:25 | gerry` | will there be no defclass only deftype in future? |
| 09:27 | rhickey | chouser: ah, good, someone is reading that :) |
| 09:27 | rhickey | yes, I think very doable |
| 09:27 | rhickey | and desirable |
| 09:27 | rhickey | need cemerick to chime in |
| 09:28 | cemerick | rhickey: on? |
| 09:28 | rhickey | I think the ony gotcha will be people expecting the static aspects to update during dynamic development |
| 09:28 | rhickey | cemerick: http://www.assembla.com/wiki/show/clojure/Datatypes |
| 09:28 | rhickey | folding defclass into deftype, i.e. you get named class when AOT compiling deftype |
| 09:28 | rhickey | under: New ideas/scratchpad |
| 09:29 | gerry` | it seems cool |
| 09:29 | rhickey | for instance if you change the deftype and call new, you'll still get the AOT-compiled version |
| 09:30 | rhickey | and (.field calls) will fail on non-AOT based instances |
| 09:31 | gerry` | but if i really want a changed AOT class? |
| 09:31 | rhickey | OTOH, if (:field x) is as fast as (.field x) (at least for non-polymorphic sites), then why use (.field x) |
| 09:31 | rhickey | gerry`: compile again |
| 09:31 | rhickey | and restart :( |
| 09:32 | djpowell | what is :field using now? is it not using case any more? |
| 09:32 | rhickey | djpowell: it is backed by case, but there is not per-call-site caching of (:field x) calls |
| 09:33 | rhickey | in my tests, when the type of x doesn't change at a callsite, the perf is identical to (.field x) |
| 09:33 | rhickey | and of course, in real code using (.field x) the type of x isn't changing |
| 09:34 | djpowell | is the call site caching stuff described anywhere - i saw some checkins, but I didn't understand it |
| 09:34 | rhickey | cemerick: did you change all of your defstructs to defclasses or deftypes? and if the latter, to (.field x). If so maybe you could see if there is any perf disadvantage for you using (;field x) |
| 09:35 | rhickey | djpowell: I just tried to describe it to some people the other day, in person, with diagrams, took over an hour |
| 09:36 | gerry` | rhickey: your new ideas/scatchpad should be put at top of wiki page |
| 09:37 | rhickey | gerry`: I don't want people to get confused by speculation, the top is now working documentation for working code |
| 09:38 | cemerick | rhickey: they all got replaced by defclass; they're implementing public named interfaces |
| 09:38 | rhickey | cemerick: oh, that's right |
| 09:38 | rhickey | so you are not as good a test case then |
| 09:38 | rhickey | for deftype |
| 09:39 | cemerick | yeah, we're using it in only limited circumstances -- really, only where we'd otherwise be using regular maps with a stable set of slots |
| 09:40 | cemerick | I'm all for simplification though: right now, we have deftype, defclass, gen-class, proxy, and reify, which is quite a buffet to choose from if you're new. |
| 09:42 | rhickey | so, other than user confusion about the lack of dynamicity of named things (a recurring problem), the only real sticking point is the clash between the factory fn name and the class name |
| 09:43 | rhickey | seems a shame that people using Java can get (Foo. 1 2 3) where people using deftype dynamically will get (make-Foo 1 2 3) or something |
| 09:43 | rhickey | but my.ns.Foo can't name both the class and the facgory |
| 09:43 | rhickey | factory |
| 09:44 | rhickey | well, could but shouldn't |
| 09:52 | avital | Hello. I just started using Emacs/Slime with a remote Swank server and it keeps disconnecting. It may be something with my internet connection but I just wanted to check if anyone experiences similar issues... |
| 10:00 | cemerick | rhickey: w.r.t. "calls to (new Foo ...) will still use compiled class" -- perhaps the compiler should emit some hairy warning when loading a deftype is already defined in a compiled class? |
| 10:02 | rhickey | cemerick: If people aren't calling new or .field in Clojure code, i.e. using the factory fn and :field, then reloading a non-problem |
| 10:03 | rhickey | static name could just be for Java consumers |
| 10:04 | rhickey | or serialization, that was a use case of yours, any thoughts? |
| 10:04 | cemerick | rhickey: true, but if you're not calling new or using .field, then there's no reason to be AOT compiling, either. |
| 10:04 | cemerick | or, AOT compiling with any potential of reloading, I should say |
| 10:05 | rhickey | cemerick: not sure I get that, if I AOT for consumption by JAva, no harm/no foul if I reload during dev |
| 10:06 | rhickey | I just don't see it as a clear error |
| 10:07 | cemerick | OK, I'm reading "will still use compiled class" as meaning reloading will be a no-op for sites using new. Not an error, perhaps, but pretty darn surprising, I'd say. |
| 10:08 | rhickey | cemerick: why use (.field x) or new from Clojure code? |
| 10:09 | rhickey | note calls to new inside methods will work properly, as will naked local field refs: field |
| 10:10 | cemerick | hrm, OK. In that case, I withdraw. :-) |
| 10:10 | rhickey | the point of factory fns and fast (:field x) is to get people away from marrying AOT-static things |
| 10:11 | rhickey | note that I don't disagree - the behavior of new and .field may be both surprising and disappointing upon reload |
| 10:12 | rhickey | I get tired of explaining the static nature of Java classes and the problems with having/eating cake |
| 10:13 | rhickey | deftypes + protocols should provide a high-performance dynamic alternative, with good bridges |
| 10:13 | cemerick | Right. Well, that's largely why I suggested the warning, but the need for it depends a lot on how closely people will hew to idiomatic usage of the classes generated by deftype/class. |
| 10:14 | cemerick | i.e. :field rather than .field |
| 10:14 | rhickey | cemerick: I think the story has to be that new and .field are for interop consumption on the Java side |
| 10:16 | djpowell | if you are using new and .field for interop on the Java side, then having to recompile probably isn't too surprising |
| 10:16 | rhickey | djpowell: exactly |
| 10:19 | djpowell | so... what code do you have to write in clojure for the call site caching stuff to kick in? is it keyword based access? |
| 10:21 | rhickey | keyword callsites design diagram: http://www.assembla.com/spaces/clojure/documents/download/keywordcallsites.pdf |
| 10:21 | djpowell | ok cool i'll take a look |
| 10:21 | rhickey | djpowell: just (:k x) where x is a deftype/class instance |
| 10:22 | rhickey | that diagram is not meant to be self-explanatory :), just what I had at hand |
| 10:26 | Chousuke | Hopefully the JVM will be smart enough to optimise away most of the (identical? ret ...) checks, too. |
| 10:28 | Chousuke | though I suppose it'll have to have a check *somewhere*. |
| 10:28 | rhickey | Chousuke: yes, the fastpath presumes false, pipelining makes it 'free' |
| 10:29 | rhickey | the truly amazing thing is that hotspot can dynamically lift the thunk 'get' body inline into the host method |
| 10:29 | Chousuke | That's kind of counterintuitive, but nice nonetherless. |
| 10:29 | Chousuke | -r |
| 10:30 | Chousuke | Just goes to show that common sense assumptions about fast code hold less and less as processors and virtual machines advance :/ |
| 10:37 | Chousuke | "Is the chart readable? no? Redesign." |
| 13:03 | chouser | We just need alternate punctuation for the factory fn, vs the trailing . for 'new'. |
| 13:08 | chouser | So (new Foo x) or (Foo. x) for java interop, (new-Foo x) or (Foo< x) for deftype |
| 13:14 | Chousuke | I suppose Foo: would be too easy to typo :P |
| 13:14 | chouser | but much prettier than Foo< |
| 13:15 | Chousuke | if Foo weren't capitalised I'd just suggest make-* but make-Foo is kind of icky. |
| 13:18 | mikehinchey | I don't think make-Foo is that bad, and more clear than a special char |
| 13:20 | chouser | google search is now apparently crawling the clojure-log every few hours now |
| 13:22 | hiredman | special |
| 13:28 | solussd | it's been doing that for awhile. :) |
| 13:29 | hiredman | clojurebot: fun with vars is <reply>http://www.slideshare.net/mudphone/fun-with-vars |
| 13:29 | clojurebot | Roger. |
| 14:43 | djork | would it be possible to build a lazy seq using StringTokenizer? |
| 14:43 | djork | I can do it all in one shot |
| 14:44 | djork | with loop |
| 14:44 | chouser | sure could |
| 14:44 | chouser | using lazy-seq directly is probably the most straightforward |
| 14:44 | djork | lazy-seq doesn't use any stack space? |
| 14:45 | djork | when evaluated? |
| 14:45 | chouser | a function that uses lazy-seq correclty and idiomatically will not consume stack space. |
| 14:45 | djork | ok |
| 14:47 | chouser | "StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code." |
| 14:48 | djork | oh, that too I guess :) |
| 14:48 | chouser | you could produce a lazy seq from StreamTokenizer as well, though you'd have to be careful about getting the InputStream or Reader closed correctly. |
| 14:49 | djork | yeah |
| 14:54 | djork | I'm looking at things like re-partition from clojure.contrib.str-utils |
| 14:54 | djork | it seems like it would consume stack space |
| 14:56 | djork | I see a pattern like (fn foo [] (lazy-seq (cons bar (foo)))) |
| 14:56 | djork | where foo is most definitely not in tail position... but is that not an issue with lazy-seq? |
| 14:59 | chouser | lazy-seq is a macro -- the expression inside it is put into a closure and returned |
| 15:00 | chouser | do you know how trampolines work, either in Clojure or other languages? |
| 15:01 | porpoise | Can someone help me with getting clojure to work with swank and jswat? I have it working with swank/Emacs but can't get it to open a port of external debugging |
| 15:02 | porpoise | Bill Clementson's site describes how to do it, but it's completely different from the automatic set up that was recommended to me as the current way to install it |
| 15:02 | lisppaste8 | froog pasted "with-open and *out*, is this the way to do it?" at http://paste.lisp.org/display/90001 |
| 15:03 | djork | chouser: nope, not familiar with trampoline |
| 15:03 | djork | http://gist.github.com/229461 |
| 15:03 | chouser | froog: looks good to me |
| 15:04 | djork | damn, trampoline means about 20 different things :) http://en.wikipedia.org/wiki/Trampoline_(computers) |
| 15:05 | porpoise | What's the recommended way to install clojure with swank, and enable Jswat? |
| 15:05 | chouser | djork: don't worry about trampolines -- if you already were familier I could use that to explain lazy-seq. |
| 15:05 | djork | oh ok |
| 15:06 | chouser | djork: your gist is close, but the body of the lazy-seq needs to always return a seq (or nil), not a string |
| 15:06 | djork | next-tok will be nil in the false case of that if |
| 15:06 | djork | bad style, probably |
| 15:06 | froog | chouser: I wish the extra binding wasn't necessary, but I guess there's great wisdom behind the different 'let' and 'binding' |
| 15:06 | chouser | djork: oh! sorry, let me read again. |
| 15:07 | djork | there has to be an idiomatic way to express (if foo bar nil) |
| 15:07 | chouser | djork: (when foo bar) |
| 15:07 | djork | excellent |
| 15:07 | djork | you know I was reading some article that said "Clojure doesn't have a faq, it has chouser" |
| 15:08 | chouser | heh |
| 15:08 | djork | you need a break man |
| 15:08 | djork | clojure.contrib.chouser-vacation-fund |
| 15:09 | chouser | Speaking of which, I'm off to read Narnia to the kids. Good luck, all. |
| 15:09 | djork | edited: http://gist.github.com/229461 |
| 15:10 | chouser | djork: perfect, though I might recommend the name 'step' instead of 'next' |
| 15:11 | djork | yes, now go be an awesome dad |
| 15:58 | turbo24prg | morning |
| 18:44 | skybound_ | i was wondering if i might suggest a small fix for repl_utils.clj; (source load-file) throws an NPE, as the symbol doesn't have a :file meta entry and .getResourceAsStream doesn't appreciate nil. i realize this isn't a critical kind of bug... |
| 19:19 | chouser | skybound_: fixed, thanks. |
| 19:25 | skybound_ | chouser: you are welcome; and thanks for fixing, i wouldn't want to send in a contrib-agreement for such a small patch. |
| 19:31 | skybound_ | i think this would be nice to have for java code as well, but for the moment i don't see an easy way to do it |
| 19:32 | chouser | you mean for Clojure's own .java files? |
| 19:33 | chouser | they're not usually in the .jar or on the classpath, so the files would be a bit tricky to find in the first place. |
| 19:33 | skybound_ | no, i mean for any kind of java/class files where both are available to the classloader; like my own legacy java libs |
| 19:34 | chouser | oh, you have .java files in the classpath? I'm not a Java guy -- is that common? |
| 19:34 | chouser | you can use 'show' to do some examination of the Java classes themselves. |
| 19:35 | chouser | maybe not the best chosen names. :-/ |
| 19:38 | skybound_ | it depends i guess, during dev i usually package source into the jars. for the moment my main usage of clojure is poking around in a java app via the repl. |
| 19:39 | skybound_ | the idea is probably not worth the effort |
| 19:41 | chouser | when tracking down a Clojure behavior I often start with 'source' at the repl, but as I walk down the function calls end up at a java interop form, at which point I have to load the .java in an editor which is an unfortunate transition. |
| 19:45 | skybound_ | right |
| 20:48 | littleidea | Learning clojure, philosophical question, when do you choose (. class-or-instance method-name args) or |
| 20:48 | littleidea | (.method-name class-or-instance args)? Is it just style or is there ever a clear preference for one over the other? |
| 20:48 | hiredman | .method-name is the prefered idiom |
| 20:50 | littleidea | ok, thanks, that seems closer to the CLOS idiom |
| 20:51 | hiredman | even before .method-name existed I think (. class-or-instance (method-name args)) was prefered over (. class-or-instance method-name args) |
| 20:52 | chouser | (. i m (a)) is the oldest -- we've gotten steadily better since then. :-) |
| 20:52 | chouser | er, (. i (m a)) |
| 20:52 | hiredman | chouser: oh |
| 20:52 | chouser | I think. I could be remembering wrong. anyway, don't use either one. |
| 20:52 | littleidea | gotcha |
| 20:53 | chouser | unless you're generating them in a macro. Sometimes they're a bit more convenient there. |
| 20:54 | hiredman | because .foo is taken care of by the reader, and once you are in macro land you don't have the reader holding your hand |
| 21:19 | chouser | not quite |
| 21:19 | chouser | ,(read-string "(.foo bar)") |
| 21:19 | clojurebot | (.foo bar) |
| 21:19 | chouser | ,(first (read-string "(.foo bar)")) |
| 21:19 | clojurebot | .foo |
| 21:19 | hiredman | huh |
| 21:19 | chouser | it's actually expanded during macro-expand time, so you *can* use that form in a macro, it's just annoying. |
| 21:20 | chouser | ,(macroexpand (list '.foo 'bar)) |
| 21:20 | clojurebot | (. bar foo) |
| 21:23 | chouser | ,(macroexpand (let [method 'foo] `(. bar ~method))) |
| 21:23 | clojurebot | (. sandbox/bar foo) |
| 21:24 | chouser | ^^ simple |
| 21:24 | chouser | (macroexpand (let [method 'foo] `(~(symbol (str "." method)) bar))) |
| 21:24 | chouser | ,(macroexpand (let [method 'foo] `(~(symbol (str "." method)) bar))) |
| 21:24 | clojurebot | (. sandbox/bar foo) |
| 21:24 | chouser | ^^ annoying |
| 21:59 | chouser | hiredman: does *your* reader expand them? :-) |
| 22:00 | hiredman | nope |
| 22:01 | hiredman | I think I was misrembering the part where the reader turns symbols naming classes into Class objects |
| 22:20 | st3fan | i see parenthesis when i close my eyes |
| 22:20 | st3fan | too much code |
| 22:20 | st3fan | totally sarting to like clojure |
| 22:28 | st3fan | is there a shortcut for (filter #(not (nil? %)) c) ? |
| 22:29 | timothypratley2 | I think (remove nil? c) from memory |
| 22:30 | timothypratley2 | ,(remove nil? [1 2 nil 3]) |
| 22:30 | clojurebot | (1 2 3) |
| 22:34 | hiredman | ,(filter identity [1 2 nil 3 4]) |
| 22:34 | clojurebot | (1 2 3 4) |
| 22:34 | plunket | ,(loop infinite) |
| 22:34 | clojurebot | java.lang.IllegalArgumentException: loop requires a vector for its binding |
| 22:34 | st3fan | cool |
| 22:34 | hiredman | ,(filter (comp not nil?) [1 2 nil 3 4]) |
| 22:34 | clojurebot | (1 2 3 4) |
| 22:34 | plunket | ,(loop (print "hello)) |
| 22:34 | clojurebot | EOF while reading string |
| 22:34 | plunket | ,(loop (print "hello")) |
| 22:34 | clojurebot | java.lang.IllegalArgumentException: loop requires a vector for its binding |
| 22:35 | st3fan | even better would be a map function that would only return non-nil items |
| 22:35 | plunket | ,(loop [print "hello"]) |
| 22:35 | clojurebot | nil |
| 22:35 | hiredman | ,(filter (complement nil?) [1 2 nil 3 4]) |
| 22:35 | clojurebot | (1 2 3 4) |
| 22:35 | plunket | ,(loop [5]) |
| 22:35 | clojurebot | java.lang.IllegalArgumentException: loop requires an even number of forms in binding vector |
| 22:35 | plunket | ,(loop [5 8]) |
| 22:35 | clojurebot | java.lang.Exception: Unsupported binding form: 5 |
| 22:43 | wtetzner|nyx | ,(loop [x 10] (if (zero? x) (println "done.") (do (println (str "x = " x)) (recur (dec x))))) |
| 22:43 | clojurebot | x = 10 x = 9 x = 8 x = 7 x = 6 x = 5 x = 4 x = 3 x = 2 x = 1 done. |
| 22:45 | st3fan | can anyone give me an example of if-let ? |
| 22:45 | timothypratley2 | ,(if-let [a true] 10) |
| 22:45 | clojurebot | 10 |
| 22:45 | wtetzner|nyx | ,(if-let [a false] 10) |
| 22:45 | clojurebot | nil |
| 22:46 | st3fan | oh so it is simply if the binding evaluates to a true value then the body is executed |
| 22:46 | timothypratley2 | yup |
| 22:46 | wtetzner|nyx | it only executes what's in the if-let if the binding is non-nil and non-false |
| 22:46 | st3fan | ok |
| 23:03 | st3fan | hm too bad if-let doesn't support multiple bindings .. would be nice if it would try all bindings and exec the body if they all returned a non-nil value |