2009-10-06
| 01:13 | slyrus_ | hmm... what's the idiomatic approach when one feels like the would normally use CL's return-from construct? |
| 01:56 | konr | should I read Let Over Lambda? Is it relevant to clojure programming? |
| 02:00 | sdeobald_ | I don't have stu's book in front of me and my googling is failing me. How can (may?) I bind an anonymous function so that it can call/recurse on itself? |
| 02:03 | slashus2 | (fn functionname [] (functionname)) |
| 02:04 | slashus2 | sdeobald: ^ |
| 02:04 | sdeobald_ | Thanks. |
| 02:05 | slashus2 | Or you can use recur |
| 02:06 | sdeobald_ | I'm actually making a weak attempt at converting an SICP exercise, so recur might be cheating and/or going too far. |
| 02:11 | hiredman | well, if you are doing sicp you might want to find a copy of the Y combinator |
| 02:30 | sdeobald_ | hiredman: is there a book/paper by that name, specifically? Or do you just mean the concept in general? |
| 02:31 | sdeobald_ | If anyone's interested: http://github.com/deobald/sicp-clojure/blob/master/1.1/sec_1_1_8.clj |
| 02:31 | sdeobald_ | I'd love to hear thoughts on how to make the re-binding of 'sqrt-iter' go away. |
| 02:37 | hiredman | no paper, I think someone implemented a clojure version on the google group |
| 02:38 | sdeobald_ | Cool, thanks. |
| 02:38 | hiredman | well, no paper I was specifically refering to |
| 02:38 | sdeobald_ | Gotcha |
| 03:13 | Fossi | hi |
| 03:41 | jdz | sdeobald: what rebindingL |
| 03:41 | jdz | ? |
| 03:41 | jdz | sdeobald: and i'm pretty sure you want to use recur |
| 04:13 | Maddas | sdeobald: If you want to read up on the Y combinator, there's a paper titled "The Why of Y" |
| 04:47 | konr | What do you think of Common Lisp? |
| 04:49 | Chousuke | I tried it when I first heard about lisp but I never really got into it :/ |
| 04:52 | LauJensen | konr: Coming from C# to CL it has very thrilling. Coming from Clojure to CL it will feel very out dated and moronic |
| 04:52 | LauJensen | s/has/was |
| 04:53 | jdz | well, after doing some work stuff in Clojure for last 3 or so months coming back to CL seems like a dream come true, really |
| 04:54 | jdz | i never thought i would be so happy seeing a real backtrace |
| 04:54 | LauJensen | jdz, why ? |
| 04:54 | Raynes | I saw that coming. |
| 04:54 | jdz | with restarts |
| 04:54 | jdz | just my experience, yours will vary |
| 04:54 | yason | konr: It's more complex than I would desire from a language, and practically has no standard environment and libraries to run with (think Python, Java). But it has good, novel things too, if you're willing to immerse into it. |
| 04:55 | Raynes | I've got everything I need with Clojure. <3 |
| 04:55 | jdz | except a backtrace you can find useful information in :/ |
| 04:56 | Chousuke | backtraces in Clojure are horrible, yes :P |
| 04:56 | Raynes | jdz: I don't need that. |
| 04:56 | Raynes | \o/ |
| 04:56 | Chousuke | my reader (which I still have to finish) have me exceptions wrapped in about 20 layers of RuntimeException for some reason ;( |
| 04:57 | Chousuke | I wish I had more time to work on Clojure stuff now |
| 04:57 | Chousuke | I'm always getting distracted by something else I need to do |
| 04:58 | Raynes | Chousuke: Let's build that time machine I designed back in '02, and we can do just that. |
| 04:58 | Chousuke | Raynes: we can go back in time and incorporate cool Clojure features in Common Lisp. |
| 04:59 | Raynes | Chousuke: Or we can kill all those associated with the creation of Common Lisp and create a Lisp with Clojure characteristics in it's place, and then return to the future to see how we modified the future. |
| 04:59 | Chousuke | that's a bit drastic. |
| 05:00 | Raynes | Yes, but what do we have to lose? |
| 05:00 | Raynes | We can just go back and not kill them. |
| 05:00 | Raynes | Besides that, they shall not die in vain. |
| 05:00 | Chousuke | The creators of CL are still smart people. they would be more useful if we brainwashed them |
| 05:01 | jdz | Raynes: if you see Common Lisp around like it is, it means you have not gone back from the future and have not corrected the past |
| 05:01 | jdz | easy as that |
| 05:02 | Chousuke | actually, if you changed the future you would forget that it ever was different |
| 05:02 | Chousuke | so you'd think you had failed. |
| 05:02 | Maddas | Clearly none of you saw Star Trek (the recent movie). |
| 05:02 | Raynes | Not necessarily. |
| 05:02 | Raynes | There would be new versions of ourselves when we return to the future, but we should still remain. |
| 05:02 | Raynes | Anyways, I'm actually going to bed, goodnight <3. |
| 05:03 | konr | bye |
| 05:07 | LauJensen | jdz, I must say I'm surprised that after using STM, atoms, agents, java libs and vector bindings that you would want to go back to CL |
| 05:07 | jdz | LauJensen: in the application domain i use i have no use for those, really. like, interfacing with a foreign code that is not thread-safe |
| 05:08 | jdz | and java libs suck balls |
| 05:08 | jdz | oh, did i say that out loud? |
| 05:36 | Chousuke | gah :( |
| 05:37 | Chousuke | terminal crashed while I was compiling emacs |
| 05:50 | LauJensen | Chousuke, where's your reader? |
| 05:51 | Chousuke | still on github :P |
| 05:52 | LauJensen | link? |
| 05:53 | Chousuke | lazy, huh :P |
| 05:53 | Chousuke | http://github.com/Chousuke/clojure/tree/clojure-reader |
| 05:54 | Chousuke | the next step would be to make Clojure actually use it but that requires messing with the java code and I'm not quite sure how to proceed :/ |
| 05:54 | LauJensen | lazy?? What does it take nowadays to search for 'Chousuke', then bring up your 'clojure-reader' project, 10 minz? |
| 05:55 | LauJensen | Chousuke, I'm sure the Group can answer that question, ie. Rich is there |
| 05:56 | LauJensen | I see you didn't do a reader.clj - which files have you worked with ? |
| 05:56 | Chousuke | it's in src/clj/clojure/lang/reader.clj :P |
| 05:56 | LauJensen | aah gotcha :P |
| 05:57 | Chousuke | it's also based on my syntax-quote-macro modification of core.clj, which is on its own in the sq-macro branch |
| 05:58 | LauJensen | Why *black-hole* ? |
| 05:58 | Chousuke | I just needed something I could conj onto that ignores the item |
| 06:00 | LauJensen | Chousuke, Are you away that you can actually put documentation directly in the source, the so-called doc-strings? When you have function names like 'make-rh', 'quick-rh', etc, it really speeds up reading for other people looking at your source |
| 06:00 | LauJensen | s/away/ware |
| 06:00 | LauJensen | s/ware/aware |
| 06:00 | Chousuke | yes. I might document it later. |
| 06:00 | Fossi | "might" xD |
| 06:00 | Chousuke | the make-rh stuff will probably go away anyway |
| 06:01 | LauJensen | I'll commend you on your brevity of source, but it's really lacking in 1) no documentation, 2) an abundance of 'magic' numbers |
| 06:02 | Chousuke | you mean the parameters to the advance function? |
| 06:03 | LauJensen | More like "(<= 0xD800 ch 0xDFFF)" "(and (== 5 (count string)) (try (Integer/parseInt (subs string 1) 16)" "(not (<= 0 ch 0377))" etc |
| 06:03 | Chousuke | oh, right. that. |
| 06:03 | Chousuke | that's directly copied from the Java Reader. :) |
| 06:03 | Chousuke | though hm, I think it had comment s :P |
| 06:03 | Chousuke | -s |
| 06:03 | Chousuke | er, -' ' I mean |
| 06:03 | LauJensen | hehe |
| 06:05 | Chousuke | the symbol resolution stuff in the keyword handling is icky |
| 06:06 | Chousuke | there seems to be no good way to resolve a symbol to its full form without many conditionals ;/ |
| 06:10 | Chousuke | hmm |
| 06:10 | Chousuke | I'm using #() in the definition of the #() implementation function :P |
| 06:10 | Chousuke | I wonder if I'll have to fix that. |
| 06:14 | danlei | not if you're compiling clojure to clojure :p |
| 07:58 | licoresse | What is the best tool for looking up stuff in java doc? |
| 07:58 | LauJensen | I recommend: Your eyes |
| 07:59 | licoresse | haha |
| 07:59 | LauJensen | ;) |
| 07:59 | licoresse | I remember a site, in the beginning of 2000, that let you search for keywords and presented examples where the keyword was present |
| 08:00 | licoresse | it was a great tool |
| 08:00 | LauJensen | Google you mean ? |
| 08:01 | licoresse | LauJensen: no... not goggle |
| 08:02 | konr | What's the clojure equivalent of CL's find-all? |
| 08:04 | konr | select! |
| 08:14 | LauJensen | licoresse, I can't determine if you're being serious or not - What tool could you want to go through a Javadoc? You always know which classes your looking, and a simple search gives you the description. What more is there? |
| 08:15 | licoresse | Ah, my point was *examples* |
| 08:15 | LauJensen | aaah |
| 08:15 | licoresse | getting related examples to the Canvas class f.ex |
| 08:15 | licoresse | hehe |
| 08:16 | licoresse | *eyes* |
| 08:16 | chouser | http://www.google.com/codesearch?q=Canvas+lang:java |
| 08:17 | licoresse | ah nice! |
| 08:18 | LauJensen | The first example is real nice, couldn't be any clearer than a one-liner |
| 08:19 | chouser | yeah, it's an excellent example of Java |
| 08:19 | chouser | public static final i forgot what i was doing... |
| 08:46 | LauJensen | It's funny that my first version of brians brain attracted thousands of readers, but my transient rewrite has barely had 200 views :) |
| 08:47 | ambient | it might have something to do where it was linked |
| 08:47 | ambient | visibility is king |
| 08:48 | LauJensen | I know - But I don't do anything to promote it, except put it on dzone, just to see what happends naturally |
| 08:49 | Chousuke | LauJensen: I don't see you in the clojure pipe ;( |
| 08:50 | LauJensen | There's a Clojure pipe? :) |
| 08:50 | Chousuke | yes |
| 08:51 | ambient | the original post is linked on reddit, the second one is not |
| 08:51 | LauJensen | Yea, I wonder why |
| 08:57 | konr | Hmmm, should I change a value set by (bindings)? |
| 08:57 | konr | *(binding) |
| 08:57 | LauJensen | konr, in which situation ? |
| 09:02 | konr | LauJensen: I'm adapting some CL code that has several functions that access global variables. These variables can be overridden at a main function, so I'm not sure whether I should override them with (binding) or use references, setting them at the main function |
| 09:03 | LauJensen | konr, I think you need to think the design through before you start coding, a 1-to-1 translation will probably give you very bad looking clojure code. If you're loading settings, it might be better to stuff them all in a hash-map, rather than have 100 global defs etc. |
| 09:05 | Chousuke | if your code is (or will be) threaded you must also take that into account. |
| 09:10 | LauJensen | yes, then you're looking at refs or atoms |
| 09:14 | Chousuke | I guess you could use alter-var-root though :/ |
| 09:14 | Chousuke | if it really is one-time configuration |
| 09:17 | LauJensen | ,(doc alter-var-root) |
| 09:17 | clojurebot | "([v f & args]); Atomically alters the root binding of var v by applying f to its current value plus any args" |
| 09:17 | LauJensen | Never used that |
| 09:20 | Chousuke | chouser showed a neat use of it on the group |
| 09:20 | Chousuke | hmm |
| 09:21 | LauJensen | got link ? |
| 09:21 | Chousuke | well, it was just (alter-var-root #'somefunc memoize) |
| 09:23 | Chousuke | ,`defang |
| 09:23 | clojurebot | sandbox/defang |
| 09:23 | Chousuke | not visible in the sandbox I guess ;( |
| 09:23 | Chousuke | clojurebot: source |
| 09:23 | clojurebot | source is http://github.com/hiredman/clojurebot/tree/master |
| 09:24 | Chousuke | ,`de-fang |
| 09:24 | Chousuke | hm. |
| 09:24 | clojurebot | sandbox/de-fang |
| 09:24 | Chousuke | ,#'hiredman.sandbox/de-fang |
| 09:24 | clojurebot | #'hiredman.sandbox/de-fang |
| 09:25 | Chousuke | ,(alter-var-root #'hiredman.sandbox/de-fang (fn [x] identity)) |
| 09:25 | clojurebot | #<core$identity__4657 clojure.core$identity__4657@1e07f4b> |
| 09:25 | Chousuke | ,(defn foo [x] x) |
| 09:25 | clojurebot | Wrong number of args passed to: core$identity |
| 09:25 | Chousuke | oops |
| 09:25 | Chousuke | :( |
| 09:25 | Chousuke | hiredman: sorry, I broke clojurebot |
| 09:25 | Chousuke | hiredman: but you need to fix that hole |
| 09:29 | Chousuke | hiredman: you need to make the defang function and the *bad-forms* global local to the sanbox-eval function :P |
| 09:32 | Chousuke | hmm |
| 09:32 | Chousuke | ,#=(alter-var-root #'hiredman.sandbox/de-fang (fn [x] (fn [form _] form))) |
| 09:32 | clojurebot | clojure.lang.Cons cannot be cast to clojure.lang.Var |
| 09:34 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) (fn [x] (fn [form _] form))) |
| 09:34 | clojurebot | clojure.lang.PersistentList cannot be cast to clojure.lang.IFn |
| 09:34 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn [x] (fn [form _] form))) |
| 09:34 | clojurebot | clojure.lang.Cons cannot be cast to clojure.lang.IFn |
| 09:34 | Chousuke | gah |
| 09:34 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn [x] #=(fn [form _] form))) |
| 09:34 | clojurebot | clojure.lang.Cons cannot be cast to clojure.lang.IFn |
| 09:35 | Chousuke | I suppose I can't fix it :( |
| 09:36 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn* [x] #=(fn* [form _] form))) |
| 09:36 | clojurebot | Can't resolve fn* |
| 09:37 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(eval '(fn [x] (fn [form _] form)))) |
| 09:37 | clojurebot | clojure.lang.PersistentList cannot be cast to clojure.lang.IFn |
| 09:38 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(eval (fn [x] (fn [form _] form)))) |
| 09:38 | clojurebot | #<sandbox$eval__2941$fn__2943$fn__2945 sandbox$eval__2941$fn__2943$fn__2945@1ab5e85> |
| 09:38 | Chousuke | hmm |
| 09:39 | Chousuke | ,4 |
| 09:39 | clojurebot | 4 |
| 09:39 | Chousuke | hooray |
| 09:42 | Chousuke | this particular security hole is really nasty though :( |
| 09:44 | Chousuke | might be better to kill Clojurebot before anyone really exploits it :P |
| 09:50 | liwp | Chousuke: remind me: what does #= do? |
| 09:50 | Chousuke | read-time evaluation |
| 09:50 | Chousuke | that's not the main security hole though. |
| 09:50 | liwp | nope |
| 09:50 | Chousuke | the real hole is that I can override the sanboxing function... |
| 09:51 | Chousuke | sandboxing* |
| 09:51 | liwp | I was just trying to figure out how you fixed clojurebot |
| 09:51 | liwp | after breaking it |
| 09:51 | Chousuke | well, I notice that clojurebot doesn't bind *read-eval* to false |
| 09:52 | Chousuke | I'm still contemplating whether I should just kill Clojurebot or wait till hiredman responds ;( |
| 09:53 | Chousuke | noticed* ;P |
| 09:54 | Chousuke | I think it would be useful if you could mark vars as truly immutable |
| 09:54 | liwp | definitely in this case |
| 09:55 | Chousuke | but there are problems with that, too I guess. |
| 09:55 | liwp | it's also against the dynamic nature of lisp |
| 09:55 | liwp | but that's more of a philosophical argument |
| 09:56 | Chousuke | I wonder if the bound-fn macro could help. |
| 09:56 | liwp | I haven't really been following the bound-fn conversation so far |
| 09:56 | liwp | I've never really been bitten by laziness in clojure so I haven't cared |
| 09:57 | Chousuke | though because you can basically change any var to anything it won't help much ;( |
| 09:57 | Chousuke | and somehow I doubt there's a way to disallow all possible ways of changing a var without crippling clojurebot completely |
| 10:03 | Chousuke | hmm |
| 10:05 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly {})) |
| 10:05 | clojurebot | {} |
| 10:06 | Chousuke | (alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form)))) |
| 10:06 | Chousuke | ,(alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form)))) |
| 10:06 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--2954$fn |
| 10:06 | liwp | Did you just disable all sandboxing from clojurebot? |
| 10:06 | Chousuke | no |
| 10:06 | Chousuke | I'm trying to fix it |
| 10:07 | Chousuke | the sandboxing was alredy disabled :P |
| 10:07 | Chousuke | ,1 |
| 10:07 | clojurebot | 1 |
| 10:07 | liwp | I mean the (constantly {}) bit |
| 10:07 | liwp | fair enough ;) |
| 10:07 | Chousuke | ,(alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form))) |
| 10:07 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--2966$fn |
| 10:07 | Chousuke | gah |
| 10:07 | Chousuke | the defang function is too complex |
| 10:08 | Chousuke | ,(alter-var-root #'hiredman.sandbox/de-fang (constantly (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form)))) |
| 10:08 | clojurebot | #<sandbox$eval__2978$fn__2980 sandbox$eval__2978$fn__2980@ca1465> |
| 10:08 | liwp | don't you need an extra layer of fn in that, because alter-var-root takes and fn that is applied to the var? |
| 10:08 | Chousuke | okay, now the defang thingy should be working |
| 10:08 | liwp | exactly |
| 10:09 | liwp | so what does it do exactly? |
| 10:09 | liwp | filters out bad forms? |
| 10:09 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* assoc 'this-is-a-test) |
| 10:09 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$assoc |
| 10:09 | liwp | one more arg |
| 10:10 | Chousuke | gah, it was a set originally... |
| 10:10 | liwp | heh |
| 10:10 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'this-is-a-test})) |
| 10:10 | clojurebot | #{this-is-a-test} |
| 10:10 | Chousuke | ,this-is-a-test |
| 10:10 | clojurebot | java.lang.Exception: Unable to resolve symbol: this-is-a-test in this context |
| 10:10 | Chousuke | hmm. |
| 10:11 | Chousuke | ,eval |
| 10:11 | clojurebot | #<core$eval__5182 clojure.core$eval__5182@4d8040> |
| 10:11 | Chousuke | *sigh* |
| 10:11 | Chousuke | maybe I should just give up |
| 10:12 | liwp | can you rebind alter-root-var and thereby plug the hole? |
| 10:12 | liwp | for the time being |
| 10:12 | Chousuke | that might break other things though |
| 10:12 | liwp | OTOH the bot is broken in any case so you can't really make things worse that way...? |
| 10:13 | Chousuke | ,(eval '5) |
| 10:13 | liwp | it's gone to bed? |
| 10:13 | clojurebot | 5 |
| 10:14 | Chousuke | nope :( |
| 10:14 | Chousuke | ,(this-is-a-test '5) |
| 10:14 | clojurebot | DENIED |
| 10:14 | Chousuke | ooh |
| 10:14 | Chousuke | okay, now I can perhaps fix it |
| 10:14 | liwp | so now you need to add all the bad forms to your set |
| 10:15 | liwp | maybe remove your this-is-a-test as well ;) |
| 10:15 | Chousuke | ,(alter-var-root #'hiredman.sanbox/*bad-forms* (constantly #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot})) |
| 10:15 | clojurebot | Chousuke: Excuse me? |
| 10:15 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot})) |
| 10:15 | clojurebot | Chousuke: Huh? |
| 10:15 | Chousuke | garr |
| 10:16 | liwp | ,(this-is-a-test '0) |
| 10:16 | clojurebot | DENIED |
| 10:17 | liwp | ,(+ 1 1) |
| 10:17 | clojurebot | 2 |
| 10:17 | Chousuke | ,(var-set #'hiredman.sandbox/*bad-forms* #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot}) |
| 10:17 | clojurebot | Chousuke: excusez-moi |
| 10:18 | liwp | I've never looked at the bot source, but it looks like that's not ever getting to the evaluator |
| 10:19 | Chousuke | fortunately the channel is rather quiet at the moment :P |
| 10:19 | Chousuke | other than this bot-trickery |
| 10:22 | Chousuke | ,(var-set #'hiredman.sandbox/*bad-forms* '#{intern eval def catch load-string load-reader clojure.core/addMethod hiredman.clojurebot/bot}) |
| 10:22 | clojurebot | Chousuke: Pardon? |
| 10:22 | Chousuke | :( |
| 10:22 | liwp | ,(var-set + +) |
| 10:22 | clojurebot | java.lang.ClassCastException: clojure.core$_PLUS___4443 cannot be cast to clojure.lang.Var |
| 10:23 | liwp | ,(var-set #'+ #'+) |
| 10:23 | clojurebot | java.lang.IllegalStateException: Can't change/establish root binding of: + with set |
| 10:23 | Chousuke | I wonder if the set thing is confusing it. |
| 10:23 | liwp | good |
| 10:23 | liwp | try using set |
| 10:23 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms conj 'catch) |
| 10:23 | clojurebot | Chousuke: Titim gan éirí ort. |
| 10:24 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'catch) |
| 10:24 | clojurebot | Chousuke: Huh? |
| 10:24 | liwp | I don't think it likes you |
| 10:24 | Chousuke | heh |
| 10:24 | rsynnott | Why does the bot speak Irish? |
| 10:25 | liwp | rsynnott: it's a polyglot, it speaks french as well |
| 10:25 | Chousuke | ,#=(alter-var-root #=(var hiredman.sandbox/*bad-forms*) conj catch) |
| 10:25 | clojurebot | Chousuke: Titim gan éirí ort. |
| 10:25 | liwp | Chousuke: since you're messing with the both, you might as well add finnish error messages |
| 10:25 | Chousuke | ,#'hiredman.sandbox/*bad-forms* |
| 10:25 | clojurebot | #'hiredman.sandbox/*bad-forms* |
| 10:26 | rsynnott | Particularly unusual language for evil robots, though :) |
| 10:26 | Chousuke | ??? I'm confused |
| 10:26 | liwp | Chousuke: aren't you getting the args in the wrong order with conj here, i.e. it'll become (conj foo #{}) |
| 10:26 | Chousuke | liwp: it's an altering function so it'll pass the thing to be altered as the first parameter |
| 10:26 | liwp | ok |
| 10:26 | Chousuke | and any user-supplied args after that |
| 10:27 | Chousuke | but it seems it's even more broken now. |
| 10:27 | liwp | ,(#'hiredman.sandbox/*bad-forms* 'this-is-a-test) |
| 10:27 | clojurebot | DENIED |
| 10:28 | liwp | ,this-is-a-test |
| 10:28 | clojurebot | java.lang.Exception: Unable to resolve symbol: this-is-a-test in this context |
| 10:28 | liwp | ,'this-is-a-test |
| 10:28 | clojurebot | this-is-a-test |
| 10:28 | liwp | duh |
| 10:35 | Chousuke | ah, now I know why it doesn't like me |
| 10:35 | Chousuke | ,catch |
| 10:35 | clojurebot | Chousuke: It's greek to me. |
| 10:36 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'intern 'eval 'def 'load-string 'load-reader 'clojure.core/addMethod})) |
| 10:36 | clojurebot | #{intern load-reader load-string clojure.core/addMethod eval def} |
| 10:36 | Chousuke | ~def alter-var-root |
| 10:37 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alterRoot |
| 10:37 | clojurebot | EOF while reading |
| 10:37 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alterRoot) |
| 10:37 | clojurebot | #{alterRoot intern load-reader load-string clojure.core/addMethod eval def} |
| 10:37 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alter-var-root) |
| 10:37 | clojurebot | #{alterRoot intern load-reader load-string clojure.core/addMethod eval alter-var-root def} |
| 10:37 | Chousuke | ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj :test) |
| 10:37 | clojurebot | DENIED |
| 10:37 | Chousuke | ,(.alterRoot #'hiredman.sandbox/*bad-forms* conj :test) |
| 10:37 | clojurebot | DENIED |
| 10:38 | Chousuke | excellent |
| 10:42 | avital | Hello Chous{er,uke} and friends. It seems that pr is supposed to print a value in the exact way the reader can read it. But (pr '(1)) prints (1) instead of '(1). Is this a bug? |
| 10:42 | avital | ,(pr '(1)) |
| 10:42 | clojurebot | (1) |
| 10:44 | Chousuke | avital: it's not a bug. pr is a function, so its parameter is evaluated |
| 10:44 | Chousuke | and if you read "(1)", you indeed get '(1) |
| 10:44 | Chousuke | ,(read-string "(1)" |
| 10:44 | clojurebot | EOF while reading |
| 10:44 | Chousuke | ,(read-string "(1)") |
| 10:44 | clojurebot | (1) |
| 10:45 | Chousuke | ,(read-string "'(1)") |
| 10:45 | clojurebot | (quote (1)) |
| 10:54 | liwp | Chousuke: good job with the bot |
| 10:55 | Chousuke | yes. first I break it and then I fix it :P |
| 10:55 | Chousuke | all publicly on IRC |
| 10:55 | Fossi | that's the spirit |
| 10:55 | liwp | you should've PM'd it |
| 10:55 | liwp | in the privacy of your own irc client |
| 10:56 | Chousuke | I don't know if it listens to PMs :/ |
| 10:56 | Fossi | it does |
| 10:56 | liwp | it does |
| 10:56 | Fossi | it's more fun in public though :D |
| 10:56 | liwp | so what was wrong with (alter-var-root #'hiredman.sandbox/*bad-forms* conj 'catch)? |
| 10:57 | Chousuke | liwp: it turned out that an earlier function tests whether the message string contains "catch". :P |
| 10:57 | liwp | auts |
| 11:35 | adityo | ola guys! |
| 11:36 | adityo | how do i remove a key/value pair from a map ..say {"lisp" "mcarthy", "Clojure" "Hickey"} and i want to remove lisp/mcarthy |
| 11:37 | stuartsierra | (dissoc *the-map* "lisp") |
| 11:39 | adityo | cool, was thinking of writing somethings in the line of remove-if in CL |
| 11:41 | adityo | thanks |
| 11:42 | stuartsierra | np |
| 11:52 | chouser | hiredman: thanks for mentioning "Evolution of Lisp". It's fascinating. |
| 11:52 | chouser | "This situation of unexpected performance is prevalent with Lisp." |
| 12:09 | ambient | one thing that really bothers me about functional programming and immutability is the performance issue |
| 12:10 | ambient | but that's not such a huge thing because of the versatility. python is about 60 times slower than C. people (and I) still use it because it gets things done a lot faster |
| 12:12 | stuartsierra | With any language, you write the code you want, then optimize a few critical sections, often by rewriting in another language. Clojure->Java, Java->C, C->assembly |
| 12:14 | ambient | i'd rather just use one language :/ but perhaps that's a pipe dream if i want both dynamicality(?) and performance |
| 12:14 | chouser | ambient: keep the dream alive |
| 12:15 | stuartsierra | Write a better compiler. Or a better VM. |
| 12:15 | stuartsierra | It happens, just slowly. Almost no one writes assembly any more; C compilers are good enough. |
| 12:16 | stuartsierra | Java is getting there. |
| 12:16 | chouser | falling back to mutable structures (like arrays) and sufficient use of macros (and other possible features like reify) we can hope to get *very* close to java speed while retaining many of clojure's abstractions, even in the small pieces of code where performance is most critical. |
| 12:46 | tmountain | as far as VM are concerned, hotspot is actually one of the best IMO |
| 12:54 | konr | Isn't there a version of (binding) that creates the variables, if they don't exist? |
| 12:54 | technomancy | (doc with-local-vars) |
| 12:55 | Chousuke | I haven't found much use for local vars :/ |
| 12:56 | technomancy | yeah, it seems like the wrong answer |
| 12:57 | stuartsierra | konr: the variables still have to be (declare ...)'d if you want to use them in other functions. |
| 13:03 | technomancy | stuartsierra: I'm looking at your swank-clojure changes |
| 13:03 | technomancy | I'm not really understanding the clojure-maven-plugin |
| 13:03 | technomancy | why does it take eleven Java classes just to perform clojure compilation? |
| 13:04 | stuartsierra | It doesn't. |
| 13:04 | stuartsierra | clojure-maven-plugin does a bunch of different things -- compile source, compile tests, run main, run tests, run repl, run swank, generate docs... |
| 13:05 | stuartsierra | Each "goal" in Maven-speak needs its own class |
| 13:06 | technomancy | ok, that's more than I've been using maven for so far. |
| 13:06 | stuartsierra | Most of them are small classes that call the methods in AbstractClojureCompilerMojo |
| 13:07 | technomancy | it would be nice if this stuff didn't have to be written in Java, but I've had a nasty time trying to gen-class maven stuff due to the wackiness in its classpath |
| 13:08 | technomancy | *class loader |
| 13:08 | stuartsierra | It could be done, but then clojure-maven-plugin would have a dependency on Clojure, which is almost circular. |
| 13:09 | stuartsierra | Mostly the plugin just invokes clojure.main with different arguments. |
| 13:09 | technomancy | as long as I'm not the one writing / reading it |
| 13:09 | technomancy | can't you do that from the pom though? |
| 13:09 | stuartsierra | technomancy: not really, and not conveniently. |
| 13:09 | technomancy | we do that at work; seems a lot simpler |
| 13:09 | technomancy | for AOT and test running |
| 13:10 | stuartsierra | The point of Maven plugins is to keep the POM simple and declarative, not full of the procedural-type scripting one does with Ant. |
| 13:11 | technomancy | ok, I'll try this out |
| 13:11 | stuartsierra | The plugin code really isn't that bad; I was able to add the SWANK stuff without knowing much about Maven internals. |
| 13:11 | technomancy | cool |
| 13:11 | technomancy | did you say something about wanting to start a repo for OSS clojure projects? |
| 13:12 | stuartsierra | It was a half-formed idea to set up a Maven repo and encourage Clojure library developers to use it. |
| 13:12 | technomancy | sounds good to me |
| 13:12 | stuartsierra | First I think we need to get swank-clojure and clojure-maven-plugin 1.1 into central. |
| 13:13 | technomancy | once clojure 1.1 is out? |
| 13:13 | stuartsierra | Not necessarily. |
| 13:13 | stuartsierra | Then we need a Maven archetype for new Clojure projects, and get THAT into central. |
| 13:13 | technomancy | you'd need a VPS or something to allow each contributor to have a user account, right? |
| 13:13 | technomancy | so they can push out releases |
| 13:14 | stuartsierra | Dunno; I'm not that familiar with Maven deployment setups. |
| 13:15 | technomancy | I guess you could accept pubkeys from contributors all hooked up to the same user as long as you trust them |
| 13:15 | stuartsierra | Basically, I want to lower the barrier to creating & releasing Maven-enabled Clojure libraries, so that everyone does it. |
| 13:15 | technomancy | yes |
| 13:16 | stuartsierra | So my plan of attack is 1. SWANK, 2. plugin, 3. archetype, 4. repository. |
| 13:19 | technomancy | I feel a little uneasy that jochu has a "start server refactoring" commit on the master branch with no further commits referencing it. =\ |
| 13:19 | technomancy | yeesh; the centralized repos are slow. |
| 13:20 | stuartsierra | you might want to ask jochu about that; maybe he has an older version that's stable enough for a 1.0 |
| 13:21 | konr | Isn't it awesome? Clojure is even more concise than CL: http://scorciapino.com/pub/fotos/clj-vs-cl.png |
| 13:23 | stuartsierra | On a related note, does the swank server target a particular version of SLIME? It would be nice to have that documented somewhere. |
| 13:23 | technomancy | stuartsierra: slime doesn't really have versions |
| 13:23 | technomancy | well... no, it has 1.0, and that's it |
| 13:23 | technomancy | I think they've decided they don't do "releases" |
| 13:24 | stuartsierra | charming |
| 13:24 | technomancy | basically I have a fork of slime, and I set M-x clojure-install to use my fork, and I only update it when I've confirmed it works. |
| 13:25 | stuartsierra | Ok. What if SLIME were packaged with swank-clojure? |
| 13:25 | technomancy | that's actually not a bad idea |
| 13:25 | technomancy | since it's just a single .el file |
| 13:25 | technomancy | actually, that's a great idea |
| 13:26 | technomancy | most of the code in slime is CL that's irrelevant anyway |
| 13:26 | technomancy | I was thinking about asking if they wanted to merge swank-clojure into slime, but I don't think that would ever happen |
| 13:26 | technomancy | why not go the other way... |
| 13:27 | Raynes | technomancy's brain is about to explode. |
| 13:27 | stuartsierra | Emacs couldn't load the .el code from a Maven JAR, but you could still tell Clojure users to get SLIME from the swank-clojure zip/tar distribution. |
| 13:28 | technomancy | stuartsierra: well swank-clojure already bundles a .el file anyway |
| 13:28 | stuartsierra | Right. |
| 13:28 | stuartsierra | So it should be easy enough. |
| 13:29 | technomancy | clojure-maven-plugin failed after twenty minutes of downloading asking for a gpg passphrase. =\ |
| 13:29 | stuartsierra | Hit enter. |
| 13:29 | technomancy | right; that made it fail |
| 13:29 | stuartsierra | weird, haven't had that problem |
| 13:29 | technomancy | gpg: no default secret key: secret key not available |
| 13:30 | technomancy | I guess I need to generate one |
| 13:30 | technomancy | I just want to install it though. =\ |
| 13:30 | technomancy | there we go |
| 13:30 | technomancy | this is why we need this in a centralized repo somewhere |
| 13:31 | stuartsierra | Or comment out the key-signing stuff in the clojure-maven-plugin POM |
| 13:31 | stuartsierra | I think you only need that to publish releases in central. |
| 13:32 | technomancy | bug filed |
| 13:34 | technomancy | stuartsierra: is there a way to see what goals are defined? |
| 13:34 | technomancy | like rake -T ? |
| 13:36 | stuartsierra | For a single plugin, yes: "mvn help:describe" |
| 13:36 | stuartsierra | For all plugins, no. |
| 13:36 | stuartsierra | mvn help:describe -DgroupId=com.theoryinpractise -DartifactId=clojure-maven-plugin -Dversion=1.1-SNAPSHOT |
| 13:36 | sproingie | what a horrible horrible ui |
| 13:36 | sproingie | in a sane world that might be "mvn-help -p clojure" |
| 13:37 | technomancy | don't forget the -o "don't download the Internet again" argument. =\ |
| 13:38 | sproingie | worst thing it would do is download the plugin itself which tends to be small |
| 13:38 | stuartsierra | It never downloads the internet again. |
| 13:40 | technomancy | hmm... I can't get any of these goals to run |
| 13:40 | sproingie | might have to be mvn-help -g com.theoryinpractise -p clojure |
| 13:40 | technomancy | I'll have to come back to this later |
| 13:40 | stuartsierra | ok |
| 13:40 | sproingie | but maven seems to have some way of figuring out groupIds of plugins automagically |
| 13:41 | sproingie | probably some kind of index on <x>-maven-plugin |
| 13:41 | stuartsierra | if they're built-in or defined in the <plugins> section of your current project, it's just "mvn help:describe -Dcmd=clojure:..." |
| 13:41 | stuartsierra | sproingie: that's exactly what it does |
| 13:42 | LauJensen | stuartsierra, did you sort out file posting in your http agent yet ? |
| 13:42 | stuartsierra | no |
| 13:42 | stuartsierra | I seriously doubt I'm going to. |
| 13:42 | LauJensen | oh, why the change of heart ? |
| 13:43 | stuartsierra | I looked at what it entails. There's Base64 encoding, MIME headers, etc. |
| 13:43 | stuartsierra | The Apache HTTP library handles that well already. I'm not going to reimplement it. |
| 13:43 | LauJensen | Softened your knees a little bit, did it? :) |
| 13:43 | stuartsierra | exactly. |
| 13:43 | LauJensen | It's fine, apache libs work without problems anyway |
| 13:44 | stuartsierra | maybe someday I'll rewrite HTTP agent based on Apache's client, but I've got bigger fish to fry right now. |
| 13:45 | LauJensen | Alright |
| 13:45 | technomancy | that'd have to wait till Dependencies Work anyway |
| 13:45 | stuartsierra | truth, hence my recent enthusiasm for Maven |
| 13:46 | LauJensen | Are you guys working on something with Maven ? |
| 13:49 | stuartsierra | (1:16:42 PM) stuartsierra: Basically, I want to lower the barrier to creating & releasing Maven-enabled Clojure libraries, so that everyone does it. |
| 13:49 | stuartsierra | (1:16:47 PM) technomancy: yes |
| 13:49 | stuartsierra | (1:17:37 PM) stuartsierra: So my plan of attack is 1. SWANK, 2. plugin, 3. archetype, 4. repository. |
| 13:53 | ambient | reading through clojure.core this sentence really took a long time to parse :P "Evaluates exprs one at a time, from left to right. If a form returns a logical true value, or returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expression. (or) returns nil." |
| 13:55 | hircus | I think parenthesizing or quoting the first "or" would help readability a lot |
| 13:57 | LauJensen | stuartsierra, thanks, I'm awake now |
| 13:57 | LauJensen | Let me know when you have something we should try out |
| 13:58 | stuartsierra | You can try the latest from github: http://github.com/jochu/swank-clojure and http://github.com/talios/clojure-maven-plugin |
| 14:01 | LauJensen | I'll have a look |
| 14:04 | LauJensen | stuartsierra, looks like you're filling a void in clojure-land, weee :) |
| 14:04 | liwp` | ~library |
| 14:04 | stuartsierra | falling into the void, more like |
| 14:05 | liwp` | huh, where's clojurebot? did hiredman take it off-line for patching? |
| 14:27 | LauJensen | liwp, yea he's probably in the shop :) Chousuke messed him up a little bit |
| 14:28 | LauJensen | liwp or actually looking through my log, its possible he just didn't recover from the ircd's restart |
| 14:28 | Chousuke | LauJensen: clojurebot already returned ;P |
| 14:29 | Chousuke | though now I have to fix him again |
| 14:29 | LauJensen | Chousuke, so you're saying, check the user list before analyzing logs? :) |
| 14:29 | hiredman | I did nae restart it, just had it reconnect and rejoin |
| 14:29 | Chousuke | or hm, I suppose the process itself survivved. |
| 14:30 | Chousuke | ,(alter-var-root error) |
| 14:30 | clojurebot | DENIED |
| 14:30 | Chousuke | -v |
| 14:40 | dnolen | cgrand: been thinking a little bit about enlive again, specifically nesting template/snippets. You said this would be slow. Would it make sense to cache the fast representation to disk? |
| 14:40 | cgrand | dnolen: I saw you forked it again :-) |
| 14:41 | cgrand | I don't remember what was your use case. |
| 14:42 | dnolen | just dynamically selecting sub templates from a template. |
| 14:42 | dnolen | template inheritance is what I wanted i realize. |
| 14:46 | dnolen | cgrand: http://groups.google.com/group/clojure/msg/4469f364b0b7c09f |
| 14:46 | dnolen | this was your response |
| 14:48 | cgrand | dnolen: thx |
| 14:51 | cgrand | there are two things that makes a dynamic snippet like the one in your sample code slow: parsing and pre-serializing. Parsing overhead is easily worked around by loading your html once. |
| 14:51 | dnolen | cgrand: does it make sense to cache the parsed content to disk? |
| 14:53 | cgrand | dnolen: I don't think |
| 14:53 | wooby | hello, would anyone happen to know why this gives me 'malformed member expression?' (.. os write (to-byte-array file) 0 (.. file length)) |
| 14:53 | dnolen | cgrand: k, what do you mean by pre-serializing? |
| 14:56 | liwp` | wooby: (..file lenght) seems broken to me |
| 14:56 | liwp` | you should avoid the .. forms if you can |
| 14:56 | liwp` | use -> instead |
| 14:56 | wooby | ah, does that do the same thing? |
| 14:57 | liwp` | in effect yes |
| 14:57 | liwp` | so something like (-> os write (to-byte-array...)) |
| 14:57 | kotarak | But it also allows for clojure functions and macros... (-> x .methodCall clj-fun (a-macro with other args)) |
| 14:58 | cgrand | dnole; once a html tree is loaded, each node is annotated with its serialization. Hence when Enlive serilaizes the output of a transformation, if a node is untouched by the transformation it can skip walking it and directly emits the cached serialization. |
| 14:58 | cgrand | dnolen: that's for you ^^ |
| 14:58 | wooby | i see... thank you |
| 14:58 | liwp` | wooby: the 0 in the middle of your .. form looks suspect as well |
| 14:59 | wooby | liwp: what i'm trying to do is write a file's contents to a socket's output stream |
| 14:59 | liwp` | are you trying to call write on os and everything else is just a set of arguments to the write call? |
| 14:59 | wooby | it's entirely possible i'm going about it entirely the wrong way |
| 14:59 | wooby | correct |
| 14:59 | dnolen | cgrand: i see. so how would you handle template inheritance using Enlive? :) |
| 15:00 | liwp` | wooby: you should have something like (.write os <args>) |
| 15:00 | wooby | http://gist.github.com/203318 that's the whole thing so far... forgive the style, i'm sure it sucks |
| 15:00 | wooby | but i appreciate any and all feedback |
| 15:00 | liwp` | let's see: (.write os (to-byte-array file) 0 (.length file)) |
| 15:00 | liwp` | try that |
| 15:00 | cgrand | dnolen: could you be more specific on what you call template inheritance? |
| 15:01 | liwp` | wooby: so whenever you want to call a method you should use (.method object) |
| 15:01 | liwp` | except for static methods it would be (Class/method ...) |
| 15:02 | liwp` | wooby: I see a lot of .. forms in your code and most of them are wrong, e.g. (.. sock close) should be (.close sock) |
| 15:02 | cgrand | but this annotation phase can be moved out of snippet* and put into html-resource, this would make dynamic snippets lighter |
| 15:02 | liwp` | wooby: I guess the .. form works as well, but it's not idiomatic |
| 15:02 | wooby | ok thanks, it's what i'm aiming for |
| 15:02 | wooby | just going off the book so far |
| 15:03 | ambient | it looks like a lot of .java in clojure/src/jvm is machine generated? |
| 15:03 | liwp` | ambient: nope |
| 15:03 | ambient | huh, weird |
| 15:03 | liwp` | or possibly some of the invoke defs |
| 15:04 | dnolen | cgrand: for example, 3 column layout. that's one template. then I have a nav template. In one app I'd like to put this in column 1 in the base 3 column template. Nav template supports showing different widgets. Each widget is itself a template. |
| 15:05 | liwp` | wooby: in the past people used to write (.. my-obj meth1 meth2 meth3), (. my-obj method) and (new Foo). These days the fashion is to write (-> my-obj m1 m2 m3) (.method my-obj) and (Foo.) instead |
| 15:06 | cgrand | dnolen: have to go, can we continue by mail? Can't you achieve what you describe by function composition? |
| 15:06 | liwp` | wooby: the (.. os...) form seems to be the only broken bit in the gist (haven't tried running it) |
| 15:06 | wooby | liwp: got it, thank you |
| 15:06 | kotarak | cgrand, dnolen: would keep also informed? |
| 15:06 | kotarak | I'm also interested in this! |
| 15:07 | wooby | liwp: thanks, i managed to fix it thanks to your help, now working on another bug |
| 15:07 | Chousuke | the .. form is still fine sometimes though. |
| 15:07 | dnolen | cgrand: you're probably right, I've just started thinking about this again. |
| 15:07 | Chousuke | you can't access statics through -> IIRC. |
| 15:07 | Chousuke | or hm |
| 15:07 | Chousuke | ,(-> Math .PI) |
| 15:07 | clojurebot | java.lang.IllegalArgumentException: No matching field found: PI for class java.lang.Class |
| 15:07 | Chousuke | right. |
| 15:07 | kotarak | Chousuke: ,(-> Math/PI) |
| 15:07 | kotarak | ,(-> Math/PI) |
| 15:07 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$--GT- |
| 15:08 | kotarak | ,(-> Math/PI identity) |
| 15:08 | clojurebot | 3.141592653589793 |
| 15:08 | Chousuke | kotarak: yeah, but that won't work if it's nested somehow... on second thought, is that even possible? :P |
| 15:08 | kotarak | nested? |
| 15:08 | Chousuke | never mind. I don't think it's possible :) |
| 15:09 | kotarak | I don't understand the nested. |
| 15:09 | raek | my first library: http://github.com/raek/clojure-sandbox/blob/master/src/com/github/raek/xml_with_xmlns.clj |
| 15:09 | Chousuke | I mean (-> foo .bar .static ...) |
| 15:09 | raek | extending clojure.xml with xml namespaces |
| 15:09 | kotarak | Chousuke: You mean .bar returns a class, which you want to use as part in front of the "/"? |
| 15:10 | liwp` | Chousuke: shouldn't that just work, i.e. can't you just call the static method on the instance rather then the class? |
| 15:10 | Chousuke | liwp`: yeah, I guess you can |
| 15:11 | raek | {:tag :foo:bar :attrs {:xmlns:foo "http://example.com/ns"}} => {:tag :http://example.com/ns/bar :attrs {}} |
| 15:12 | kotarak | ,(-> "123" Integer/valueOf (.valueOf "567")) |
| 15:12 | clojurebot | java.lang.IllegalArgumentException: No matching method found: valueOf for class java.lang.Integer |
| 15:15 | liwp` | kotarak: so you can't call a static method on an instance... |
| 15:15 | chouser | uh |
| 15:15 | kotarak | liwp`: It seems like this is not possible, no. Any Java gurus around? |
| 15:15 | raek | (anyone here using clojure.xml and/or xml namespaces?) |
| 15:16 | crios | in Java you can call a static methond on an instance |
| 15:16 | wooby | sweet, this little webserver totally works now... thanks everyone for your help |
| 15:16 | wooby | http://gist.github.com/203329 |
| 15:17 | kotarak | ,(.valueOf 5 "123") |
| 15:17 | clojurebot | java.lang.IllegalArgumentException: No matching method found: valueOf for class java.lang.Integer |
| 15:17 | kotarak | hmmm |
| 15:17 | liwp` | kotarak: in java you're definitely allowed to write Foo f = new Foo(); f.staticMethod(); |
| 15:17 | liwp` | it's not good style, but it's allowed |
| 15:17 | kotarak | I believe you. But it obviously doesn't work in Clojure. |
| 15:17 | liwp` | yep |
| 15:19 | mgarriss | (n00b warning) why does this: http://pastie.org/644262 produce this error: "java.lang.IllegalArgumentException: recur arg for primitive local: x must be matching primitive" |
| 15:21 | kotarak | mgarriss: Math/pow is double, while (/ x y) is maybe integer? (Just guessing) |
| 15:22 | chouser | pow returns a primitive double. / will only return a primitive double if both x and y are also |
| 15:23 | chouser | So (double (/ x y)) or (/ (double x) (double y)) |
| 15:23 | kotarak | The code is (/ x 10). So maybe (/ x 10.0)? |
| 15:23 | raek | anyway, if you are interested in taking a look at a newbie's code: http://github.com/raek/clojure-sandbox/blob/master/src/com/github/raek/xml_with_xmlns.clj |
| 15:24 | raek | all kinds of comments are welcomed |
| 15:25 | mgarriss | hmm, the (/ x 10.0) didn't work |
| 15:25 | kotarak | mgarriss: try chouser's tip |
| 15:26 | mgarriss | that was it! |
| 15:26 | Chousuke | (/ x (double 10)) should be enough, since x is already double |
| 15:26 | mgarriss | thx all |
| 15:26 | chouser | Chousuke: yep, hadn't read the paste yet. :-{ |
| 15:26 | chouser | er, :-P |
| 15:29 | mgarriss | i guess i'm not clear as to why i needed to do that |
| 15:30 | liwp` | ,(class (/ 10 2)) |
| 15:30 | clojurebot | java.lang.Integer |
| 15:30 | liwp` | ,(class (/ 10 2.0)) |
| 15:30 | clojurebot | java.lang.Double |
| 15:30 | chouser | mgarriss: when you create a local (via let or loop), if the value assigned to it will be a primitive, the local itself will be a primitive. |
| 15:30 | mgarriss | but shouldn't have x already been a double? |
| 15:30 | chouser | yes, x was indeed a primitive double. |
| 15:31 | chouser | so the problem was the recur, where you were trying to assign the result of (/ x 10) back to x |
| 15:32 | chouser | numeric literals in Clojure are boxed, so / sees a primitive double (x) and a instance of Integer (10) |
| 15:32 | mgarriss | boxed? |
| 15:32 | chouser | that causes / to compile to a form that would return a Number |
| 15:33 | chouser | boxed means non-primitive -- an instance of a Class that extends Object vs. a primitive which isn't an instance of any class type, it's a special built-in Java primitive. |
| 15:34 | mgarriss | this is all in an attempt to learn some more clojure and to prove this: http://en.wikipedia.org/wiki/Kaprekar_constant |
| 15:35 | mgarriss | i love clojure already, ruby is paying the bills but driving me nuts |
| 15:37 | crios | a "boxed" object lives in the "heap" memory, and it is garbage collected. A primitive datum lives in the stack |
| 15:37 | hoeck1 | mgarriss: mhh, strange, it disappears when wrapping the first recur form in a double: (recur (double (/ x 10)) ....) |
| 15:38 | crios | and it is not collected |
| 15:38 | chouser | so (double (/ x 10)) or (/ x (double 10)) should work. |
| 15:39 | mgarriss | chouser: i used the former |
| 15:39 | chouser | you can experiment with repl-utils/expression-info to see details about the return types including (primitive or not) of expressions. |
| 15:39 | chouser | mgarriss: the latter probably has slightly better performance, if that matters. |
| 15:39 | mgarriss | it does, i was just about to ask about that |
| 15:40 | chouser | (double (/ x 10)) will box the x, do the math, return a Double (boxed), and then unbox it to a double |
| 15:41 | chouser | (/ x (double 10)) will use an unboxed 10, do primitive math on it and use the result directly. |
| 15:41 | mgarriss | new version (i also had to subtract 1 from number of digits): http://pastie.org/644313 |
| 15:41 | Chousuke | I think (dec x) is more idiomatic than (- x 1) |
| 15:42 | mgarriss | good call |
| 15:42 | mgarriss | is dec more efficient then (- x 1) ? |
| 15:42 | mgarriss | i imagine it is |
| 15:43 | chouser | probably. |
| 15:43 | Chousuke | ~def dec |
| 15:43 | mgarriss | it's certainly easier to read |
| 15:43 | chouser | you should test any performance claims, as the JVM can do unexpected magic (or fail to perform expected magic) |
| 15:43 | Chousuke | well, apparently it uses some java magic... so maybe |
| 15:44 | chouser | but having said that, it looks like (double 10) may be unboxing that Integer every time. |
| 15:45 | chouser | you might try (def digits (let [ten (double 10)] (fn [number] ... (/ x ten) ...))) |
| 15:46 | crios | so the unbox occurs just one time? |
| 15:48 | chouser | right. the closure stored in digits would then close over the primitive 'ten' which would be used in the loop. Surely the JVM can perform magic on that. :-) |
| 15:48 | chouser | but again, you'd have to test on a fully warmed-up JVM to be sure |
| 15:49 | spuz | I'm having a bit of a weird problem with a method on a class not being found. Is there a way to enumerate all of the instance and static methods on a class from clojure? |
| 15:49 | herdrick | Hi. I'm wanting to use union and intersection for Maps (hashes). |
| 15:50 | chouser | spuz: try clojure.contrib.repl-utils/show |
| 15:50 | technomancy | spuz: in slime it's C-c I |
| 15:50 | herdrick | It looks like I can use clojure.set.project to make something that works like this but it's ugly |
| 15:50 | technomancy | or use repl-utils |
| 15:50 | herdrick | Like this: |
| 15:50 | herdrick | (project [map1 map2] (intersection (set (keys map1)) (set (keys map2)))) |
| 15:50 | mgarriss | ugh, now i need an undigits that undoes digits |
| 15:53 | hiredman | I was just reading a pdf that discussed the chaotic nature of performance on today's platforms |
| 15:56 | crios | maybe too many layers |
| 15:57 | hiredman | well, you get chaotic (extremely sensitive to initial conditions) performance behaviour from cpus even, but I'm sure the jvm's optimizing (or not) doesn't help |
| 15:58 | herdrick | part of the problem is that what I want isn't really just an intersection of the keys of the maps, |
| 15:59 | herdrick | but rather new maps of a subset of each original map |
| 15:59 | clojurebot | new Class(x) is (Class. x) |
| 16:01 | herdrick | sorry: new maps, each a subset of one of the original maps, |
| 16:01 | herdrick | using the keys found in both |
| 16:04 | crios | cloning the values of those keys? |
| 16:06 | kotarak | herdrick: this are probably not well-defined operations. What happens in this case: (hypothetical-map-union {:a 2 :b 3} {:b 4 :c 5})? |
| 16:07 | mgarriss | undigits was much easier: (defn undigits [numbers] (reduce + (map #(* %2 %) powers-of-10 (reverse numbers)))) |
| 16:08 | chouser | could use * instead of #(* %2 %) |
| 16:08 | kotarak | herdrick: union is merge, btw. intersection can probably be done with select-keys. |
| 16:08 | herdrick | kotarak: sorry, i think my irc client is doing something funny with your code. What's the second key of your second Map? |
| 16:09 | kotarak | herdrick: colon c (or (keyword "c")) |
| 16:09 | kotarak | ,(merge {:a 2 :b 3} {:b 4 :c 5}) |
| 16:09 | clojurebot | {:c 5, :a 2, :b 4} |
| 16:09 | herdrick | Also, yes, map-union would need to be like merge or merge-into |
| 16:09 | kotarak | ,(select-keys {:a 2 :b 3} [:b]) |
| 16:09 | clojurebot | {:b 3} |
| 16:10 | kotarak | (where [:b] is the intersection of the keys of the two maps) |
| 16:11 | kotarak | ,(let [m1 {:a 2 :b 3} m2 {:b 3 :c 4}] (select-keys m1 (clojure.set/intersection (set (keys m1)) (set (keys m2))))) |
| 16:11 | clojurebot | {:b 3} |
| 16:12 | mgarriss | chouser: good call, not sure what i was thinking there |
| 16:14 | herdrick | kotarak: but you are only preserving the values for m1 there |
| 16:15 | herdrick | kotarak: i want both |
| 16:15 | crios | ,(class (seq [])) |
| 16:15 | clojurebot | nil |
| 16:15 | kotarak | herdrick: that's where the "not well-defined" comes into play. |
| 16:15 | herdrick | kotarak: the code I pasted in above does that |
| 16:15 | crios | Why is it nil? Shouldnt'it be an empty sequence? |
| 16:15 | herdrick | here it is again: |
| 16:15 | herdrick | (project [map1 map2] (intersection (set (keys map1)) (set (keys map2)))) |
| 16:15 | chouser | crios: seq on an empty collection returns nil |
| 16:15 | hiredman | crios: what does (seq []) return? |
| 16:16 | herdrick | kotarak: well, it only takes a careful definition... :) |
| 16:16 | herdrick | but thanks, |
| 16:16 | kotarak | herdrick: then it's not "intersection" of maps |
| 16:16 | kotarak | herdrick: your code must return something different |
| 16:16 | herdrick | right, it returns two maps |
| 16:16 | crios | seq [] returns null, mm thank you |
| 16:17 | herdrick | so it isn't really an intersection |
| 16:17 | herdrick | it |
| 16:17 | herdrick | it's something else |
| 16:17 | herdrick | BTW I just used clojure.set/project because it seems to do what I wanted but I don't really understand the short description of it |
| 16:18 | kotarak | ,(let [m1 {:a 2 :b 3} m2 {:b 3 4} intersected-keys (clojure.set/intersection (set (keys m1)) (set (keys m2)))] (vector (select-keys m1 intersected-keys) (select-keys m2 intersected-keys))) |
| 16:18 | clojurebot | 3 |
| 16:19 | kotarak | ,(let [m1 {:a 2 :b 3} m2 {:b 3 :d 4} intersected-keys (clojure.set/intersection (set (keys m1)) (set (keys m2)))] (vector (select-keys m1 intersected-keys) (select-keys m2 intersected-keys))) |
| 16:19 | clojurebot | [{:b 3} {:b 3}] |
| 16:22 | herdrick | ,(let [m1 {:a 1 :b 2} m2 {:b 3 :c 4}] (clojure.set/project [m1 m2] (clojure.set/intersection (set (keys m1)) (set (keys m2))))) |
| 16:22 | clojurebot | #{{:b 2} {:b 3}} |
| 16:22 | herdrick | kotarak: that's the way i was doing it |
| 16:23 | kotarak | herdrick: well, ... when it works. :) It's shorter. |
| 16:23 | herdrick | kotarak: but your way is possibly superior |
| 16:23 | herdrick | kotarak: thanks for the help |
| 16:23 | kotarak | herdrick: maybe, maybe not. But it's good to know select-keys :) |
| 16:24 | herdrick | kotarak: it sounds like you know more about sets in Clojure than me. Can you tell me about clojure.set/project ? |
| 16:24 | herdrick | I don't get what xrel is in the docs |
| 16:24 | kotarak | herdrick: oehm... actually never used it :P |
| 16:24 | kotarak | Let's see. |
| 16:24 | kotarak | (doc clojure.set/project) |
| 16:24 | clojurebot | "([xrel ks]); Returns a rel of the elements of xrel with only the keys in ks" |
| 16:24 | herdrick | kotarak: me neither until now |
| 16:25 | kotarak | Just watching Joshua Bloch's "How to Design a Good API and Why it matters": don't use cryptic abreviations.... |
| 16:26 | herdrick | kotarak: indeed |
| 16:28 | kotarak | Well. It simply maps select-keys over the xrel part. |
| 16:28 | kotarak | And turns the result again into set. (Which might not be what you want.) |
| 16:28 | kotarak | ,(let [m1 {:a 1 :b 2} m2 {:b 2 :d 4}] (clojure.set/project [m1 m2] (clojure.set/intersection (set (keys m1)) (set (keys m2))))) |
| 16:28 | clojurebot | #{{:b 2}} |
| 16:28 | herdrick | kotarak: yeah, except for the "turns the result again into set" part |
| 16:29 | herdrick | kotarak: that breaks my code when the two new maps are the same |
| 16:29 | kotarak | exactly |
| 16:29 | herdrick | kotarak: exactlt! |
| 16:29 | herdrick | sorry, exactly! |
| 16:29 | herdrick | lol |
| 16:29 | herdrick | kotarak: i'm going with your version |
| 16:29 | herdrick | kotarak:thanks |
| 16:30 | kotarak | herdrick: np |
| 16:37 | mgarriss | how do i combine 2 vectors into one? |
| 16:38 | chouser | ,(into [1 2 3] [4 5 6]) |
| 16:38 | clojurebot | [1 2 3 4 5 6] |
| 16:38 | mgarriss | thx |
| 16:39 | hircus | ,(reduce conj [1 2 3] [4 5 6]) |
| 16:39 | clojurebot | [1 2 3 4 5 6] |
| 16:39 | mgarriss | how do i create a vector of some given size containing all zeroes? |
| 16:39 | clojurebot | with style and grace |
| 16:40 | chouser | into should use transients while reduce conj I think would not. |
| 16:40 | mgarriss | i don't really understand the reduce method |
| 16:40 | chouser | ,(vec (repeat 12 0)) |
| 16:40 | clojurebot | [0 0 0 0 0 0 0 0 0 0 0 0] |
| 16:41 | hircus | for each element in the second sequence, it applies conj to the first sequence and that element, and then repeats with the resulting sequence and the rest of the second sequence |
| 16:41 | hircus | ,(doc reduce) |
| 16:41 | clojurebot | "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the r |
| 16:42 | mgarriss | i see, very cool |
| 16:42 | hircus | mgarriss: this is probably a more obvious example: ,(reduce * [1 2 3]) |
| 16:42 | hircus | ,(reduce * [1 2 3]) |
| 16:42 | clojurebot | 6 |
| 16:42 | kotarak | hilarious : http://www.youtube.com/watch?v=aAb7hSCtvGw#46m0s |
| 16:43 | kotarak | rather http://www.youtube.com/watch?v=aAb7hSCtvGw#t=46m0s |
| 16:43 | hiredman | clojurebot: botsnack |
| 16:43 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 16:44 | hircus | or defining factorial this way |
| 16:44 | hircus | ,(reduce * (take 5 (iterate inc 1))) |
| 16:44 | clojurebot | 120 |
| 16:49 | mgarriss | i can see myself using reduce a lot in the future |
| 17:13 | rosejn | What's the best way to look at *err* while in the repl? |
| 17:14 | tomoj | rosejn: I'm not sure that makes sense |
| 17:14 | rosejn | hmmm, ok |
| 17:14 | ambient | *e |
| 17:14 | tomoj | oh, now I get it. been awake too long. :( |
| 17:14 | ambient | ? |
| 17:14 | rosejn | I'm trying to use clojure.contrib.logging |
| 17:14 | ambient | (i dont even know what *err* does) |
| 17:15 | tomoj | it's STDERR, no? |
| 17:15 | rosejn | It's just like another standard out, but for errors |
| 17:15 | ambient | ok |
| 17:15 | rosejn | a pipe you can connect to things |
| 17:15 | tomoj | you mean the slime repl or a plain old repl? |
| 17:15 | rosejn | vimclojure repl |
| 17:16 | rosejn | I've inserted (log :debug "my msg here...") messages, but it seems that clojure.contrib.logging is sending stuff to *err* |
| 17:17 | rosejn | it's also not clear how to set the log-level... |
| 17:17 | tomoj | I suppose that's vimclojure's business, not clojure's? (the former) |
| 17:17 | mgarriss | i need a function that returns any repeating pattern in a vector: (foobar [3 4 19 2 4 2 4 2 4 2]) ==> [2 4] |
| 17:17 | mgarriss | or i should say the first repeating pattern found |
| 17:18 | lisppaste8 | crios pasted "ternary if" at http://paste.lisp.org/display/88306 |
| 17:19 | crios | sure do exits a better way than my "ternary if" in http://paste.lisp.org/display/88306 |
| 17:19 | crios | *exists |
| 17:19 | chouser | crios: you want :else ? |
| 17:20 | crios | mmm I think so. but can I put an if inside cond? |
| 17:21 | crios | BTW, why (memq 'n '(a b c) ) throw a StackOverflowException? |
| 17:21 | hiredman | cond checks for true values |
| 17:22 | hiredman | not nil and not false |
| 17:22 | chouser | crios: 'rest' always returns a seq, perhaps an empty one |
| 17:22 | chouser | you probably want 'next' |
| 17:22 | hiredman | :else is not nil and not false, so it can be used as a catch-all there |
| 17:23 | technomancy | so... it looks like the use-fixtures function is not really intended for interactive development since it keeps wrapping more and more fixture functions around the test functions rather than being idempotent |
| 17:23 | technomancy | I wonder if there's a way to fix that |
| 17:23 | chouser | ,(some #{'b} '(a b c)) |
| 17:23 | clojurebot | b |
| 17:23 | crios | chouser: mmm ok, I check that |
| 17:23 | chouser | crios: is that what you want? |
| 17:24 | crios | yes :-( |
| 17:24 | technomancy | you could store the fixtures as a set, but then you lose the ability to order it. |
| 17:25 | crios | chouser: but also studying this: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html , just for "set the stage" |
| 17:25 | crios | [memq example is there, written in Scheme] |
| 17:36 | lisppaste8 | crios annotated #88306 "goes in StackOverflow" at http://paste.lisp.org/display/88306#1 |
| 17:37 | crios | another try: I'm using next in this implementation, but I get a StackOverflow |
| 17:38 | lisppaste8 | Chouser annotated #88306 "some other versions" at http://paste.lisp.org/display/88306#2 |
| 17:40 | crios | thank Chouser; I'll study it. But why :else is not documentated here http://clojure.org/API#toc161 ? |
| 17:41 | chouser | crios: it's just convention -- any true value will do |
| 17:41 | crios | ah ok, it is a keyword which evalutes to true, isn't it? |
| 17:41 | chouser | crios: right |
| 17:43 | crios | an other question: in your second example, (recur calls memq itself, right? |
| 17:43 | chouser | crios: yes |
| 17:43 | chouser | but without cosuming a stack frame, so no stack overflow |
| 17:46 | crios | it seems that the trick is the (when function: |
| 17:47 | chouser | (when x y z) is just (if x (do y z)) |
| 17:47 | lisppaste8 | crios annotated #88306 "untitled" at http://paste.lisp.org/display/88306#3 |
| 17:48 | crios | I mean, that last implemention doesn't go in StackOverflow |
| 17:48 | crios | (thought your is sure better) |
| 17:49 | crios | *though |
| 17:52 | chouser | (next x) returns nil when x has zero or 1 items left. nil acts as false so we stop looping |
| 17:52 | chouser | gotta go. |
| 17:57 | crios | so here http://paste.lisp.org/display/88306#1 memq is infinitely called with arguments (item nil) ? |
| 17:58 | crios | Using when, the recursive call with (item nil) is not tried |
| 17:58 | crios | I think it makes sense |
| 18:08 | MetaReilly | Are there current instructions for setting up slime and swank manually (NOT using clojure-install)? |
| 18:09 | spaceman_stu | is there a way to iterate over a transient vector? something like (doseq [i (transient [1 2])] i)? |
| 18:09 | technomancy | spaceman_stu: I don't know if you're supposed to use transients while they're still transient |
| 18:10 | mgarriss | let's say i wanted to use clojure to draw a fractal. is the AWT my best bet here for the actual displaying? |
| 18:10 | technomancy | mgarriss: clj-processing is probably the easiest |
| 18:10 | spaceman_stu | technomancy: get and nth work. Those are along the same lines, no? |
| 18:11 | hiredman | spaceman_stu: you would need to use some kind o reduce operation |
| 18:11 | hiredman | of |
| 18:11 | spaceman_stu | I don't understand why |
| 18:12 | mgarriss | MetaReilly: here is the clojure section of my .emacs, i just started using clojure so it probably has issues but it might help you: http://pastie.org/644604 |
| 18:13 | MetaReilly | mgarriss: thanks |
| 18:13 | hiredman | spaceman_stu: because you are supposed to keep the result of the transient mutation operations |
| 18:13 | MetaReilly | mgarriss: i was using the old slime/swank setup from before the new automated install and find the automated setup annoying |
| 18:13 | mgarriss | MetaReilly: you'll have to build the swank-clojure jar using maven first |
| 18:14 | mgarriss | MetaReilly: me too |
| 18:14 | MetaReilly | mgarriss: Thanks |
| 18:14 | technomancy | MetaReilly: you could read the source to clojure-install. =) |
| 18:15 | MetaReilly | technomancy: I had started to do that and decided that it would be worth asking if somebody had a recipe handy |
| 18:15 | hiredman | clojurebot: transient is <reply> Don't bash in place |
| 18:15 | clojurebot | 'Sea, mhuise. |
| 18:20 | mgarriss | technomancy: clj-processing looks perfect, thx for the lead |
| 18:20 | clojurebot | technomancy is to blame for all failures |
| 18:21 | hiredman | ~laugh |
| 18:21 | clojurebot | ha ha |
| 18:21 | technomancy | clojurebot: maybe so, but hiredman is to blame for all errors |
| 18:21 | clojurebot | 'Sea, mhuise. |
| 18:21 | technomancy | wait, did that just do what I think it did? |
| 18:21 | technomancy | clojurebot: hiredman? |
| 18:21 | clojurebot | hiredman is lazy |
| 18:22 | technomancy | clojurebot: maybe so, but hiredman? |
| 18:22 | clojurebot | maybe so, but hiredman is to blame for all errors |
| 18:22 | technomancy | clojurebot: forget maybe so, but hiredman |
| 18:22 | clojurebot | I forgot maybe so, but hiredman |
| 20:43 | herdrick_ | l |
| 20:49 | enderoute | how do you set a breakpoint in jswat for a running clojure repl? I see all my functions in the "classes" list to the left, i right click and add a breakpoint, but it doesn't seem to stop when i call the function from the repl |
| 23:32 | jaiganesh | hi |
| 23:32 | jaiganesh | i have a problem |
| 23:33 | jaiganesh | i am trying to use lcm function but getting this error |
| 23:33 | jaiganesh | java.lang.Exception: Unable to resolve symbol: lcm |
| 23:33 | jaiganesh | i have use clojure.contrib.math dont hsi |
| 23:34 | jaiganesh | i have included the namespace "use clojure.contrib.math" |
| 23:36 | jaiganesh | anyone? |
| 23:37 | jaiganesh | hi room |
| 23:37 | jaiganesh | i have aproblem |
| 23:37 | jaiganesh | i am trying to use lcm function but getting this error |
| 23:37 | jaiganesh | java.lang.Exception: Unable to resolve symbol: lcm |
| 23:37 | jaiganesh | i have included the namespace "use clojure.contrib.math" |
| 23:43 | jaiganesh | hi room |
| 23:48 | adityo | hey |
| 23:54 | rongenre | Looking for an idiom: I have a bunch of vectors, all equal length. Want to treat them like a table, search, select based upon it. Like in R with dataframes |
| 23:57 | arbscht | ,(doc filter) |
| 23:57 | clojurebot | "([pred coll]); " |
| 23:58 | rongenre | well sure. I can filter one vector |
| 23:58 | arbscht | ,(filter (comp odd? first) [[1 2 3] [4 5 6] [7 8 9] [10 11 12] [13 14 15]]) |
| 23:58 | clojurebot | ([1 2 3] [7 8 9] [13 14 15]) |
| 23:58 | rongenre | But I want to use it to index the rest. |
| 23:59 | somnium | rogenre: something like (filter identity (map #(filter pred vec) bunch-of-vecs)) ? |
| 23:59 | rongenre | so it'd take that to [1 3] [4 6] [7 9] [...] |