2009-10-22
| 00:58 | technomancy | jlilly: I've never noticed any difference between openjdk and sun's. |
| 00:58 | technomancy | I think the only difference is in some desktop-app font rendering |
| 00:59 | technomancy | jlilly: $CLASSPATH and -cp are mutually exclusive IIRC |
| 00:59 | technomancy | generally the env var is discouraged |
| 01:01 | mikehinchey | I found one problem with openjdk, something about clojure.contrib.jmx, I posted to clojure-dev. But I've used openjdk a lot with clojure. |
| 01:23 | jlilly | technomancy: I got it all sorted out. |
| 01:24 | jlilly | thx though. |
| 02:00 | hiredman | hah! |
| 02:01 | hiredman | I can run ant, and the first time clojure will build using LispReader, then run ant again and clojure will build using my reader written in clojure |
| 02:02 | hiredman | now I just need to get rid of all the calls to LispReader/* in my reader written in clojure |
| 02:05 | hiredman | http://github.com/hiredman/clojure/tree/readerII |
| 02:35 | mikehinchey | hiredman: that's a good way way of putting it :) |
| 03:32 | angerman | how would I turn (a b c d) -> (d a b c) ? |
| 03:36 | hiredman | ,((fn [x] (conj (butlast x) (last x))) '(a b c d)) |
| 03:36 | clojurebot | (d a b c) |
| 03:38 | angerman | ahh, butlast |
| 05:26 | G0SUB | I was just wondering, what is the problem in introducing optional (and/or) keyword arguments to Clojure? |
| 05:29 | G0SUB | They are quite useful sometimes. |
| 05:31 | cgrand | GOSUB: perfs and interop |
| 05:31 | cgrand | G0SUB i mean |
| 05:32 | G0SUB | cgrand: interop with what? |
| 05:32 | cgrand | java |
| 05:32 | G0SUB | cgrand: and is perf a real issue? |
| 05:33 | cgrand | on each call? I think but I haven't thought too far about how it could be implented. |
| 05:34 | G0SUB | hmm |
| 05:34 | cgrand | G0SUB: but you could mimick them with maps and/or macros |
| 05:36 | cgrand | (fn [{:keys [opt1 opt2 opt3] :or {:opt3 42}}] ...) |
| 05:36 | arbscht | G0SUB: you have optional arguments with arity overloading, and something like keywords with hash destructuring (or c.c.def/defnk). that covers a lot of cases |
| 05:37 | G0SUB | cgrand: as far as mimicking keyword args, I don't like that fact that I have to call a fn like (myfn {:a 1 :b 2}) and not (myfn :a 1 :b 2) |
| 05:37 | G0SUB | arbscht: hmm, let me look again. |
| 05:38 | AWizzArd | Strange... I am using htmlunit and do (.asText #^HtmlPage (.getPage webclient url)) and this results in a reflection warning "reference to field asText can't be resolved". But when I do (let [p (.getPage webclient url)] (.asText #^HtmlPage p)) then I get no reflection warning. |
| 05:38 | AWizzArd | cgrand: maybe you have an idea why it is that way? |
| 05:43 | cgrand | G0SUB: (fn [& args] (let [{:keys [opt1 opt2 opt3] :or {:opt3 42}} (apply hash-map args)] ...)) ; and I think that's more or less what defnk macroexpands to |
| 05:44 | G0SUB | cgrand: OK. thanks. I will take a look at defnk. |
| 05:47 | cgrand | AWizzArd: yes I see what's the problem is. macro and inline expansion make type hints disappear |
| 05:49 | cgrand | (meta '#^HtmlPage (.getPage webclient url)) |
| 05:49 | cgrand | ,(meta '#^HtmlPage (.getPage webclient url)) |
| 05:49 | clojurebot | {:tag HtmlPage} |
| 05:49 | cgrand | ,(meta (macroexpand-1 '#^HtmlPage (.getPage webclient url))) |
| 05:49 | clojurebot | nil |
| 05:49 | cgrand | ,(macroexpand-1 '#^HtmlPage (.getPage webclient url)) |
| 05:49 | clojurebot | (. webclient getPage url) |
| 05:50 | cgrand | AWizzArd: can't you just hint webclient? |
| 05:51 | AWizzArd | I will try that |
| 05:51 | cgrand | I guess if webclient (and maybe url) are propely hinted the return type of .getPage will be inferred to HtmlPage |
| 05:51 | AWizzArd | Although funnily getpage doesn't produce a complaint |
| 05:52 | AWizzArd | I have a (let [webclient (WebClient.)] ...) so I thought webclient is implicitly hinted. |
| 05:52 | cgrand | can you paste with more context? |
| 05:53 | AWizzArd | Do you have htmlunit installed and setup in your classpath? |
| 05:54 | AWizzArd | If yes I could hack up a minimal example for pasting into a .clj file which will demonstrate it. |
| 05:55 | AWizzArd | But what I basically have is: (let [webclient (WebClient.), url (java.net.URL. "http://clojure.org/")] ... (.asText (.getPage webclient url))) |
| 06:18 | cgrand | AWizzArd: ok, looked at the javadocs .getPage returns a Page object so you must "downhint" it to HtmlPage |
| 06:19 | cgrand | right now your let is the best workaround I can think of |
| 06:22 | AWizzArd | Yes, .getPage returns a Page. So in those cases, where a method returns an "instance of an Interface" (such as Page) the type hint info can get lost? |
| 06:26 | cgrand | rhickey: would you accept a patch to preserve (merge) metadata on macro (and inline) expansion? It would make some hinting headaches go away. |
| 06:27 | rhickey | cgrand: preserve which metadata? |
| 06:28 | rhickey | on the form as a whole? |
| 06:30 | cgrand | yes actually type hints are lost when put on something that is expanded (macro, inline, .method), so I was thinking about merging metadata of the original form into the expanded form's metadata |
| 06:32 | AWizzArd | Currently it seems a work around is needed, such as (let [p (.getPage webclient url)] (.asText #^HtmlPage p)) ==> no reflection warning, vs (.asText #^HtmlPage (.getPage webclient url)) ==> can't resolve the call to .asText |
| 06:34 | rhickey | cgrand: you can't do that, but it would be nice to have a way to communicate it to the macro itself, so it could if it wanted. Right now there is no &whole-like thing |
| 06:35 | AWizzArd | cgrand: btw, if metadata would be preserved, would that also mean that there won't be reflection warnings anymore for things as (.replaceAll (with-out-str ...) ...)? Currently i need to (let [xyz (with-out-str ..)] (.replaceAll #^String xyz ...)) to prevent reflection. |
| 06:39 | esj | Hi everybody, please excuse a very naive question, but can anybody provide an explanation, or link to such, of the -> macro ? I'm struggling to find anything beyond (doc ->), which has, sadly, not enlightened me. |
| 06:40 | G0SUB | esj: (-> {} (assoc :a 1) (assoc :b 2)) |
| 06:40 | G0SUB | esj: that expands to (assoc (assoc {} :a 1) :b 2) |
| 06:40 | esj | aha ! |
| 06:41 | esj | I get it, much obliged indeed. |
| 06:41 | AWizzArd | ,(macroexpand-1 '(-> 5 (+ 3))) |
| 06:41 | clojurebot | (+ 5 3) |
| 06:41 | G0SUB | esj: :) |
| 06:42 | arsatiki | esj: I think it's a sort of a enhanced reverse function composition |
| 06:43 | arbscht | -> it is not function composition |
| 06:43 | arbscht | it simply rearranges code |
| 06:43 | arsatiki | yeah, that's why it's "sort of" |
| 06:44 | rhickey | (-> x a b c) => (c (b (a x))) |
| 06:44 | rhickey | (-> x (a 1) (b 2) (c 3)) => (c (b (a x 1) 2) 3) |
| 06:44 | rhickey | it just reduces nesting and lets you write things in the order in which they will occur, when that's convenient |
| 06:45 | G0SUB | woohoo! rhickey |
| 06:48 | rhickey | -> threads the expr as first arg, ->> threads the expr as last arg: (->> x (a 1) (b 2) (c 3)) => (c 3 (b 2 (a 1 x))) |
| 06:48 | AWizzArd | rhickey: it would be so nice to have a function "pipe" that is like comp, but follows the sequence like -> does. |
| 06:51 | esj | Thanks very much everybody. |
| 06:52 | AWizzArd | Using comp often means to write "(comp fn1" then using the arrow keys to go left, editing it to become "(comp #(fn2 1 % 3) fn1", then again the arrow keys, etc. |
| 06:55 | rhickey | AWizzArd: since it's not a nesting issue, only arg order, not very compelling |
| 06:57 | AWizzArd | I see |
| 06:58 | AWizzArd | Just found myself often using comp, which is not soo nice for editing and reading. |
| 06:58 | arsatiki | oh |
| 06:58 | arsatiki | I had the impression that comp use was pretty rare |
| 07:03 | AWizzArd | Maybe not soo often, but for example if your webserver was writing log files readably, containing json strings you maybe want to analyze them (map (comp read-json :text first read-string #(slurp % "UTF-8")) log-files) |
| 07:04 | liwp | it's very nice for things like that. it get's a bit messy if you have to use partial when your functions take more than one argument |
| 07:04 | AWizzArd | liwp: or using %1 %2 %3 or %* |
| 07:04 | AWizzArd | Typically I don't use partial and instead the nice reader macro #(...) |
| 07:05 | liwp | AWizzArd: yep. I tend to prefer #() rather than partial |
| 07:21 | arsatiki | re: comp, partial -- I'm often impressed by the ease Haskell handles them (http://www.haskell.org/haskellwiki/Pointfree) |
| 07:21 | arsatiki | but honestly, sometimes pointfree is really pointless :) |
| 07:23 | G0SUB | What's the best way to unzip a file in Clojure? |
| 07:33 | AWizzArd | G0SUB: http://java.sun.com/javase/6/docs/api/java/util/zip/ZipFile.html |
| 07:33 | G0SUB | AWizzArd: yeah, looking at that itself :) |
| 07:35 | AWizzArd | you can do: (enumeration-seq (.entries (java.util.zip.ZipFile. (java.io.File. "c:/clojure/clojure.zip")))) |
| 07:38 | cgrand | rhickey: sorry, I have been called away. Why can't I do that? |
| 07:46 | G0SUB | AWizzArd: how do I handle directories and all? |
| 07:46 | G0SUB | AWizzArd: I want to use as much code from c.c as possible. |
| 07:50 | kunley | Hi. |
| 07:51 | kunley | Do we have Long literals in Clojure? |
| 07:54 | AWizzArd | kunley: (long 123456789) |
| 07:54 | rhickey | cgrand: because you don't know what the macro wants/needs - it may be creating something non-meta-supporting, or setting meta explicitly, expecting that to be the only meta on the expansion |
| 07:55 | kunley | doh.. likely need more coffee ;] thx! |
| 07:56 | AWizzArd | G0SUB: What do you mean, how do you handle directories? |
| 07:57 | AWizzArd | The ZipEntries that .entries returns will list all files in all directories |
| 07:57 | G0SUB | AWizzArd: well, if the zip file has directories, how will the unzipping maintain the same dir structure? |
| 07:58 | AWizzArd | The java.io.File class has a (.mkdirs ...) method. |
| 08:00 | AWizzArd | G0SUB: and you have a (.isDirectory some-entry) |
| 08:01 | G0SUB | hmm |
| 08:01 | AWizzArd | So if that returns true, then call (.mkdirs (File. (str some-entry))) and you will have the directory |
| 08:02 | AWizzArd | I'm not sure if .entries *must* return the enumeration of ZipEntry's in such a way that a directory entry D will always come before entries that live in D. |
| 08:03 | G0SUB | AWizzArd: OK, got it. by the way, how do I figure out in which dir a file exists? Does File have a method for that? |
| 08:03 | AWizzArd | I would suggest you to filter all entries that are true for .isDirectory, then mkdirs those, and only then begin storing files in there. |
| 08:03 | G0SUB | AWizzArd: thanks for the tip. |
| 08:04 | AWizzArd | G0SUB: the (str your-entry) will return a string of the directory |
| 08:04 | AWizzArd | plus file name |
| 08:04 | AWizzArd | just play with it in the repl |
| 08:04 | cgrand | rhickey: don't you find surprising for the user to see his type hints ignored/discarded? |
| 08:04 | cgrand | Concerning your two points: if the macro returns something non-meta supporting, a warning can inform the user his metadata is discarded. And for a macro setting meta explicitely (and expecting it to be the only meta) there would be a problem only when the user adds his own metadata. |
| 08:05 | AWizzArd | G0SUB: in Contrib there is a filter function "separate" which you could use to separate the directory ZipEntry's from the non-directory ones. |
| 08:05 | G0SUB | AWizzArd: will look. thanks. |
| 08:05 | cgrand | I think the new problem would be less frequent than the current one |
| 08:06 | AWizzArd | cgrand: I was surprised today when working with htmlunit, and I also thought that .replaceAll would know that a (with-out-str ...) will return a String. |
| 08:06 | rhickey | cgrand: discarded how? no macro can promise to use any metadata placed on it's invocation. You are presuming some semantics for metadata (that it is destined for the expansion) that's simply not there |
| 08:06 | G0SUB | AWizzArd: where in c.c is separate? |
| 08:07 | AWizzArd | clojure.contrib.seq-utils/separate |
| 08:07 | G0SUB | ok |
| 08:09 | cgrand | rhickey: I think I failed to explain what I want |
| 08:09 | rhickey | #^meta (a-macro-call) ==> #^meta (its-expansion), right? |
| 08:10 | cgrand | right :-( |
| 08:11 | rhickey | so the question is, who should 'own' the metadata on the macro call, the enclosing scope or the macro itself |
| 08:12 | rhickey | if a macro were to be passed &whole (http://www.lispworks.com/documentation/HyperSpec/Body/03_dd.htm) one would presume it could act on the metadata |
| 08:12 | cgrand | currently the macro can't see it (no &whole) |
| 08:13 | rhickey | but there's nothing in the definition of macros that says they can't become richer than they are (macros are just functions is an implementation detail of the current mechanism) |
| 08:13 | rhickey | &whole and environments would be logical extensions |
| 08:14 | rhickey | at which point this ownership issue would arise |
| 08:15 | cgrand | ok, so I may try to restrict what I'd like: can we have #^meta (.method obj) ==> #^meta (. obj method) and #^meta (inlined-fn obj) ==> #^meta (inline-expansion) |
| 08:16 | rhickey | in the - a macro call provides its replacement - world, I would give ownership to the macro |
| 08:17 | rhickey | cgrand: I'm wondering in those cases that the meta isn't better place on obj, then return type should flow through |
| 08:18 | cgrand | rhickey: I agree except when the .method says to return an interface and you want to "downhint" to something more specific |
| 08:18 | rhickey | but yes, those expansions are compiler controlled so could do |
| 08:19 | rhickey | I would accept a patch limited to that |
| 08:19 | AWizzArd | would be helpful |
| 08:20 | cgrand | rhickey: ok thanks! |
| 08:20 | rhickey | cgrand: thank you! |
| 08:27 | AWizzArd | rhickey: would a datatype made via deftype be GCable? |
| 08:27 | rhickey | AWizzArd: the class itself or instances? |
| 08:27 | AWizzArd | the class itself I mean |
| 08:27 | rhickey | subject to same issues as all classes |
| 08:28 | AWizzArd | ok |
| 08:29 | rhickey | I'm working on making protocols hold classes weakly, not there yet |
| 08:29 | rhickey | and not sure it would matter, since their caches must hold strongly |
| 08:29 | AWizzArd | sounds very promising |
| 08:30 | rhickey | once implementing a protocol and called, class would be embedded in cache until un-implemented |
| 08:30 | rhickey | so not so promising |
| 08:42 | G0SUB | AWizzArd: This is what I wrote just now. Works well. http://paste.lisp.org/display/89087 |
| 08:43 | G0SUB | AWizzArd: many thanks for the tips. I am a Java n00b :) |
| 08:43 | AWizzArd | Anyway, it would still be enormously helpful to have deftype. We have a lot of structs that contain a :type slot, but this is convention. Having a default way for marking a type (deftype ...) would make things easier. But mostly the speedup will be very nice. |
| 08:44 | AWizzArd | G0SUB: grats! You have a nice zip app now :) |
| 08:44 | AWizzArd | G0SUB: you can download the SDK from http://www.7-zip.org/sdk.html and extend your program to handle .7z files as well. |
| 08:46 | G0SUB | AWizzArd: well, right now, I just need to handle the Zip algo. May be some other time :) |
| 10:11 | saml | i installed clojure box. i can type stuff in REPL. where do I learn to actually use it to program? like editing files, loading some defn from files.. debugging, printing doc of a symbol, jumping to definition of the symbol...etc? |
| 10:17 | RomanRoe | Is it possible to get namespace/function code completion in Emacs/Slime? (Just like in Enclojure and CCW) |
| 10:18 | liwp | RomanRoe: you should get it out of the box on the repl, just hit tab |
| 10:18 | liwp | I'm not sure what the keybinding would be for a clojure-mode buffer, try M-tab |
| 10:19 | RomanRoe | liwp: thx. will try that |
| 10:20 | liwp | RomanRoe: looks like M-tab is bound to slime-complete-symbol if your clojure buffer has the slime-minor-mode enabled (as it should) |
| 10:22 | RomanRoe | liwp: unfort. I cant check it right now (different machine right now). But I doubt that M-tab work since it cycles the windows |
| 10:22 | liwp | saml: try googling for some clojure / slime blog posts. But the basic steps are something like this: open a new buffer (e.g. test.clj), write some code in it, and hit C-c C-k to compile and load the file to the repl |
| 10:22 | RomanRoe | liwp: I will try M-x slime-complete-symbol and remap if it works |
| 10:22 | liwp | RomanRoe: you can hit M-tab by hitting Esc and Tab |
| 10:23 | RomanRoe | liwp: ah thx! I am a emacs newbie... ;-) |
| 10:23 | liwp | annoying, I know, but you can rebind it |
| 10:23 | liwp | I only found out about M-tab maybe a week ago ;-) |
| 10:50 | Kjellski | Hi there =) |
| 10:53 | Kjellski | Can someone tell me how I can call a constructor of a native java class with more than one argument? I saw that in the book but can´t find it again... |
| 10:54 | rhickey | Kjellski: (TheClass. a b c) |
| 10:55 | Kjellski | *homerlike* doh... thanks! |
| 10:55 | rhickey | np |
| 11:08 | Soulster | hello everyone, whats up with "gen-and-load-class" when i am using it i get "Unable to resolve symbol: gen-and-load-class in this context" |
| 11:08 | Soulster | with a java.lang.Exception |
| 11:12 | Chousuke | Soulster: gen-and-load-class went away ages ago :) |
| 11:12 | Soulster | outch..^^ |
| 11:14 | chouser | Soulster: you may use gen-class, but that requires you use 'compile' to actually generate the class. |
| 12:01 | ambient | i can't quite get this to work: (defmacro foo [num] `(do ~(for [i# (range 5)] `(+ 1 1)))) |
| 12:01 | ambient | it's supposed to expand into (do (+ 1 1) (+ 1 1)) etc.. |
| 12:01 | chouser | try ~@ instead of ~ |
| 12:02 | ambient | cool! thanks |
| 12:05 | cgrand | ambient: and no need for the # in i#: you aren't in the syntax quote |
| 12:06 | ambient | i just started doing macros 30 minutes ago :p |
| 12:06 | ambient | so what you mean by syntax quote, i dont know |
| 12:07 | chouser | ` is read "syntax quote" |
| 12:07 | ambient | ok |
| 12:07 | ambient | well, i will be so it might as well be i# |
| 12:08 | ambient | (defmacro foo [num] `(do ~@(for [i# (range num)] `(+ ~i# ~i#)))) |
| 12:09 | chouser | still no need for the # |
| 12:09 | ambient | ok |
| 12:09 | chouser | don't worry -- if you forget the # somewhere that you should have it, Clojure will yell at you. |
| 12:10 | cgrand | as soon as you cross a ~ (unquote) you escape from the syntax-quote |
| 12:10 | Chousuke | I think I managed to compile a clojure with my reader |
| 12:10 | Chousuke | the repl still uses lispreader though. |
| 12:11 | Chousuke | presumably because of read... hm |
| 12:14 | ambient | my first working macro, that's actually useful: (defmacro mdaset [a vals] `(do ~@(for [i (range (count vals))] `(aset #^doubles ~a ~i ~(vals i))))) :) |
| 12:15 | ambient | sets values to an array |
| 12:20 | Chousuke | \o/ it works |
| 12:20 | Chousuke | well, as far as I can tell, anyway |
| 12:20 | Chousuke | except for a small bug |
| 12:21 | Chousuke | for some reason, if my input ends with a symbol I need to press enter twice. |
| 12:22 | cgrand | ambient: you can't hint an unquote, you should change the do in a let [#^doubles a# ~a] |
| 12:23 | cgrand | and replace all other ~a by a# |
| 12:23 | Chousuke | or ~(with-meta a {:tag 'doubles}) |
| 12:38 | ambient | type hints dont seem to macro-expand :/ |
| 12:38 | ambient | cgrand answered my question :P |
| 12:39 | Chousuke | type hints are read-time. you're actually attaching the hints to the macro code :P |
| 12:41 | ambient | my problem is that if the macro breaks, the execution time of the program goes from 0.2 sec to 16 |
| 12:45 | ambient | (defmacro daset [a vals] `(let [#^doubles b# ~a] ~@(for [[idx val] (partition 2 vals)] `(aset b# ~idx ~val)))) ==> "unable to resolve symbol: b__16325__auto__ in this context" |
| 12:47 | cgrand | ambient: sorry didn't notice that you were going in an uout of syntax-quote so the two b# are different. Try Chousuke's solution or |
| 12:49 | ambient | thanks, it works now :) |
| 12:49 | ambient | *fist pump* |
| 12:49 | cgrand | (defmacro daset [a vals] (let [b (with-meta (gensym "b") {:tag 'doubles})] `(let [~b ~a] ~@(for [[idx val] (partition 2 vals)] `(aset ~b ~idx ~val)))) ; not worth it here |
| 12:52 | ambient | pretty cool, now i can just write (daset oscm2 [0 (+ car-f os1-o), 2 car-v]) instead of painfully doing it piece by piece |
| 12:52 | ambient | and the performance doesn't suffer at all |
| 12:52 | cgrand | no i'm wrong: this last one is worth the pain because it doesn't cause multiple evaluations of a (which is important when a is not a symbol but a function call) |
| 12:52 | ambient | here's mine: (defmacro daset [a vals] `(do ~@(for [[idx val] (partition 2 vals)] `(aset ~(with-meta a {:tag 'doubles}) ~idx ~val)))) |
| 12:54 | cgrand | try (macroexpand-1 '(daset (foo bar) [0 1 2 3])) |
| 12:54 | ambient | it's not supposed to be used like that |
| 12:55 | cgrand | ok, I just wanted to make you aware of potential shortcomings |
| 12:55 | ambient | (foo bar) would be evaluated at each iteration? |
| 12:57 | cgrand | yes because your macro would expand to (do (aset (foo bar) 0 1) (aset (foo bar) 2 3)) |
| 12:58 | cgrand | my last (untested) one should expand to (let [b457 (foo bar)] (aset b457 0 1) (aset b457 2 3)) |
| 13:01 | ambient | if i would be making more general purpose array handling operations, that might be a problem. for my case every array's lifetime is programs lifetime and there are no intermediate arrays |
| 13:38 | cemerick | since it's macro workshop day: how do people deal with using private fns in public macros? I've always just used the corresponding var, but that feels wrong. |
| 13:42 | Chousuke | just make them public and document that the only supported way of using them is via the macro |
| 13:43 | Chousuke | hmm, pretty good. |
| 13:44 | hiredman | Chousuke: hows the reader coming? |
| 13:44 | Chousuke | running the clojure tests with my reader, I got one test failure and two errors |
| 13:44 | hiredman | :/ |
| 13:45 | Chousuke | the failure tests compiler metadata which I omit on purpose :P |
| 13:45 | Chousuke | the errors are... something. need to investigate |
| 13:45 | hiredman | can you build clojure with it? |
| 13:45 | Chousuke | hm |
| 13:45 | Chousuke | didn't try. |
| 13:46 | hiredman | really? |
| 13:46 | cgrand | cemerick: by "used the corresponding var" you mean @#'ns/private-fn? I agree with Chousuke, make them public but documented as unsupported |
| 13:48 | cemerick | cgrand: yes. Just making the fns public seems worse, though. Reminds me of abstract method overrides on Java APIs that aren't meant to be called that have javadoc that reads "Public as an implementation detail, do not use." Uk. |
| 13:50 | hiredman | how do you know if rhickey got your ca? |
| 13:50 | hiredman | ask him? |
| 13:50 | cgrand | hiredman: check the cotributors page |
| 13:50 | cgrand | contributors even |
| 13:50 | hiredman | w00t |
| 13:51 | Chousuke | hm, I get a nullpointer exception :-( |
| 13:51 | hiredman | I can build clojure, but the reader is not complete yet, the missing parts are stubbed out to LispReader |
| 13:51 | cgrand | cemerick: can't you make your macro shallow? and backed by a public (supported) function |
| 13:53 | djork | This might be more of a Java issue than a Clojure one, but if build a MUD-style game using a thread per-player, will I have problems with high player counts? |
| 13:53 | djork | this is just based on some (probably bad) advice from a friend who said that threaded servers don't scale |
| 13:53 | djork | i.e. in terms of memory usage etc. |
| 13:54 | cemerick | cgrand: yeah, I could support it, but the macro helps to ensure proper usage. I suppose I should put the unsupported stuff in a secondary ns. |
| 13:54 | Knekk | maybe thread-per-connection servers don't scale.... threaded servers scale |
| 13:54 | hiredman | I doubt you will have any trouble with a mud |
| 13:54 | cemerick | djork: use an *agent* per player, and you can have thousands, millions perhaps. |
| 13:54 | djork | hmm |
| 13:55 | hiredman | cemerick: ahem |
| 13:55 | djork | I'm still not quite clear on agents. Is there a good example on their usage? The docs don't quite "click" yet. |
| 13:55 | cemerick | hiredman: hrm? |
| 13:56 | Chousuke | hmm, interesting |
| 13:56 | hiredman | agents sit on top of threads, so picking agents because you don't want threads doesn't seem like a good idea |
| 13:57 | djork | yeah |
| 13:57 | djork | that's what I thought |
| 13:57 | Chousuke | I suspect there's something wrong with my syntax-quote :/ |
| 13:57 | technomancy | agents use a thread pool |
| 13:57 | hiredman | djork: with the amount of users you will get for a mud, a thread per user should not be a problem |
| 13:57 | djork | heh :) |
| 13:57 | hiredman | technomancy: yes |
| 13:57 | cemerick | hiredman: my point is that agents are lightweight; you could service a very, very large number of agents with a very small number of threads. |
| 13:57 | djork | the idea is to scale up to a graphical client on iPhone eventually |
| 13:57 | hiredman | but the send-off threadpool is unbounded |
| 13:58 | djork | which could see a lot more users |
| 13:58 | hiredman | cemerick: ah |
| 13:58 | djork | hmm, so agents join threads in the pool as needed? or something like that? |
| 13:58 | cemerick | I see no reason why you couldn't use send for a MUD (and maybe snapshot state every now and then or something). |
| 13:58 | hiredman | right, for re-use of threads that happen to be laying around :P |
| 13:59 | cemerick | djork: agents use threads as needed, when they have an action to service. |
| 13:59 | djork | OK that makes sense. Now if only I understood their general use :P |
| 13:59 | hiredman | Chousuke: it's statements like that that make me want a line by line port of the java reader :P |
| 14:00 | djork | By the way, is there any work towards tracebacks for Clojure code? |
| 14:00 | Knekk | you'll still run into problems when your number of agents and actions saturate and exceed the threadpool |
| 14:00 | Knekk | maybe think about queueing actions, decouple your user connections |
| 14:02 | cemerick | The real criteria is whether one's actions will saturate the send threadpool to such an extent that responsiveness is impacted. For a MUD, probably never. |
| 14:02 | Knekk | cemerick: you are assuming that a MUD won't have thousands of users. |
| 14:02 | Knekk | cemerick: there's no reason why it shouldn't |
| 14:03 | Knekk | cemerick: specially as he wants to port to the iPhone |
| 14:03 | cemerick | Knekk: well, it's a little bit moot one way or the other -- you can do as much decoupling as you want, but you can't do more work than what the send threadpool can schedule (e.g. you've got the cores you've got, and that's a pretty hard limit regardless of the arch.) |
| 14:05 | Knekk | I'd personally queue actions so that the impact of saturation is seen as latency across the system for all users rather than arbitrary delays/timeouts for some connections. |
| 14:05 | Knekk | cemerick: right, but one can control where the pain is felt. |
| 14:07 | cemerick | Good point. I guess it's a product mgmt question, then: IMHO, better to get the thing working, and if he's so lucky to have a load problem, his massive bankroll can be put into an alternative scheduling strategy for agents. :-) |
| 14:08 | Knekk | It'd be a good problem to have, for sure |
| 14:08 | cemerick | Actually, it might be as easy as building a send* variant that uses a given threadpool that throttles as desired. |
| 14:08 | jasapp | roughly, how many users is this MUD to support? |
| 14:08 | cemerick | (this is already the most heavily-engineered MUD in history ;-) ) |
| 14:08 | jasapp | heh |
| 14:09 | serp_ | cemerick: how would one do that? |
| 14:11 | cemerick | serp_: in broad strokes, change Agent.dispatch and Agent$Action to take an ExecutorService, rather than a boolean controlling which of two standard threadpools are to be used. I'm sure there'd be a lot of consequences to such a change, but that's the first step. |
| 14:19 | Chousuke | aha, I think I found the bug. |
| 14:20 | Chousuke | I was expanding (Foo. ...) to (fully.qualified.Foo ...) :P |
| 14:21 | Chousuke | or wait |
| 14:22 | Chousuke | yeah |
| 14:25 | djork | cemerick: yes, I'd love to have too many users :) |
| 14:26 | ambient | FFFUUUUU... macros are killing my brain |
| 14:27 | djork | ambient: just be glad macros are so easy in Clojure... just try digesting the docs for building them in any other lisp |
| 14:27 | ambient | is there somewhere a whole reference for every type of macro possible in clojure? |
| 14:27 | Chousuke | type? |
| 14:28 | Chousuke | there's only one type of macro: one that takes in a form and produces another :P |
| 14:28 | ambient | meaning comprehensive |
| 14:29 | Chousuke | hm, cool |
| 14:29 | Chousuke | only one test failure for my reader now |
| 14:30 | Chousuke | for line metadata :P |
| 14:31 | djork | ambient: just check out the source |
| 14:31 | djork | grep for defmacro |
| 14:37 | ambient | here's what's giving me trouble: http://paste.pocoo.org/show/146449/ |
| 14:38 | ambient | grep, one of those tools that unices use |
| 14:39 | mwoelker_ | quick question: is it possible to create cyclic immutable collections in clojure? e.g. two vectors that contain each other? |
| 14:40 | cgrand | mwoelker_: quick answer: no (apart from cyclic lazy-seq) |
| 14:42 | cgrand | imagine you have a cyclic vector of one item (itself), what does (conj v 42) must return? |
| 14:44 | cgrand | [new-self 42] or [old-self 42]? it seems easy but once you are deely nested, not so: you have to "update" all collections that are on the path to the recursive reference(s) |
| 14:45 | mwoelker_ | cgrand: hmm, is it possible to put refs into collections? |
| 14:45 | cgrand | yes of course and it's one way to deal with cyclic stuff |
| 14:46 | cgrand | one other being the relational way |
| 14:46 | chouser | ambient: http://paste.pocoo.org/show/146451/ |
| 14:46 | mwoelker_ | e.g. a list of edges (relations) for a graph? |
| 14:47 | mwoelker_ | or a map? |
| 14:47 | chouser | mwoelker_: right. like a bag of RDF triples or something. |
| 14:48 | arsatiki | chouser: it seems that body is missing in that response |
| 14:48 | chouser | arsatiki: oh! indeed. |
| 14:48 | mwoelker_ | wouldn't that kill performance for larger graphs? |
| 14:48 | ambient | chouser perfect, thank you. although just a hint into the right direction would be enough :) |
| 14:49 | chouser | well then a hint for the body: ~@body |
| 14:52 | Licenser_ | a very off topic question, how is the clojurebot secured against tempering? I mean how do you ensure that code that is run on it does not affect the host system it runs on? |
| 14:53 | lpetit | ,(System/exit) |
| 14:53 | clojurebot | java.lang.NoSuchFieldException: exit |
| 14:53 | djork | nice |
| 14:53 | lpetit | ,(System/exit 0) |
| 14:53 | clojurebot | java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0) |
| 14:54 | chouser | Licenser_: it's got a range of things -- uses the Java sandbox to prevent access to filesystem and such, uses a blacklist of words to prevent certain kinds of meddling within the sandbox, runs stuff in a separate thread so it can be timed out to prevent consuming host resources, etc. |
| 14:54 | Licenser_ | hmm nice |
| 14:55 | chouser | ,(defmacro if [x y z] `(clojure.core/if x z y)) |
| 14:55 | clojurebot | DENIED |
| 14:55 | Licenser_ | And the JVM provides protection against flooded memory by itself due to it's memory restrictions |
| 14:56 | chouser | ,(while true) |
| 14:56 | serp_ | how does clojure handle recursion between two functions? |
| 14:56 | clojurebot | Execution Timed Out |
| 14:56 | serp_ | a calls b and b calls a |
| 14:56 | Licenser_ | recursively |
| 14:56 | djork | is the clojurebot source available? |
| 14:56 | Licenser_ | that'd be incredible nice |
| 14:56 | serp_ | I understand if it's just one function you can use the recur thing |
| 14:57 | djork | ,"Hello" |
| 14:57 | clojurebot | "Hello" |
| 14:57 | hiredman | serp_: trampoline |
| 14:57 | chouser | serp_: that consumes JVM stack, just as it would in Java. In some cases you can use 'trampoline' to avoid consuming stack. |
| 14:57 | djork | ,*ns* |
| 14:57 | clojurebot | #<Namespace sandbox> |
| 14:57 | Licenser_ | serp_: yes then it's optimized as tail recursion (in a kind of iterative way) |
| 14:57 | chouser | clojurebot: where are you? |
| 14:57 | clojurebot | http://github.com/hiredman/clojurebot/tree/master |
| 14:58 | Licenser_ | clojurebot: what did you had for lunch? |
| 14:58 | clojurebot | for is not a loop |
| 14:58 | Licenser_ | interesting diet |
| 14:58 | djork | hah hah |
| 14:58 | serp_ | hiredman, chouser: thanks |
| 14:58 | Licenser_ | ,(doc trampoline) |
| 14:58 | clojurebot | "([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline |
| 14:59 | lpetit | serp_: and you (declare) the first function if you want the stuff to compile |
| 15:00 | chouser | or use letfn |
| 15:00 | serp_ | I see |
| 15:01 | djork | clojurebot: 2d6 |
| 15:01 | clojurebot | I don't understand. |
| 15:01 | djork | clojurebot: 2 d6 |
| 15:01 | clojurebot | Pardon? |
| 15:01 | hiredman | hmmm |
| 15:01 | djork | must not be turned on :) |
| 15:01 | chouser | ,2d6 |
| 15:01 | clojurebot | Invalid number: 2d6 |
| 15:02 | hiredman | 2d6 |
| 15:02 | clojurebot | 4 |
| 15:02 | hiredman | 5d4+5 |
| 15:02 | clojurebot | 18 |
| 15:02 | danlarkin | In the case of nested dosyncs, are internal ones no-ops (essentially)? |
| 15:02 | chouser | danlarkin: I think that's right. |
| 15:03 | djork | huh, so no "clojurebot:" first |
| 15:03 | hiredman | yeah |
| 15:04 | hiredman | Chousuke added a pluginish architecture so I wrote the dice plugin to kind of figure out the ropes |
| 15:04 | danlarkin | chouser: great, so I don't have to worry about the internal one closing the transaction before the outside one gets to finish the rest of its work |
| 15:04 | djork | I just wrote dice rolling yesterday :) |
| 15:05 | chouser | danlarkin: you certainly don't need to worry about that. Looking at the code, it's not quite a no-op -- it's still creates and calls a closure. |
| 15:05 | Licenser_ | wooh let's play some Shadowrun |
| 15:05 | Licenser_ | 100d6 |
| 15:05 | clojurebot | 354 |
| 15:07 | danlarkin | chouser: great, that's what I got from the code too, thank you |
| 15:08 | djork | hah hah |
| 15:12 | mwoelker_ | 2d6 |
| 15:12 | clojurebot | 2 |
| 15:12 | mwoelker_ | 2d6 |
| 15:12 | clojurebot | 11 |
| 15:12 | mwoelker_ | 2d6 |
| 15:12 | clojurebot | 10 |
| 15:12 | mwoelker_ | 0d6 |
| 15:12 | clojurebot | 0 |
| 15:13 | mwoelker_ | -1d6 |
| 15:13 | mwoelker_ | id6 |
| 15:13 | mwoelker_ | 1d1e3 |
| 15:13 | clojurebot | 1 |
| 15:15 | Licenser_ | 1d100000 |
| 15:15 | clojurebot | 6196 |
| 15:17 | ambient | i have no clue why this error pops up: "More than one matching method found: aset" |
| 15:17 | ambient | while trying to run a macro that uses aset outside any function |
| 15:18 | chouser | 10d1 |
| 15:18 | clojurebot | 10 |
| 15:18 | ambient | 6d0 |
| 15:18 | Chousuke | hmmh |
| 15:19 | Chousuke | I don't think I'm going to solve this problem today... :P |
| 15:19 | Licenser_ | Chousuke: what is your problem? |
| 15:19 | Chousuke | "clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn" hooray for informative error messages |
| 15:19 | Licenser_ | roll a dice to help you decide! |
| 15:20 | Licenser_ | I think I had that yesterday - same message |
| 15:20 | Licenser_ | problem for me was that I had a () too much around my code |
| 15:20 | Licenser_ | I used next instead of second :P |
| 15:20 | Chousuke | the problem is, that comes from core.clj :P |
| 15:20 | Licenser_ | wooh! |
| 15:20 | Licenser_ | you broke it! |
| 15:21 | Licenser_ | I have the feeling that is bad |
| 15:21 | Chousuke | because I'm compiling it with the version of clojure that resulted from compiling my clojure-reader-clojure with the java-reader-clojure |
| 15:22 | Chousuke | so it's most likely that my reader is producing something that confuses the compiler |
| 15:22 | chouser | ambient: what are your args to aset? |
| 15:22 | Licenser_ | ah |
| 15:22 | hiredman | Chousuke: I have my reader plugged into build.xml, the first ant run it builds clojure.jar and reader.jar and subsequent runs it uses the reader from reader.jar instead of LispReader |
| 15:23 | Licenser_ | why does everyone want a own reader? |
| 15:24 | ambient | using ~(with-meta a {:tag 'doubles}) seems to break something essential |
| 15:24 | ambient | inside a macro |
| 15:24 | Chousuke | hiredman: that's about what I'm doing, too. I guess :P |
| 15:24 | chouser | Licenser_: so we can use whitespace and indentation instead of parens. |
| 15:24 | hiredman | this is my first time metacirculating a language |
| 15:24 | Chousuke | me too. :P |
| 15:24 | hiredman | so figuring out where to put the indirection and stuff is interesting |
| 15:24 | ambient | i'm actually programming a metacircular language... |
| 15:25 | Licenser_ | hiredman, Chousuke: why don't you combine your work? |
| 15:25 | Chousuke | but it'll be even more fun when clojure no longer needs java to actually compile itself |
| 15:25 | neotyk | Hi *, what is your single favorite feature of clojure? |
| 15:25 | G0SUB | Where can I find the two Wiki pages on datatypes and protocols that Rich published? |
| 15:25 | lpetit | ~datatypes |
| 15:25 | clojurebot | http://www.assembla.com/wiki/show/clojure/Datatypes |
| 15:25 | lpetit | ~protocols |
| 15:25 | clojurebot | http://www.assembla.com/wiki/show/clojure/Protocols |
| 15:26 | G0SUB | neotyk: sequences. |
| 15:26 | Chousuke | G0SUB: assembla for everything :) |
| 15:26 | G0SUB | Chousuke: heh |
| 15:26 | Licenser_ | neotyk: paralelity |
| 15:26 | neotyk | I'm just learning but so far destructuring rocked me |
| 15:26 | ambient | neotyk parentheses |
| 15:26 | arsatiki | ambient :) |
| 15:26 | hiredman | I am really interested to see Chousuke's reader |
| 15:26 | chouser | ambient: this works for me: (let [ary (into-array Double/TYPE [1 2 3 4 5])] (dalet ary [a 0, b 1, c 2, d 3] [a b c d])) |
| 15:27 | hiredman | and how he is building/using it |
| 15:27 | Chousuke | hiredman: I'll push my current work on github and tell you how to build it. :P |
| 15:28 | hiredman | Chousuke: how are you getting the reader to run before clojure is loaded? |
| 15:28 | djork | neotyk: The way it takes the suck out of Java. |
| 15:28 | Licenser_ | I undertand how it would work with identation but doesn't that mean I have to use a newline for everything? |
| 15:29 | ambient | chouser this doesn't for me: http://paste.pocoo.org/show/146471/ |
| 15:29 | chouser | Licenser_: I was kidding about the reader, though I think there actually is one for whitespace somewhere. |
| 15:29 | Licenser_ | o.o |
| 15:29 | chouser | Licenser_: I think hiredman and Chousuke are just writing readers for fun while secretly hoping rhickey ends up using them in cinc. :-) |
| 15:30 | G0SUB | Chousuke: what reader? any links? |
| 15:30 | Licenser_ | muhaha |
| 15:30 | Licenser_ | Well one thing I didn't yet found isa nice parser generator :/ I got too used to having one |
| 15:31 | ambient | well i construct domain spesific languages with lisp for solving problems so parser generator is not so critical ;) |
| 15:31 | Chousuke | http://github.com/Chousuke/clojure/tree/reader-integrated |
| 15:32 | Chousuke | it's... quite a mess, still :P |
| 15:32 | chouser | ambient: try (double ~val) instead of just ~val in your macro |
| 15:32 | G0SUB | Chousuke: what are the features? |
| 15:32 | hiredman | my reader is a fn with all the pieces contained in a letfn, so I keep track of the classname of the enclosing Fn |
| 15:33 | Chousuke | G0SUB: features? :) |
| 15:33 | Chousuke | G0SUB: it's just a clojure reader written in clojure :P |
| 15:33 | G0SUB | ah, cool |
| 15:34 | Chousuke | a rather simple one, too. |
| 15:34 | hiredman | http://github.com/hiredman/clojure/tree/readerII |
| 15:34 | Licenser_ | ambient: but if you want to write a interpreter a DSL isn't the way to go :P |
| 15:34 | ambient | chouser works, ty |
| 15:35 | hiredman | http://github.com/hiredman/clojure/blob/readerII/src/clj/clojure/reader.clj it's an incomplete port of LispReader |
| 15:36 | hiredman | Chousuke: gen-class never worked for me |
| 15:37 | Chousuke | I don't actually use gen-class with my reader |
| 15:37 | hiredman | loading the gen-class'ed class always seem to try and load clojure |
| 15:37 | Chousuke | the ClojureReader thing is a left-over from an earlier attempt. |
| 15:38 | lpetit | Licenser_ : there's fn-parse, and also cgrand is writing parsley (both are on github) |
| 15:39 | Licenser_ | I looked at fn-parse but since last time I worked with racc (something yacc related) it is really hard to understand |
| 15:39 | Chousuke | I suppose a proper parser combinator would be much better :/ |
| 15:39 | hiredman | Chousuke: so you load core, then your reader, then reload core using your reader? |
| 15:39 | Chousuke | hiredman: yes. |
| 15:41 | Licenser_ | Chousuke: but they are hard to understand :P |
| 15:41 | hiredman | interesting |
| 15:44 | lpetit | parsley has the interesting property of being an incremental parser |
| 15:45 | Licenser_ | hmm parsley |
| 15:45 | Licenser_ | I see it is well documented :P |
| 15:45 | lpetit | but still in inception, not really for prime use / production purpose. But interesting to keep on the radar (We intend to use it for static analysis / user code writing assistance in counterclockwise) |
| 15:46 | lpetit | wait a min., I've something for ya |
| 15:46 | Licenser_ | An experimental undocumented parser lib/DSL. Hah! |
| 15:48 | chouser | Licenser_: pretty sure that's the wrong way 'round. |
| 15:48 | lpetit | clojurebot: parsley is an incremental parser with docs at http://wiki.github.com/cgrand/parsley/design-notes and at http://cloud.github.com/downloads/cgrand/parsley/parsley.pdf |
| 15:48 | clojurebot | Roger. |
| 15:48 | lpetit | ~parsley |
| 15:48 | clojurebot | parsley is an incremental parser with docs at http://wiki.github.com/cgrand/parsley/design-notes and at http://cloud.github.com/downloads/cgrand/parsley/parsley.pdf |
| 15:48 | ambient | but what are sage, rosemary and thyme? |
| 15:48 | lpetit | note those are design notes : subject to change (if not already) :) |
| 15:48 | Licenser_ | chouser: why? |
| 15:49 | Licenser_ | I want to see if I can do it :P I wrote one in ruby - not perfect but it does a lot already |
| 15:50 | serp_ | ambient: they are spices |
| 15:51 | chouser | Licenser_: because I want to write more clojure (perhaps where only JavaScript is supported), not vice versa. |
| 15:51 | somnium | the day when the DOM can be scripted in pure-clojure will be a beautiful day indeed |
| 15:51 | hiredman | Chousuke: I am going to ask rhickey about exposing LispReader has Fn bound to something like READER in clojure.core, then removing all direct calls to LispReader/read in favor of going through the Fn |
| 15:52 | Licenser_ | but chouser when you implement clojure in javascript and I implement javascript in clojure we can run clojure code in javascript in clojure in javascript in clojure in javascript in safari! |
| 15:53 | G0SUB | odd, use of transients actually made the example code slower on my machine. |
| 15:53 | Licenser_ | and then chouser we will rule the world! |
| 15:57 | cgrand | lpetit please use the future tense when talking about parsley :-) |
| 16:02 | chouser | Licenser_: heh |
| 16:02 | rlb | Is re-split probably the most efficient way to split a string at (a single) tab, or is there something simpler that might be faster? |
| 16:02 | Licenser_ | Another question, is there a good way to scan a string to tokenize it? |
| 16:02 | chouser | somnium: that day already came and went. :-/ |
| 16:02 | rlb | i.e find index and substr or similar... |
| 16:02 | Licenser_ | I wrote a own function re-scan but I fear it's horrible ineffective |
| 16:05 | somnium | chouser: I was thinking something between clojurescript and scriptjure, 'browjure'? whatever it is it has to play nice with all the js libraries out there. Are you still working on ClojureScript? |
| 16:05 | Licenser_ | http://gist.github.com/216251 |
| 16:06 | chouser | somnium: ClojureScript's on hold until cinc |
| 16:06 | Licenser_ | if someone want to take a look |
| 16:07 | Licenser_ | sadly I don't think this will return a lazy seq :P |
| 16:08 | somnium | ,(doc re-seq) |
| 16:08 | clojurebot | "([re s]); Returns a lazy sequence of successive matches of pattern in string, using java.util.regex.Matcher.find(), each such match processed with re-groups." |
| 16:11 | Licenser_ | somnium: I know but that only works if you have one regexp not if you've multiple |
| 16:12 | chouser | Licenser_: you've considered combining your regexs using | ? |
| 16:12 | Licenser_ | yes that a) gets ugly and b) I don't know which regexp matched in the end - which isn't too good |
| 16:13 | somnium | Licenser_: if you don't like ugly best to stay away from regex altogether :-p |
| 16:13 | Licenser_ | heh |
| 16:13 | chouser | well, you could combine them programmatically so you don't have to look at them all together. ...knowning which matched might to tough -- no named groupings in Java |
| 16:14 | Licenser_ | I think java allowed named groupings |
| 16:16 | lpetit | cgrand: Oh it's was just an easy way to place some more pressure on parsley's planning :) |
| 16:16 | Licenser_ | well no it does not seem to have |
| 16:20 | somnium | Licenser_: have you looked at partition and grep in contrib.str-utils2 ? |
| 16:20 | Licenser_ | nope never heared of them |
| 16:20 | Licenser_ | ,(doc grep) |
| 16:20 | clojurebot | "clojure.contrib.str-utils2/grep;[[re coll]]; Filters elements of coll by a regular expression. The String representation (with str) of each element is tested with re-find." |
| 16:21 | Licenser_ | ,(doc partition) |
| 16:21 | clojurebot | "([n coll] [n step coll] [n step pad coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap. If a pad collection is supplied, use its elements as necessary to complete last partition upto n items. In case there are not enough padding elements, return a partition with less than n items." |
| 16:22 | somnium | partition is in core, not sure how to get the doc from str-utils2 out of him |
| 16:22 | Licenser_ | ,(doc clojure.contrib.str-utils2/partition) |
| 16:22 | clojurebot | I don't understand. |
| 16:23 | somnium | ,(doc split) |
| 16:23 | clojurebot | "clojure.contrib.str-utils2/split;[[s re] [s re limit]]; Splits string on a regular expression. Optional argument limit is the maximum number of splits." |
| 16:25 | Licenser_ | I will try to just run the regexp over the stuff twice, once to tokenize it and once ti determine the kind of tiken |
| 16:26 | somnium | clojure.walk is useful if you're building ASTs |
| 16:27 | somnium | so one day you can do away with rhino and script java through clojure back to java ;) |
| 16:36 | djork | raise your hand if you're using clojure-mode and slime |
| 16:40 | The-Kenny | *raises hand* |
| 16:41 | Dawgmatix | *raises hand* |
| 16:45 | jasapp | I am |
| 16:46 | eyeris | Is there any CSV stuff in contrib? |
| 16:49 | djork | how do you set up your working environment so that you can load files properly |
| 16:49 | djork | I'm not sure if that question even makes sense |
| 16:49 | jasapp | what do you mean load files? |
| 16:49 | djork | but I have classpath problems using slime and working on projects |
| 16:50 | djork | or just what are project layout and file loading/inclusion practices in general? |
| 16:50 | Licenser_ | ,(doc walk) |
| 16:50 | clojurebot | Huh? |
| 16:50 | Licenser_ | ,(doc clojure.walk) |
| 16:50 | clojurebot | java.lang.ClassNotFoundException: clojure.walk |
| 17:06 | Kjellski | Can someone tell me how the regular expression escape for an uppercase character is? \u doesn´t work... |
| 17:09 | stuartsierra | [A-Z] |
| 17:09 | Licenser_ | Kjellski: one so- what stuartsierra saied |
| 17:11 | Kjellski | okay... thanks... was just looking for the java doc... are there any differences? |
| 17:11 | stuartsierra | some; look up java.util.regex.Pattern |
| 17:11 | Kjellski | Thanks! |
| 17:11 | stuartsierra | welcome |
| 17:11 | rlb | In my case, I just wanted the fastest way to grab everything up to the first tab from a bunch of strings -- wonder if (subs s (.indexOf s tab)) is preferable -- have to test. |
| 17:11 | technomancy | djork: are you using M-x swank-clojure-project? |
| 17:11 | technomancy | C-c C-k should just work |
| 17:12 | djork | nope, no swank-clojure-project |
| 17:12 | djork | does that come with the whole kit? |
| 17:12 | djork | (not working on clojure right this second...) |
| 17:13 | technomancy | djork: you'll have it if you did M-x clojure-install |
| 17:13 | djork | oh ok, cool |
| 17:14 | rlb | Hmm, so (.indexOf s "\t") works, but (.indexOf s (int \t)) doesn't, though java has a str.indexOf(int character). |
| 17:15 | Kjellski | This is going to be an stream closed error, does anyone know why? |
| 17:15 | Kjellski | (with-open [rdr (reader *text-file-path*)] |
| 17:15 | Kjellski | (filter #(re-find #"[A-Z]" %) (line-seq rdr))) |
| 17:16 | technomancy | Kjellski: filter is lazy; so the reader is closed by the time it gets consumed |
| 17:17 | technomancy | either consume it inside the with-open block or wrap filter in a doall |
| 17:17 | Kjellski | *doh* ... thanks |
| 17:18 | rlb | (Oh, right *\tab*, not \t...) |
| 17:24 | rads | I'm trying out redis-clojure, and for now I've had to wrap (redis/with-server) around the forms in every function that accesses redis. is there an idiomatic way of abstracting that? |
| 17:37 | Licenser_ | hmmm one problem I run into is that when using combined regexp it does not match in the right order o.O |
| 18:01 | Kjellski | I´ve got a pretty stupid question for you advanced, but I can´t get how to accumulate values in a function... |
| 18:01 | Licenser_ | define accumulate :P |
| 18:01 | Licenser_ | while I |
| 18:01 | Licenser_ | 'm not advanced I am always curiose! |
| 18:01 | Licenser_ | and I really have trouble with the ' on the english keybard ... |
| 18:01 | Kjellski | 1 sec... I´ll post an example of my function ok? |
| 18:01 | Licenser_ | YaY! |
| 18:02 | Kjellski | ,(defn read-with-filter [file regx] |
| 18:02 | Kjellski | (with-open [rdr (reader file)] |
| 18:02 | Kjellski | (let [result []] |
| 18:02 | Kjellski | (doseq [line (line-seq rdr)] |
| 18:02 | Kjellski | (doseq [line-char line] |
| 18:02 | Kjellski | (if (Character/isUpperCase line-char) |
| 18:02 | clojurebot | EOF while reading |
| 18:02 | Kjellski | (conj result line-char)))) |
| 18:02 | Kjellski | result))) |
| 18:03 | jasapp | Try putting it here: http://pastebin.com/ |
| 18:04 | Kjellski | *ugly*http://paste.lisp.org/display/89128 |
| 18:05 | Kjellski | I´m trying to find the uppercase characters in a file ang conj them into a result... |
| 18:06 | Kjellski | That this doesn´t work is what I would aspect from immutable result, but how can I accumulate the values I need? I´ve tryed loop, but how to tailcall in nested doseqs? |
| 18:07 | chouser | Kjellski: doseq and for both do nesting for you, so you could say (for [line (line-seq rdr), line-char line] ...) |
| 18:08 | Kjellski | ups, the second argument of the function is not used anymoro... |
| 18:08 | chouser | Kjellski: both doseq and for also support :when which you could use instead of 'if' |
| 18:08 | Kjellski | okay? so the complete nesting could be removed with one for? |
| 18:08 | djork | Kjellski: (loop [coll []] (recur (conj stuff coll))) |
| 18:09 | djork | that's what I've found to work for building collections |
| 18:09 | djork | err, (conj coll stuff) |
| 18:09 | chouser | Kjellski: then instead of calling conj manually, the body of the 'for' could just return line-char |
| 18:09 | Kjellski | inside the if statement? |
| 18:10 | chouser | Kjellski: that'll give you a lazy seq of the uppercase chars, but since you're in a with-open you'd want to wrap your 'for' with 'vec' or 'doall' |
| 18:11 | Kjellski | Sure, but would there be a way to, just for educational purposes, "save" the state of reading in order to make it "lazy-with-open"? |
| 18:14 | chouser | Kjellski: when would you close the file? |
| 18:15 | wwood | I'm trying to setup liverepl on mac os x |
| 18:15 | wwood | http://github.com/djpowell/liverepl |
| 18:15 | Kjellski | ^^ ... I know you would ask, for easyness, after the last value is taken from the lazy-seq? |
| 18:15 | wwood | liverepl.sh is looking for tools.jar in jdk home |
| 18:15 | wwood | but /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home doesn't have tools.jar |
| 18:16 | wwood | anyone more clueful than I about that? |
| 18:17 | wwood | think I found the answer |
| 18:17 | wwood | tools.jar does not exist. Classes usually located here are instead included in classes.jar. Scripts that rely on the existence of tools.jar need to be rewritten accordingly. |
| 18:17 | wwood | from http://developer.apple.com/mac/library/documentation/Java/Conceptual/Java14Development/02-JavaDevTools/JavaDevTools.html |
| 18:21 | chouser | Kjellski: yes it's possible (contrib duck-streams has such a thing) but it's a bit dangerous since normally failing to consume a whole seq is fine, but one of these seqs will leak filehandles if you don't consume it. |
| 18:22 | wwood | found it |
| 18:23 | wwood | under Versions/1.6.0/classes/classes.jar |
| 18:23 | Kjellski | Okay, but that behaviour is necessary right? If the duckstream keeps opened, the file handles state remains open and the lazy-seq will too... hope you understand what I mean... but a more important question, how have you found that out? What have you typed in google or where have you searched? maybe clojure.org -> api -> duck-streams? |
| 18:24 | Kjellski | I think it´s pretty hard to find informations with examples for learning clojure on the net.... |
| 18:25 | somnium | Kjellski: browsing the source code in contrib is a good way to get familiar with the libraries (there are a lot, I know) |
| 18:27 | Kjellski | somnium thanks, that is something i´ve never tryed before ^^... |
| 18:27 | Kjellski | -y +ie |
| 18:27 | chouser | (doc read-lines) |
| 18:27 | clojurebot | "clojure.contrib.duck-streams/read-lines;[[f]]; Like clojure.core/line-seq but opens f with reader. Automatically closes the reader AFTER YOU CONSUME THE ENTIRE SEQUENCE." |
| 18:28 | lisppaste8 | foomanchoo pasted "Abtract Class" at http://paste.lisp.org/display/89129 |
| 18:28 | foomanchoo | Hi All |
| 18:28 | Kjellski | Hi foomanchoo =) |
| 18:28 | foomanchoo | learning (or trying to learn clojure) and hit a snag trying to gen class an abtract class |
| 18:28 | foomanchoo | it is in the above paste |
| 18:29 | chouser | foomanchoo: no need for genclass there -- just proxy |
| 18:29 | foomanchoo | proxy... ok, I will try that. thank you |
| 18:30 | Kjellski | thanks chouser, thats what i wanted to know... ^^ |
| 18:35 | wwood | that worked! |
| 18:35 | wwood | liverepl cool! |
| 18:36 | Kjellski | Congratulations! |
| 18:36 | Kjellski | =) |
| 18:38 | rads | what's the simplest way to convert :foo to "foo"? |
| 18:38 | rads | (str :foo) returns ":foo" |
| 18:39 | danlarkin | ,(name :foo) |
| 18:39 | clojurebot | "foo" |
| 18:39 | rads | thanks |
| 18:40 | hiredman | I have come to a conclusion |
| 18:40 | hiredman | ant is horrible |
| 18:40 | mtm | all build systems are horrible |
| 18:41 | hiredman | make is great |
| 18:41 | mtm | does it still require hard tabs? |
| 18:41 | hiredman | who cares |
| 18:41 | mtm | it offends my delicate sensibilities :) |
| 18:42 | authentic | clj noob question: has something like GWT been made for clojure? |
| 18:42 | hiredman | I am just sick in tired of ant rerunning everything when nothing has changed |
| 18:42 | hiredman | or not running anything |
| 18:42 | authentic | mtm: i'd say all imperative build systems are terrible, ant is full of do-this and do-that rather than make-me-an-X |
| 18:43 | mtm | true, true |
| 18:48 | Kjellski | Why is this(http://paste.lisp.org/display/89130) function giving me a seq over one element vectors? |
| 18:50 | hiredman | becuase you are using conj to create a new vector that contains one more element than an empty vector |
| 18:51 | Chousuke | for is not a loop |
| 18:51 | Chousuke | ~for |
| 18:51 | clojurebot | for is not used often enough. |
| 18:51 | djork | hah |
| 18:51 | hiredman | and conj does not mutate vectors |
| 18:51 | Chousuke | clojurebot: you were supposed to agree with me |
| 18:51 | clojurebot | It's greek to me. |
| 18:52 | hiredman | clojurebot: laugh |
| 18:52 | clojurebot | ha ha |
| 18:52 | authentic | clojurebot: cry |
| 18:52 | clojurebot | Gabh mo leithscéal? |
| 18:53 | Chousuke | Kjellski: You seem to have this silly notion that clojure allows you to *mutate* things. It does, but not until you've passed intermediate level. I suggest you prepare to rewire your brain entirely :) |
| 18:54 | djork | I was wrestling with this same thing yesterday. |
| 18:54 | cemerick | interesting, looks like transients aren't metadata-friendly |
| 18:55 | funkenblatt | authentic: there's clojurescript |
| 18:55 | funkenblatt | wrt a GWT-like thing |
| 18:56 | funkenblatt | dunno how complete it is though |
| 18:56 | Kjellski | Don´t tell me to rewrite my brain an forget to tell how ...^^ |
| 18:56 | Chousuke | Kjellski: for generates a sequence, so you can just change the body of your for to "line-char" and you get a sequence of characters, appropriately filtered. |
| 18:57 | Chousuke | Kjellski: then you can use either (into [] (for ...)) or (vec (for ...)) or (reduce conj [] (for ...)) to create a vector of those characters |
| 18:57 | Kjellski | outch... THAT hurts... btw, today is CAPSLOCK day, isn´t it? ^^ |
| 18:57 | AWizzArd | rhickey: please delete ticket 197 on assembla (count in hashmaps is already fixed) |
| 18:57 | authentic | funkenblatt: thanks, i'll have a look |
| 18:58 | hiredman | clojurebot: ticket #197 |
| 18:58 | clojurebot | {:url http://tinyurl.com/yh7w68h, :summary "Field 'count' not updated correctly for 'PersistentHashMap's when three hashes collide", :status :new, :priority :normal, :created-on "2009-10-15T19:41:24+00:00"} |
| 18:59 | Chousuke | AWizzArd: would just closing it do? :/ |
| 18:59 | Chousuke | in fact, that's probably better than deleting it. just close as invalid or fixed |
| 19:00 | Kjellski | clojurebot: ticket #197 |
| 19:00 | clojurebot | {:url http://tinyurl.com/yh7w68h, :summary "Field 'count' not updated correctly for 'PersistentHashMap's when three hashes collide", :status :new, :priority :normal, :created-on "2009-10-15T19:41:24+00:00"} |
| 19:00 | Kjellski | ...sorry... |
| 19:00 | lpetit | ouch what a spam on my emailbox ! |
| 19:00 | AWizzArd | Chousuke: yes |
| 19:00 | Chousuke | lpetit: from assembla? :/ |
| 19:01 | lpetit | yeah |
| 19:01 | AWizzArd | lpetit: what do you mean? those 70 mails within 3 minutes? ;) |
| 19:01 | lpetit | sure :) |
| 19:01 | Chousuke | AWizzArd: Are you not a clojure contributor? If you are, you could just close it yourself. |
| 19:02 | lpetit | When Rich commits, he doesn't do half the job ! :) |
| 19:02 | Chousuke | lpetit: you can reduce the spamming to bearable levels from the preferences somewhere. |
| 19:02 | AWizzArd | Chousuke: nope, not snail mailed the form yet |
| 19:02 | Chousuke | heh. should remember those "fixes #123" in the commit message |
| 19:02 | lpetit | Chousuke: oh yes, I'll have to dig in the options of assembla maybe ? |
| 19:03 | Chousuke | AWizzArd: which commit was it fixed by? |
| 19:03 | Chousuke | hmm, b4095306ddc59c1a992c39369f06f1315b97d377 probably |
| 19:04 | hiredman | I heard contributors get a secret decoder ring |
| 19:04 | Chousuke | well, I marked it as fixed now. |
| 19:04 | Chousuke | enjoy your spam |
| 19:04 | Kjellski | Chousuke: Thanks a lot... actually I´ve saved the that above to my notes ... |
| 19:05 | Chousuke | Kjellski: the key to functional programming is recursion |
| 19:06 | Chousuke | instead of looping and mutating the value, you create a new value within the function, and then call the function again on the new value (and possibly other modified parameters) to generate the next value, until you hit the base case |
| 19:07 | Chousuke | the "loop" form, while not a function, is recursive like this too; you always need to "restart" the loop by calling recur with the new values. |
| 19:10 | AWizzArd | hiredman: when one wears the ring... is one visible? |
| 19:14 | hiredman | it is a metacircular ring |
| 19:15 | Raynes | The key to functional programming is a functional key. It fits in the lock upside down and right side up. I hear you can even insert it sideways. |
| 19:23 | djork | I read the Little Schemer last Summer, but I have a hard time applying it to Clojure for some reason. |
| 19:23 | Chousuke | Raynes: but curiously enough, once you turn the key, you will suddenly have two locks. |
| 19:23 | djork | I wonder why? |
| 19:23 | djork | s/read/did/ |
| 19:24 | djork | Philosophical question: is the cosmos functional or object-oriented? |
| 19:24 | djork | Functional would mean a multiverse. |
| 19:24 | Kjellski | Chousuke : thanks for this decription... it brings me steps forward... as i keep reading the same sentences again and again... ^^ |
| 19:25 | djork | Kjellski: http://www.google.com/search?client=safari&rls=en&q=define:recursion&ie=UTF-8&oe=UTF-8 (notice the "did you mean") |
| 19:25 | jasapp | djork: http://xkcd.com/224/ |
| 19:25 | hiredman | djork: have you see the slides from rhickey's jvmlang summit presentation? |
| 19:25 | djork | I think I had them on my desktop for a long time |
| 19:25 | djork | glanced at them |
| 19:25 | djork | jasapp: yes, hilarious :) |
| 19:26 | Chousuke | infinite recursion is not very useful though :/ |
| 19:26 | The-Kenny | There is another very good one about lisp, but I don't remember the name. |
| 19:26 | hiredman | awn quotes like "the future is a function of the present" or some such |
| 19:26 | Chousuke | of the past |
| 19:27 | Chousuke | and present is (deref universe) :P |
| 19:29 | Kjellski | Someone knows who intentionally said the notepad irc thing? |
| 19:30 | Kjellski | "IRC is just multiplayer notepad..." |
| 19:31 | hiredman | clojurebot: #clojure |
| 19:31 | clojurebot | clojure is far closer to perfection then python |
| 19:31 | hiredman | bah |
| 19:31 | djork | ~clojurebot |
| 19:31 | clojurebot | clojurebot is like life: you make trade-offs |
| 19:33 | djork | clojurebot: python |
| 19:33 | clojurebot | python is ugly |
| 19:33 | djork | ouch |
| 19:33 | djork | clojurebot: ruby |
| 19:33 | clojurebot | Chunky bacon! |
| 19:33 | djork | Hear hear! |
| 19:33 | djork | clojurebot: Java |
| 19:33 | clojurebot | ☕ |
| 19:33 | djork | this is fun |
| 19:34 | djork | clojurebot: c# |
| 19:34 | clojurebot | I don't understand. |
| 19:34 | djork | neither do I |
| 19:35 | jasapp | clojurebot: lisp |
| 19:35 | clojurebot | "if you never learnt Lisp, then you never learned to program" -- some rant on some blog somewhere |
| 19:35 | Kjellski | ^^ |
| 19:36 | The-Kenny | clojurebot: brainfuck |
| 19:36 | clojurebot | excusez-moi |
| 19:38 | ambient | so, are there any clojure versions for the shootout? http://shootout.alioth.debian.org/ |
| 19:38 | hiredman | clojurebot: #clojure |
| 19:38 | clojurebot | this is not IRC, this is #clojure. We aspire to better than that. |
| 19:38 | djork | clojurebot: IRC |
| 19:38 | clojurebot | Pardon? |
| 19:39 | djork | ambient: I have never seen any, but it would be interesting to see how high you can go. |
| 19:39 | ambient | well, you could write non-idiomatic clojure and make it quite fast |
| 19:39 | djork | I mean the Java steady-state stuff is pretty much a total hack... and so Clojure would never get that fast. |
| 19:39 | djork | it would be interesting to see how idiomatic clojure fares though |
| 19:40 | ambient | i did my modular synth functionally, took about 5 seconds to render. imperically the same thing took 100 milliseconds |
| 19:40 | djork | imperically? |
| 19:40 | ambient | i dont know the word |
| 19:40 | djork | or imperatively |
| 19:40 | ambient | something like that |
| 19:41 | ambient | but the slowness might've been because of lazy sequences |
| 19:41 | djork | in Java? |
| 19:41 | ambient | in clojure |
| 19:41 | djork | oh, nice |
| 19:41 | djork | how much audio were you producing? |
| 19:41 | djork | (hopefully more than 100 ms) |
| 19:41 | ambient | 2 seconds |
| 19:41 | ambient | 88k samples |
| 19:42 | djork | k |
| 19:42 | ambient | but the whole thing's not done yet, so it's just a semi-micro benchmark |
| 19:43 | djork | so is it better to set up clojure to run with java -sever |
| 19:43 | djork | server |
| 19:46 | ambient | i'll tell you when i get to the point where it's actually relevant :) |
| 19:46 | ambient | performance-wise |
| 19:52 | Kjellski | is there a lazy "pi-digits" function in a lib someone knows? |
| 19:57 | mattrepl | random question, wasn't there a video posted of Rich Hickey's talk on time/concurrency at the JVML summit? |
| 19:57 | mattrepl | google isn't helping |
| 19:57 | Qvintvs | does anyone know of a gedit plugin for clojure editing? |
| 19:57 | Kjellski | ... enough hacker-quests for today, good night! |
| 19:58 | foomanchoo | ah... to-array and into-array.. a bit confusing but finally got it |
| 19:58 | hiredman | mattrepl: not yet |
| 19:59 | mattrepl | could've sworn I watched it.. weird =) thanks |
| 20:02 | scottj | Can you define a stored procedure in MySQL over the jdbc connecting with clojure.contrib.sql? |
| 20:07 | somnium | (use 'mongo.config) |
| 20:12 | tomoj | wow, apparently you could somewhat easily write your couchdb views in clojure |
| 20:13 | The-Kenny | tomoj: Yeah, it should be pretty easy to write a view-server in clojure. |
| 20:13 | The-Kenny | (I remember seeing one somewhere on github) |
| 20:15 | tomoj | cool |
| 20:15 | tomoj | first I must grok couchdb |
| 20:16 | The-Kenny | tomoj: http://github.com/tashafa/clutch/blob/master/src/com/ashafa/clutch/view_server.clj |
| 20:16 | The-Kenny | (I don't know how advanced this server is, I just found it :)) |
| 20:18 | somnium | http://paste.lisp.org/display/89135 <- any suggestions? |
| 20:48 | rhickey | hrm, the first graphic here puzzles me: http://fupeg.blogspot.com/2009/10/concurrency-patterns-java-scala-and.html |
| 20:49 | ambient | heh, nice graphics. |
| 20:50 | ambient | -s |
| 20:53 | rlb | I didn't realize that the jvm doesn't support tagged pointers (though it seems there's been some consideration of it). |
| 20:57 | Licenser_ | I wonder how you can devide Code Correctly by Comprehend |
| 21:00 | Licenser_ | How does scalar resolves the concurrency part task? |
| 21:02 | ambient | i parsed from the text that he meant coding correctly and comprehending are almost the same thing |
| 21:03 | ambient | so the "/" is not a division, but interchangeability |
| 21:03 | Licenser_ | :P ambient I know no reason not to make fun out of it |
| 21:08 | Licenser_ | rhickey: don't let the post draw you down, I is anything but scientific just an personal oppinion from what I can tell after reading |
| 21:16 | somnium | I saw on a mailing list that the Lift guy gave a presentation at E-Bay recently, maybe they drank the scala kool-aid while he was there |
| 21:16 | Licenser_ | heh |
| 21:20 | rhickey_ | Licenser_: it doesn't bother me at all, just puzzling - I think refs are a much easier thing to understand (managed variables) than switching to message passing, if you haven't been doing the latter |
| 21:20 | Licenser_ | glad to hear that :) |
| 21:29 | Licenser_ | so what surprised me most is that scalar is suppost to be faster then java? |
| 21:31 | somnium | can scala's actors be coordinated like clojure's refs? (for a consistent snapshot of the world) |
| 21:32 | chouser | not likely. actors tend to be more like Clojure agents |
| 21:33 | chouser | though with actors it usually requires a round-trip message to get their current state |
| 21:33 | chouser | I think this is true of both erlang and scala actors |
| 21:33 | Licenser_ | on another note, comojure is darn fast o.O |
| 21:33 | somnium | in that case, it seems like the guy who wrote this blog is barely familiar with clojure at all, since he's comparing scala's actors with clojure's refs |
| 21:33 | rhickey_ | no, he recognizes the coordination difference and notes it at the end |
| 21:33 | Licenser_ | just for fun I ran apache benchmark against a simple website, it gets 180 reqs/s on my machine |
| 21:37 | scottj | Licenser_: a simple compojure website right? Have you done any similar benchmarks against simple php/apache or other apps? |
| 21:37 | Licenser_ | scottj: with ruby I don't tuch PHP |
| 21:38 | Licenser_ | not the exact same thing but a simple RoR is a good bit slower I think it was < 100 |
| 21:39 | Licenser_ | but again RoR does a lot of things like caching & stuff the compojure app is really stupid about it right now - no caching no nothing |
| 21:43 | Licenser_ | wow after warming up its get to 250 reqs/s |
| 21:45 | devlinsf | Hey, does anyone know why there are 100 patches being applied right now? |
| 21:45 | rhickey_ | devlinsf: just merging master into a branch |
| 21:45 | devlinsf | Oh, okay |
| 21:45 | devlinsf | Thanks :) |
| 21:51 | Licenser_ | by the way, why did you people choose git over svn? |
| 21:52 | Licenser_ | disclaimer: No I don't want to start a flame war about git vs svn I just am curiose since I often think about using git instead of svn |
| 21:53 | Raynes | Licenser_: Because Git is better than SVN. ;) |
| 21:53 | Licenser_ | I heard that I just wonder what features are important for the decision ^^ |
| 21:53 | The-Kenn1 | Raynes: Simple answers are the best answers :) |
| 21:53 | rlb | Don't hear about too many people switching back... |
| 21:54 | The-Kenn1 | Licenser_: Because it's decentral, you have the whole history of the project on your harddrive. Really cheap and easy branching is also cool. |
| 21:54 | Licenser_ | that makes sense actually, I hate branching in SVN, or actually not branching but merging |
| 21:55 | The-Kenn1 | Licenser_: You should try git. Then try forking a project in Github and you will never switch back to svn :) |
| 21:56 | Licenser_ | heh I downloaded a few things from github via git, was nice and easy I've to admit |
| 21:57 | Licenser_ | but I'm not sure if the 'fork everything' thing is in the end good, I mean do we really need *checks* 42 forks of clojure |
| 21:57 | Licenser_ | while I agree that 42 is a very good number of forks |
| 21:57 | The-Kenn1 | Licenser_: It's easy to merge back changes. |
| 21:57 | chouser | clojure was on google code svn for a quite a while |
| 21:57 | Licenser_ | hmm so forks are like branches? |
| 21:58 | The-Kenn1 | Licenser_: Yes. But a bit more than that. |
| 21:58 | Licenser_ | ahhh okay, I always had the impression that forks are really forks of the project |
| 21:58 | Licenser_ | I mean always |
| 21:58 | Licenser_ | Usually when you read about a fork it means a copy of the project because someone thinks they can do it better :P |
| 21:59 | Licenser_ | at least that is how I used it |
| 21:59 | The-Kenn1 | They are, but git and especially github makes it very easy to merge back changes from other users. |
| 21:59 | The-Kenn1 | Licenser_: Maybe they can. If the owner thinks that someone improved his project, he merges the changes back into the original :) |
| 22:00 | Licenser_ | I noticed that rhickey himself had like 4 or 5 fokrs that makes 42 forks look a lot scarry |
| 22:01 | The-Kenn1 | Licenser_: These are branches.. |
| 22:01 | The-Kenn1 | Forks are under the "networks" tab: http://github.com/richhickey/clojure/network |
| 22:01 | The-Kenn1 | (They are 41+1 forks :)) |
| 22:02 | Licenser_ | I see 4 forks from rhickey in ther |
| 22:02 | Licenser_ | o.O I just checked rails has over 700 good greif |
| 22:02 | chouser | github forks are just a way to manage your own set of patches against a project |
| 22:02 | The-Kenn1 | rails is a popular project :p Ruby is big on Github. |
| 22:03 | rlb | Licenser_: one key is that git makes all kinds of things *possible* that just aren't possible with say svn -- then you get to decide what you actually want to do. |
| 22:03 | Licenser_ | I'll think I'll try git out for my next project just to get a feel for it |
| 22:03 | mudphone | git == ozmm |
| 22:03 | Licenser_ | the console output of git looks a lot nicer then the one of svn :P |
| 22:04 | rlb | git provides quite a bit of mechanism, and you get quite a bit of freedom wrt policy. |
| 22:04 | Licenser_ | ^^ |
| 22:04 | mudphone | you can get colorization of the output too |
| 22:05 | mudphone | and tab-completion of commands... and set up aliases... :) |
| 22:05 | Licenser_ | yea tab completion is eays I fiddled that together for svn too, it was even completeing file names depending on the action you choose ^^ |
| 22:06 | Licenser_ | then again svn up, and svn commit is what I use 95% of the time |
| 22:06 | The-Kenn1 | Licenser_: git will give you completion for commands, files, branches, tags and everything :) |
| 22:06 | mudphone | I suppose the killer feature for me is branching, painlessly |
| 22:07 | jasapp | somnium: have you gotten very far with mongodb and clojure? |
| 22:07 | somnium | jasapp: yeah, already used it on two projects, right now I' |
| 22:07 | somnium | jasapp: extracting a library so I don't have to copy paste anymore |
| 22:07 | jasapp | how are you going storing objects in mongo? |
| 22:08 | somnium | jasapp: one of the maintainers fixed a bug so clojure hashmaps go right in |
| 22:08 | jasapp | a bug in mongo, or clojure? |
| 22:09 | somnium | strings and numbers, vectors and hashes go in, object-ids are a special object, but they're not hard to coerce to and from strings |
| 22:09 | somnium | in mongo, the json reader wasn't storing nested maps, but he fixed in about 5 minutes when I asked |
| 22:09 | somnium | pretty good service :) |
| 22:09 | jasapp | nice, how recently was this? |
| 22:10 | djork | is a seq generated by iterate memoized or anything? |
| 22:10 | somnium | you can also teach the java api to serialize arbitrary objects, but thankfully in clojure we don't need this too much |
| 22:10 | somnium | jasapp: a couple days ago? the latest on github has the patch, I don't think he bumped the version number |
| 22:10 | jasapp | awesome |
| 22:10 | somnium | I'll probably put my wrapper on github once its a little polished |
| 22:10 | Licenser_ | hmm that sounds damn handy |
| 22:10 | somnium | but the java api is pretty easy as it is |
| 22:11 | jasapp | yeah, that's what I've been using |
| 22:11 | jasapp | although, I've been using their json utils |
| 22:12 | jasapp | as well as contrib.json |
| 22:12 | jasapp | it's pretty ugly |
| 22:13 | Licenser_ | one of the good things to hang out in the channel is that one can read up about new tech when others are talking abou it :P |
| 22:15 | jasapp | cool, thanks for the info |
| 22:15 | jasapp | I'll keep an eye out for your wrapper |
| 22:16 | somnium | jasapp: you don't have to use json, if you coerce everything to a string or number, you just do (doto (BasicDBObject.) (.putAll {"some" "random" "clojure" ["data" "structure"]})) |
| 22:17 | somnium | my library is just some config helpers and some coercion utils, maybe in a day or two? (want to finish it tonight, but I should turn off irc to do that) |
| 22:17 | jasapp | that'll certainly clean things up |
| 22:17 | jasapp | my code was ugly, but the queries were even worse. |
| 22:18 | somnium | I made some wrappers for those too! |
| 22:18 | somnium | right now just (fetch :mycollection :where {:foo "is bar"}) |
| 22:18 | jasapp | wow |
| 22:19 | jasapp | well, if you need any help, I'd be happy to |
| 22:19 | jasapp | but it sounds like you've got it taken care of |
| 22:20 | somnium | my acct is somnium, 0.00001 up in a day or two? I'll be happy for contributions, I think it does really well with clojure |
| 22:20 | jasapp | ok |
| 22:26 | djork | so apparently (take 10000 (fib-seq)) runs out of memory |
| 22:27 | Licenser_ | djork: give it more memory :P |
| 22:27 | djork | I actually meant to use nth not take ;) |
| 22:27 | Licenser_ | teehee |
| 22:27 | djork | still trying to grok this lazy-seq generation business |
| 22:28 | Licenser_ | I find it funny, I made a primes lazy seq ^^ |
| 22:28 | Licenser_ | not that I need it or it would make sense, but it was fun :P |
| 22:28 | somnium | djork: it sounds like its 'holding-the-head' |
| 22:29 | foomanchoo | a proxied class, with an overwritten method, can or can not access a protected field? (it seems it can not) |
| 22:29 | djork | this particular implementation just doesn't click with me, maybe someone could help explain it |
| 22:29 | djork | http://www.pastie.org/666176 |
| 22:30 | djork | hmm, I think I prefer it like this now (edited) |
| 22:33 | djork | OK so lazy-seq just takes one expr and doesn't evaluate it until a seq operation is called on it? |
| 22:37 | somnium | ,(macroexpand-1 '(lazy-seq (iterate inc 1))) |
| 22:37 | clojurebot | (new clojure.lang.LazySeq (fn* [] (iterate inc 1))) |
| 22:37 | djork | hah, nice |
| 22:38 | djork | that helps |
| 22:38 | somnium | er, bad example, iterate is already lazy |
| 22:38 | djork | :) |
| 22:39 | djork | ,(macroexpand-1 '(lazy-seq (cons 1 (inc 1)))) |
| 22:39 | clojurebot | (new clojure.lang.LazySeq (fn* [] (cons 1 (inc 1)))) |
| 22:40 | djork | ,(macroexpand-1 '((fn rfib [a b] (cons a (lazy-seq (rfib b (+ a b))))) 0 1)) |
| 22:40 | clojurebot | ((fn rfib [a b] (cons a (lazy-seq (rfib b (+ a b))))) 0 1) |
| 22:40 | djork | hmm that was not what I was looking for |
| 22:41 | djork | oh well I think I get it now |
| 22:41 | chouser | foomanchoo: proxy cannot access protected fields |
| 22:41 | somnium | ,(source iterate) |
| 22:41 | clojurebot | java.lang.Exception: Unable to resolve symbol: source in this context |
| 22:42 | foomanchoo | chouser: thanks. any ways to work around this? |
| 22:42 | chouser | foomanchoo: unfortunately. For now you'll have to use gen-class after all. |
| 22:42 | foomanchoo | ok... i can't seem to grok gen-class. any good examples? |
| 22:43 | chouser | foomanchoo: uber-proxy is coming (related to new new a.k.a. reify) |
| 22:43 | foomanchoo | cool, i might just create a plain old java class for now and move on |
| 22:44 | Licenser_ | what the hell is reify doing? it sounds look food |
| 22:45 | hiredman | ~google reify |
| 22:45 | clojurebot | First, out of 23600 results is: |
| 22:45 | clojurebot | Reification - Wikipedia, the free encyclopedia |
| 22:45 | clojurebot | http://en.wikipedia.org/wiki/Reification |
| 22:45 | chouser | that's not unreasonable. gen-class can do it in a couple lines to, but if you're comfortable with a little java class you won't be bad off. |
| 22:45 | hiredman | I think reify still doesn't let you create pedal to the medal named classes, which is kind of a pain |
| 22:46 | hiredman | you can instantiate and invoke Fns |
| 22:46 | Licenser_ | " the consideration of an abstraction or an object as if it had living existence and abilities; at the same time it implies the thingification of social relations" |
| 22:46 | hiredman | which is how I bootstrap my reader |
| 22:47 | Licenser_ | ~help |
| 22:47 | clojurebot | http://www.khanacademy.org/ |
| 22:47 | Licenser_ | hrm that was not what I was looking for o.O |
| 22:49 | somnium | I didn't know thingification was a word |
| 22:52 | Licenser_ | well now it is! |
| 22:52 | Licenser_ | wokipedia saied that (amongst other things) about rify |
| 22:52 | Licenser_ | b |
| 22:52 | Licenser_ | u |
| 22:53 | Licenser_ | but it is right we should treat clojurebot better, he has dignity too! |
| 22:53 | Licenser_ | or is clojurebot female? |
| 22:54 | hiredman | hmmm |
| 22:54 | hiredman | I guess I should add tests to clojure.test-clojure.reader as I find things I left out of my reader that the tests don't catch |
| 22:54 | Licenser_ | I think we should rename ',' to 'Good day Mr. Clojurebot, could you please be so kind and evaluate <code> for me'? |
| 22:54 | somnium | I saw something about it being a bad idea to have functions in data, but what's the problem with having a map like {:fun-a (fn [x] x) :fun-b ...} ? |
| 22:56 | Licenser_ | why is it bad to have functions in data? Isn't that one of the good things that of first class functions that you can put them in data? |
| 23:24 | technomancy | somnium: nothing wrong with that |
| 23:25 | Licenser_ | hmm reading p about the mongodb thing makes me really curiose to try that out |
| 23:25 | somnium | technomancy: ok, in my current case I was having trouble envisioning an alternative. |
| 23:26 | technomancy | somnium: of course the person who warned you may have more context... you shouldn't put fns in a map if another alternative like multimethods would be more appropriate. |
| 23:29 | somnium | technomancy: I saw it in an old message on a mailing list. (couldn't find it just now). In this case its a hook for users to add predicates to a library. |
| 23:33 | chouser | multimethods allow for dynamic redefinition where fns in data objects do not |
| 23:33 | chouser | on the other hand, clojure.zip is implemented with functions stored in metadata, so it can't be all bad. :-) |
| 23:34 | technomancy | chouser: not to mention clojure.test... (though the reasoning behind that one escapes me utterly) |
| 23:35 | Licenser_ | fuctions stored in metadata? |
| 23:36 | somnium | do multi-methods transcend namespaces? |
| 23:37 | chouser | somnium: no, multi-methods are rooted in namespaces |
| 23:37 | hiredman | multimethods are not names |
| 23:37 | chouser | I guess defmethods transcend namespaces, but defmultis create namespaced vars |
| 23:38 | somnium | defmethods do? |
| 23:38 | somnium | then that's a more elegant alternative |
| 23:39 | Raynes | Dynamic failcat fails at runtime. |
| 23:42 | jasapp | somnium: have you had trouble with mongo serializing keywords correctly? |
| 23:43 | jasapp | (doto (BasicDBObject.) (.putAll {:foo :bar})) |
| 23:43 | somnium | jasapp: it doesn't do keywords |
| 23:43 | somnium | jasapp I use clojure.walk to coerce members |
| 23:43 | jasapp | Ahh, I didn't realize |
| 23:43 | somnium | if performance is really a concern better to use strings or implement DBObject, but I like the pleasantness of using keywords |
| 23:44 | somnium | at least for the scale of what I've been doing so far |
| 23:44 | jasapp | Hmm, I'm not sure if it'll be a concern |
| 23:44 | jasapp | How large are your data sets typically? |
| 23:45 | somnium | in current case 100,000 records, but small number of users |
| 23:46 | somnium | premature optimization is the root of all evil :) |
| 23:46 | jasapp | That's what I keep telling myself |
| 23:46 | jasapp | I'll see how clojure.walk works for me |