2009-04-08
| 00:03 | hiredman | http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html <-- java on app engine |
| 00:05 | cmvkk | aw, Groovy, Scala and JRuby get a mention but not Clojure. is this still a second-class JVM language? |
| 00:08 | danlarkin | hey now |
| 00:08 | danlarkin | that's a neat thing |
| 00:09 | durka42 | maybe it will get mentioned when we implement it :) |
| 00:11 | durka42 | great minds think alike |
| 00:11 | hiredman | did someone just grab the clojure1 app identifier? |
| 00:11 | durka42 | clojurebot: great minds think alike is <reply>and fools rarely differ |
| 00:11 | clojurebot | In Ordnung |
| 00:11 | durka42 | ~great minds think alike |
| 00:11 | clojurebot | and fools rarely differ |
| 00:12 | hiredman | cause I tried to get clojure1, the check availability button said it was availble, then when I clicked "next" it said it was in use |
| 00:15 | Drakeson | is there something similar to map that applies the function f first to the whole coll, then to (rest coll), then to (rest (rest coll)), etc. (as opposed to applying f to (first coll), then (second coll), etc. ? |
| 00:16 | cmvkk | not built in, to my knowledge |
| 00:16 | Chouser | (map foo (take-while identity (iterate next coll))) |
| 00:17 | Drakeson | wow, (iterate next coll) is a nice idiom. thanks |
| 00:19 | cmvkk | iterate-while might be a worthwhile function to have |
| 00:19 | Chouser | "For instance, an app cannot spawn threads" ...google app engine |
| 00:19 | Chouser | cmvkk: it's come up |
| 00:19 | cmvkk | hmm |
| 00:19 | Chouser | oh |
| 00:19 | Chouser | take-while identity has come up, I think |
| 00:20 | durka42 | hmm, no threads could be an issue |
| 00:20 | cmvkk | does clojure implicitly use threads or something? |
| 00:21 | cmvkk | i don't mean with agents, of course |
| 00:21 | Chouser | http://groups.google.com/group/clojure/msg/f88b1675635837a2 -- iterate-while |
| 00:22 | hiredman | No, an App Engine app may not spawn new threads |
| 00:22 | hiredman | oh |
| 00:23 | cmvkk | so, when you send to an agent, are you spawning a thread? |
| 00:23 | cmvkk | if not, when do the threads in a thread pool get spawned? |
| 00:23 | cmvkk | or is it more subtle than all that. |
| 00:27 | hiredman | cmvkk: when you send-off, the executor must be creating a thread |
| 00:27 | cmvkk | yes. but with send, maybe it's not as clear |
| 00:28 | cmvkk | how often are agents used in web application code anyway? |
| 00:28 | hiredman | with send the threadpool creates the threads when it is created |
| 00:29 | cmvkk | right, and when is the threadpool created? |
| 00:29 | hiredman | how does that matter? |
| 00:29 | cmvkk | if it's created the first time you use send, then you can use any clojure code as long as you don't use agents. |
| 00:30 | cmvkk | if it's created no matter what, or something, then won't it be a problem for any clojure code? |
| 00:31 | durka42 | i suppose it would depend on how silently google makes spawning threads fail |
| 00:32 | durka42 | i don't know the answer to your question |
| 00:32 | cmvkk | right. if google kills the process if it tries to spawn a thread, it might be a problem. |
| 00:33 | durka42 | ,(.getPoolSize clojure.lang.Agent/pooledExecutor) |
| 00:33 | clojurebot | 1 |
| 00:33 | durka42 | in my repl (having not used any agents yet) that returns zero |
| 00:34 | durka42 | ~javadoc clojure.lang.Agent |
| 00:34 | hiredman | uh |
| 00:34 | durka42 | er |
| 00:34 | durka42 | i don't expect that to work |
| 00:34 | hiredman | ~def c.l.Agent |
| 00:34 | durka42 | ~javadoc java.util.concurrent.ThreadPoolExecutor |
| 00:35 | cmvkk | based on that test, it seems like there's not really a problem, though. |
| 00:35 | durka42 | ,(.getCorePoolSize clojure.lang.Agent/pooledExecutor) |
| 00:35 | clojurebot | 3 |
| 00:36 | durka42 | setCorePoolSize Sets the core number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle. If larger, new threads will, if needed, be started to execute any queued tasks. |
| 00:36 | durka42 | that sounds like they still aren't created unless there are tasks on the queue |
| 00:39 | slashus2 | The thread pool is created when the agent is created. |
| 00:40 | slashus2 | ? |
| 00:43 | durka42 | no, it is a static member |
| 00:43 | durka42 | ,(.pooledExecutor (agent nil)) |
| 00:43 | clojurebot | java.lang.IllegalArgumentException: No matching field found: pooledExecutor for class clojure.lang.Agent |
| 00:43 | slashus2 | okay |
| 00:43 | durka42 | ^- wat |
| 00:49 | slashus2 | So all send-off's use the same thread pool? |
| 00:49 | durka42 | i think the pooledExecutor is for send |
| 00:49 | durka42 | send-off's are handled by the soloExecutor |
| 00:49 | durka42 | i think |
| 00:50 | slashus2 | ,(.pooledExecutor clojure.lang.Agent) |
| 00:50 | clojurebot | java.lang.IllegalArgumentException: No matching field found: pooledExecutor for class java.lang.Class |
| 00:50 | durka42 | ,(.getPoolSize clojure.lang.Agent/soloExecutor) |
| 00:50 | clojurebot | 1 |
| 00:50 | dnolen | first public GAE app? |
| 00:50 | dnolen | http://guestbook-clj.appspot.com/ |
| 00:50 | slashus2 | ,clojure.lang.Agent/pooledExecutor |
| 00:50 | clojurebot | #<ThreadPoolExecutor java.util.concurrent.ThreadPoolExecutor@197f158> |
| 00:50 | slashus2 | ,(clojure.lang.Agent/pooledExecutor) |
| 00:50 | clojurebot | #<ThreadPoolExecutor java.util.concurrent.ThreadPoolExecutor@197f158> |
| 00:50 | dnolen | nice write up here |
| 00:50 | dnolen | http://elhumidor.blogspot.com/2009/04/clojure-on-google-appengine.html |
| 00:51 | durka42 | cool! |
| 00:52 | durka42 | this demands playing with this weekend |
| 00:53 | cmvkk | that was fast |
| 00:53 | cp2 | oh nice |
| 00:54 | slashus2 | http://guestbook-clj.appspot.com/exercise What do you make of this? |
| 00:55 | cp2 | heh |
| 00:55 | cp2 | haha |
| 00:55 | cp2 | anon anon anon... |
| 00:55 | cp2 | kinda like debian random generator |
| 00:55 | cp2 | 9 9 9 9 9 .. |
| 00:56 | slashus2 | Why exactly is the atom value jumping around? |
| 00:56 | dnolen | yeah AppEngine is distributed across JVMs so you really can't really on refs/atoms |
| 00:56 | slashus2 | ooh |
| 00:57 | slashus2 | That is the number of visitors. |
| 00:59 | hiredman | me too |
| 01:00 | hiredman | dnolen: that doesn't make sense to me |
| 01:00 | hiredman | well |
| 01:00 | hiredman | hmmm |
| 01:01 | dnolen | hiredman: could be wrong, but I think what happens is the first request is handled by one jvm |
| 01:01 | dnolen | the next request might not be. |
| 01:01 | slashus2 | google broke it :-( |
| 01:01 | durka42 | so if you don't write something out to disk it's not guaranteed to persist across requests? |
| 01:02 | hiredman | no write to disk |
| 01:03 | dnolen | well not to disk, but to whatever store google provides. |
| 01:03 | durka42 | well database or whatever |
| 01:11 | hiredman | http://fragmental.tw/2009/04/08/clojure-on-google-app-engine/ |
| 01:30 | durka42 | hey, it's an email |
| 01:30 | hiredman | ! |
| 01:31 | hiredman | me too |
| 01:31 | durka42 | however, bedtime |
| 02:17 | kadaver | ok guys time to launch compojure apps on appengine! |
| 02:18 | hiredman | it's been done, at least twice already |
| 02:22 | slashus2 | Does Common Lisp have multi-methods comparable to clojure's? |
| 02:23 | cmvkk | it has the object system |
| 02:23 | cmvkk | which allows you to define methods |
| 02:23 | cmvkk | but it isn't like clojure |
| 02:24 | slashus2 | CL's methods can dispatch on value? |
| 02:25 | cmvkk | no, they dispatch on class type. |
| 02:25 | cmvkk | that's why it isn't like clojure. |
| 02:25 | slashus2 | Hmm, I am getting some mixed information. |
| 02:25 | cmvkk | well, don't take my word for it... |
| 02:25 | cmvkk | if someone is telling you otherwise, they're probably right. |
| 02:26 | slashus2 | I don't know about that. |
| 02:26 | cmvkk | my understanding is that CLOS is just a regular object system. you define classes, then you define methods which dispatch on the class of each argument. |
| 02:28 | blbrown | is everyone on the appengine train |
| 02:29 | hiredman | yes |
| 02:34 | lisppaste8 | jauk pasted "Problem with lazy parsing of xml" at http://paste.lisp.org/display/78235 |
| 02:34 | jauk | I can't get the lazy parsing of xml working correctly |
| 02:35 | jauk | If anyone has time to look at the code above, I would appreciate it |
| 02:35 | jauk | i'm still a newbie with lisp (java background) |
| 02:36 | hiredman | no exceptions? |
| 02:37 | hiredman | I am unfamiliar with that lib, but the call to first, then the call to zip/node is very odd |
| 02:38 | jauk | well, with the default ram it gives finally outofmemoryexception |
| 02:38 | jauk | but with xMx=1000m xMs=1000m it just freezes |
| 02:39 | hiredman | you are sure it is not doing any work? |
| 02:39 | hiredman | how large is finland.osm? |
| 02:39 | jauk | well, it is doing work. but the idea would be that because of lazy parsing it shouldn't need to do much any work. |
| 02:40 | hiredman | that is a naive idea |
| 02:40 | jauk | finland.osm is quite large, 513 megs in total |
| 02:40 | hiredman | hmm |
| 02:40 | jauk | is it? |
| 02:41 | hiredman | ~lazy |
| 02:41 | clojurebot | lazy is hard |
| 02:41 | jauk | in the comments of the lazy-xml lib (http://github.com/dysinger/clojure-contrib/blob/36d13c6d40750b80b612921d5b3499d3a6c2fdb5/src/clojure/contrib/lazy_xml.clj): |
| 02:41 | jauk | ; When used with zip and zip-filter, you can get do queries like this |
| 02:41 | jauk | ; without parsing more than the first few tags: |
| 02:41 | jauk | ; (zip/node (first (xml-> (zip/xml-zip tree) :id))) |
| 02:41 | jauk | this is why i thought it should work |
| 02:43 | hiredman | maybe it should |
| 02:52 | lisppaste8 | jauk annotated #78235 "Further details" at http://paste.lisp.org/display/78235#1 |
| 02:59 | jauk | hiredman: thanks for your input! i guess i'll have to ask the question again later if someone else would have had experience with the lazy-xml library... |
| 03:00 | hiredman | Chouser is the xml filter guy, he is on central time (US) I believe |
| 03:00 | hiredman | there is also always the google group |
| 03:02 | jauk | ok, i'll have to ask him then, thanks! i didn't want to start by spamming the google-group with a newbie question :) (maybe there should be separately a stupid questions -group?) |
| 03:48 | dysinger | GAE yayz |
| 05:36 | leafw | any help with vimclojure |
| 05:37 | leafw | I forgot how to view the help page ... |
| 05:37 | leafw | kotarak is not here, *sigh* |
| 05:38 | Neronus | leafw: maybe :help vimclojure |
| 05:38 | Neronus | leafw: Or the doc directory whereever you installed the package |
| 05:53 | leafw | Neronus: :help vimclojure I tried, and variations, but didn't wokr |
| 05:53 | leafw | yeah the help is in a file; was just wondering how to access it from within vim |
| 06:17 | AWizzArd | ~ seen rhickey |
| 06:17 | clojurebot | no, I have not seen rhickey |
| 06:17 | AWizzArd | ~ max people |
| 06:17 | clojurebot | max people is 164 |
| 07:43 | cemerick | is there some usage for condp floating around somewhere? I don't quote grok it. |
| 07:50 | AWizzArd | ,(doc condp) |
| 07:50 | clojurebot | "([pred expr & clauses]); Takes a binary predicate, an expression, and a set of clauses. Each clause can take the form of either: test-expr result-expr test-expr :>> result-fn Note :>> is an ordinary keyword. For each clause, (pred test-expr expr) is evaluated. If it returns logical true, the clause is a match. If a binary clause matches, the result-expr is returned, if a ternary clause matches, its result-fn, which must be a unary function, is called |
| 07:51 | AWizzArd | ,(condp = (+ 5 4) 10 'it-is-10 9 'no-it-is-9) |
| 07:51 | clojurebot | no-it-is-9 |
| 07:51 | AWizzArd | ,(condp #(+ 1 %) (+ 5 4) 10 'it-is-10 9 'no-it-is-9) |
| 07:51 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--1583$pred--1585 |
| 07:52 | AWizzArd | yeah, nonsense |
| 07:52 | AWizzArd | Well, it takes the expression and does (pred exp clause), until there is a match |
| 07:53 | cemerick | yeah. I guess I just don't have a use-case for it. |
| 07:54 | AWizzArd | It is just less repetetive than |
| 07:54 | AWizzArd | ,(cond (= 10 (+ 5 4)) 'it-is-10 (= 9 (+ 5 4)) 'no-it-is-9) |
| 07:54 | clojurebot | no-it-is-9 |
| 07:54 | AWizzArd | where I need to repeat = and (+ 5 4) over and over again |
| 07:55 | cemerick | yeah, I got that. I just thought that there might have been more to it. |
| 09:17 | Lau_of_DK | Hey guys |
| 12:20 | danlarkin | quietest I've ever seen this channel! |
| 12:20 | pjstadig | shhh |
| 12:20 | pjstadig | clojurbot: whose job is it to keep danlarkin quiet? |
| 12:20 | pjstadig | clojurbot: who's job is it to keep danlarkin quiet? |
| 12:21 | danlarkin | you're spelling his name wrong |
| 12:21 | pjstadig | clojurebot: who's job is it to keep danlarkin quiet? |
| 12:21 | clojurebot | Titim gan �ir� ort. |
| 12:21 | pjstadig | clojurebot: whose job is it to keep danlarkin quiet? |
| 12:21 | clojurebot | that is alek_b's job |
| 12:21 | danlarkin | whose is correct, not who's |
| 12:21 | pjstadig | fourth time is the charm |
| 12:21 | danlarkin | sweet |
| 12:21 | rsynnott | why does that thing speak Irish? |
| 12:26 | pjstadig | so |
| 12:26 | pjstadig | one of the major issues left with Clojure + TC is the fact that you cannot assign a non-portable value as the root binding of a var |
| 12:27 | pjstadig | the most glaring example is *in*, *out*, and *err* |
| 12:27 | pjstadig | what we need is a way to specify specific values to share, and specific values to exclude |
| 12:28 | pjstadig | AWizzArd and I have been talking about it and I think he has some good ideas |
| 12:28 | pjstadig | we could add metadata values to specific vars that we would want to share |
| 12:28 | pjstadig | instead of automatically sharing everything |
| 12:30 | pjstadig | then the trick would be to fracture the namespace map so that when a var is resolved it is either fetched from a shared or a non shared mapping |
| 12:30 | pjstadig | is there a better way to do it? |
| 12:32 | pjstadig | anyone? anyone? bueller? |
| 12:32 | AWizzArd | rhickey maybe has an idea? :) |
| 12:33 | pjstadig | ~def clojure.lang.Namespace |
| 12:40 | pjstadig | the only problem i foresee is classes |
| 12:40 | pjstadig | if you add a var to the TC graph whose value is a compiled function |
| 12:41 | pjstadig | for that function to be used in another VM its class would have to get added to the graph |
| 12:41 | pjstadig | which could be done |
| 12:41 | pjstadig | but if that function depends on other functions those classes would have to be added as well |
| 12:42 | pjstadig | the only way around it might be to just add all of the classes into the TC graph |
| 13:13 | rhickey | pjstadig: It's too complex to explain here, but I am keeping in mind these TC issues in my work now on namespace modularity |
| 13:14 | Cark | hum i've fallen behind on the mailing list, did you talk about these changes there yet rhickey ? |
| 13:14 | kotarak | hmm... couldn't with-ns go to ns-utils instead of having a dedicated namespace? |
| 13:17 | rhickey | Cark: no changes yet to discuss |
| 13:18 | Cark | ok thanks ! i'm only slightly shaking at the thought of breaking changes |
| 13:18 | rhickey | Cark: This is for down-the-line post 1.0 |
| 13:18 | clojurebot | for is not a loop |
| 13:18 | Cark | ah nice =) |
| 13:18 | Cark | ~chouser? |
| 13:18 | clojurebot | chouser is ruthless about breaking other people's code |
| 13:20 | Neronus | is variable lookup in clojure performant, or is it always a good idea to avoid using vars? |
| 13:20 | Neronus | rhickey: Any plans when 1.0 will be released? And is there a roadmap available, or is it all in your head? |
| 13:21 | Chouse1 | rhickey: there's some pre-lazier verbage on clojure.org yet. I deleted a couple lines from "sequences", but there's still stuff in "lisps" |
| 13:21 | Cark | neronus : might be usefull to enclose a tight loop with a (let [myvar *myvar*] |
| 13:24 | AWizzArd | ,((fn [& args] (map class args)) 1 2 3) |
| 13:24 | clojurebot | (java.lang.Integer java.lang.Integer java.lang.Integer) |
| 13:24 | AWizzArd | ,(defmulti foo (fn [& args] (map class args))) |
| 13:24 | clojurebot | DENIED |
| 13:24 | AWizzArd | okay, if I do this defmulti, and then (defmethod foo '(Integer Integer Integer) [i] (print "Integers: " i)) |
| 13:25 | AWizzArd | (foo 1 2 3) ==> IllegalArgumentException: Wrong number of args passed to: user$fn |
| 13:25 | kotarak | AWizzArd: (defmethod .... [i] <- *m��p* |
| 13:26 | AWizzArd | Ah I see, it m��ps at that point. |
| 13:26 | Neronus | hehe.. moeep |
| 13:27 | AWizzArd | if I replace the [i] with [& i] now it funnily says: IllegalArgumentException: No method for dispatch value: clojure.lang.LazySeq@4319aced |
| 13:28 | kotarak | Try using vectors for the dispatch value. |
| 13:32 | rhickey | Chouser_: ok, thanks, welcome back! |
| 13:33 | rhickey | Neronus: 20090320 is feeling like a 1.0 release candidate to me, we (the community) have to have a discussion about what 1.0 means, esp. re: patching etc |
| 13:35 | rhickey | Neronus: the roadmap is in my head and somewhat in issues, and as always driven by what is happening, where people's (including my own) interests lie etc |
| 13:37 | cemerick | are there any expectations around patching at all? Very large frameworks might backport patches, but that's not at all a typical expectation in most environments (short of security-related stuff, if any). |
| 13:42 | jauk | Chouser_: i'm trying to do lazy xml parsing but with a huge xml file (500 megs) the application would seem to consume huge amounts of memory. do you have any tips? some code is here: http://paste.lisp.org/display/78235 |
| 13:43 | rhickey | cemerick: I imagine 1.0 is all about patching - being able to get fixes without new enhancements or breaking changes |
| 13:44 | eevar_ | rhickey: http://clojure.org/lisps -- the paragraph on sequences looks dated |
| 13:44 | rhickey | eevar_: yes, some of the site needs touchups to correspond to last release |
| 13:47 | Cark | jauk : i don't know the xml stuff, but it seems to me that a zip will retain all of the data, as it's supposed to be able to reconstruct the full thing |
| 13:47 | cemerick | rhickey: breaking changes, no, but without new enhancements? That's an unnecessary burden, I think (again, outside of security fixes). |
| 13:49 | jauk | Cark: ok, it could be that it just doesn't make sense to load a 500M xml. I was just hoping that with lazy evaluation it would just under the hood fetch only those items that are needed for computing the expected result (in the case of the example, the first matching node) |
| 13:50 | rhickey | cemerick: well, that's a topic for discussion - many people want 1.0 so they don't have to contend with 'changes' generically, rarely distinguishing breaking from non. Any core name introduction is potentially (trivially) 'breaking' code that used that name for something else |
| 13:50 | Cark | jauk : try doing your processing without the ziper |
| 13:52 | stuhood | rhickey: another way to distinguish breaking from non-breaking changes is to use major/point releases |
| 13:52 | jauk | Cark: hmm, i could try that |
| 13:52 | stuhood | rhickey: going straight to 1.0 instead of 0.9.* may be rushing things |
| 13:53 | cemerick | rhickey: eh, that's what :except is for in ns. |
| 13:53 | cemerick | I know that if we backported all fixes to each major release of our product, we'd go absolutely batshit insane. |
| 13:54 | rhickey | cemerick: I'm not arguing for or against, as I personally don't need 1.0. Those that do need to articulate what it means to them, and we need to see consensus |
| 13:54 | cemerick | rhickey: yeah, I know I'm arguing with the wind here :-) |
| 13:55 | rhickey | AFAIC, those that want fixes in the releases branch can backport them |
| 13:55 | cemerick | more important than what it means is who's going to do that maintenance? |
| 13:55 | rhickey | cemerick: precisely |
| 13:55 | jauk | Cark: it was just that the comments in lazy_xml seem to suggest that xml-zip can be used in a lazy fashion: http://paste.lisp.org/display/78235#1 |
| 13:55 | rhickey | who other than me |
| 13:56 | cemerick | right. And if you're not going to do it (thank goodness!), then what's the real point behind a v1.0 release w.r.t. patches (it certainly has good PR benefits). |
| 13:56 | Cark | jauk : right, but what if you access something toward the end ? the zipper will keep it all in order to be able to reconstruct the full xml |
| 13:57 | rhickey | cemerick: there will be a release branch, a policy for patches (fixes only), a version labeling system 1.0.1 etc |
| 13:57 | jauk | Cark: true. in the example code, i'm trying to access the first sub-node in the xml file, so - in theory - that should work ok? |
| 13:58 | rhickey | Other than the PR side, my impression is that people want 1.0 for stability, but wouldn't consider that they are getting that if there were no fixes other than those on trunk |
| 13:58 | rhickey | they can fix on a release or an SVN version right now |
| 14:00 | rhickey | but aren't satisfied with that |
| 14:00 | jauk | Cark: thanks for your input! it might be that the approach of using xml-zip with a huge xml file is flawed. this whole lazy evaluation is quite difficult for a java coder to handle :) |
| 14:00 | rhickey | bbl |
| 14:00 | Cark | jauk : don't take my word for it |
| 14:00 | cemerick | obviously, it's very hard for me to see the argument |
| 14:20 | clojurenoob | Probably a stupid Q (I'm not too familiar with Java/JVM): are Clojure-compiled programs particularly amenable to decompilation compared to regular Java code? |
| 14:23 | AWizzArd | clojurenoob: yes, in some sense. I tried it, and while JAP can decompile, it produces programs that can't be compiled with javac again |
| 14:23 | AWizzArd | The code itself is not really human readable |
| 14:24 | clojurenoob | AWizzArd: are the names of functions mostly preserved? |
| 14:24 | AWizzArd | They still exist. |
| 14:24 | AWizzArd | So people could read your function names in clear text. |
| 14:24 | AWizzArd | We have two solutions for that |
| 14:24 | AWizzArd | One is: use a java obfuscator |
| 14:25 | jauk | i guess one could make a java bytecode -> clojure decompiler |
| 14:25 | AWizzArd | jauk: yes |
| 14:25 | Chousuke | You'd think the dynamicism makes decompilation less likely to produce anything understandable. |
| 14:25 | AWizzArd | right |
| 14:26 | AWizzArd | clojurenoob: while a obfuscator would be a good solution, you can also use a second method, a simple macro trick |
| 14:26 | AWizzArd | You write a macro which replaces defn |
| 14:26 | AWizzArd | This macro creates another defmacro |
| 14:26 | AWizzArd | It adds your function to a global vector |
| 14:27 | AWizzArd | Your macro manages all magic to find the right function out of your vector |
| 14:27 | AWizzArd | So, (defsecret foo [x] (+ x 20)) allows you to still say (foo 100) ==> 120 |
| 14:27 | clojurenoob | That's all very informative. Thanks! |
| 14:27 | AWizzArd | but (foo 100) will be ra macro |
| 14:27 | duncanm | can i put metadata in non-Clojure objects? |
| 14:28 | AWizzArd | and it will produce something like: ((get secret-functions 14) 120) |
| 14:28 | AWizzArd | clojurenoob: then no function name will be readable in clear text |
| 14:28 | AWizzArd | instead people could only see how you fetch functions out of this vector |
| 14:28 | duncanm | oh |
| 14:28 | clojurenoob | AWizzArd: wouldn't you need some kind of code walker to look for all function applications? (non-trivial presumably) |
| 14:29 | duncanm | symbols and collections |
| 14:29 | duncanm | sigh |
| 14:29 | AWizzArd | clojurenoob: no, you would use the defsecret macro only for functions that you write yourself. |
| 14:29 | clojurenoob | OK |
| 14:29 | AWizzArd | If you use existing clojure libs then their function names would stay readable. |
| 14:30 | kotarak | duncanm: you can implement clojure.lang.IMeta/clojure.lang.IObj with your object. Then they support meta/with-meta. |
| 14:31 | AWizzArd | ~ seen AWizzArd |
| 14:31 | clojurebot | AWizzArd was last seen in #clojure, 0 minutes ago saying: ~ seen AWizzArd |
| 14:32 | pjstadig | clojurebot: ~seen clojurebot |
| 14:32 | clojurebot | no, I have not seen ~seen clojurebot |
| 14:32 | hiredman | clojurebot: seen clojurebot? |
| 14:32 | clojurebot | Of course I have seen myself. |
| 14:32 | pjstadig | ah |
| 14:33 | duncanm | so the COND in Clojure is not like COND in Scheme in that it has an implicit BEGIN, is that right? |
| 14:33 | AWizzArd | pjstadig: the ~ is instead of "clojurebot:" |
| 14:33 | pjstadig | yeah i know |
| 14:33 | pjstadig | i realized afterward |
| 14:33 | kotarak | duncanm: no. It has no implicit do. |
| 14:33 | hiredman | "the definition of a lagacy application is one that works" |
| 14:34 | clojurenoob | I'm curious, Clojure seems like one of the most popular functional languages these days. How come it's still not in the ShootOut? (GHC, OCaml, SBCL and some virtual unknowns are) |
| 14:34 | duncanm | in Scheme (if test (begin (a) (b)) (begin (c) (d))) can be written (cond ((test (a) (b)) (else (c) (d)))) |
| 14:34 | duncanm | kotarak: ah |
| 14:34 | kotarak | duncanm: (cond test (do (a) (b)) :else (do (c) (d))) |
| 14:35 | duncanm | right |
| 14:35 | duncanm | in that case, it's not that much shorter than using IF |
| 14:35 | AWizzArd | clojurenoob: it is too new |
| 14:35 | AWizzArd | Clojure started to take off after Summer 2008 |
| 14:35 | kotarak | duncanm: it is for more than one test |
| 14:36 | hiredman | and the shootout is generaly not well enough thought of for anyone to bother with it |
| 14:36 | AWizzArd | clojurenoob: I think sooner or even sooner Clojure code will appear for the shootout. Maybe you will be the first to submit an entry ;) |
| 14:38 | cconstantine_ | I have the shootout on my computer, and I plan on doing some of the tasks for clojure (once i know clojure better and can really represent it) |
| 14:38 | cconstantine_ | I expect clojure to get performance very simlar to Java 6 Server |
| 14:39 | AWizzArd | I think this is not possible yet for these micro benchmarks. |
| 14:39 | hiredman | cconstantine_: generally the tasks in the shootout aren't long runner tasks |
| 14:40 | clojurenoob | Most shootout submissions start as lame entries by a noob. Then some angry expert rewrites them. |
| 14:40 | AWizzArd | Yes |
| 14:40 | cconstantine_ | yeah, I understand. If the solution involves compiling the .clj and running the resulting .class it should be near-identical to native java |
| 14:40 | pjstadig | maybe instead we could just make Chouser angry |
| 14:40 | pjstadig | and he'll write it to start with |
| 14:40 | cconstantine_ | hehe |
| 14:41 | hiredman | I don't think anything jvm based is really going to shine in short run tasks |
| 14:41 | cconstantine_ | some of them aren't all that short-running |
| 14:41 | AWizzArd | Although Java does pretty well in the shootout. |
| 14:42 | cconstantine_ | java does very respectably. |
| 14:43 | hiredman | I found ibm devzone article that said java object allocations take about 10 machine code instructions, while C++ takes around 100 |
| 14:43 | cconstantine_ | it does better than my spelling at the very least |
| 14:43 | clojurenoob | I'm also curious to see what a high-performance Clojure code would look like. Haskell code in the shootout is ugly, for example. (knucleotides, spectral norm, n-bodies). Clojure is "pure functional". How would you be mutating arrays (in n-bodies and others)? |
| 14:43 | hiredman | clojure is not "pure functional" |
| 14:44 | Chousuke | clojure is not purely fun... damn you |
| 14:44 | clojurebot | clojure is like life: you make trade-offs |
| 14:44 | hiredman | clojurebot: botsnack |
| 14:44 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 14:44 | Chousuke | clojure is perfectly capable of working with mutable java arrays :) |
| 14:44 | Cark | use java arrays ! |
| 14:44 | cconstantine_ | You don't mutate arrays in clojure. Every "modification" returns a new array with the modification in place. There are some very fancy things going on behind the scenes for that to be very fast |
| 14:44 | hiredman | cconstantine_: a vector is not an array |
| 14:45 | cconstantine_ | ok, array-like thinger |
| 14:45 | hiredman | "Clojure is an effort in pragmatic dynamic language design" |
| 14:45 | Chousuke | cconstantine_: Those are vectors. you can mutate Java arrays. |
| 14:45 | clojurenoob | Chousuke: I understand that, but doesn't mixing in mutation dangerous if you also want multithreading, etc? |
| 14:45 | hiredman | cconstantine_: you can make a normal java array |
| 14:45 | Chousuke | clojurenoob: sure. |
| 14:45 | cconstantine_ | using a normal java array isn't very clojure-ish |
| 14:45 | hiredman | java arrays are very mutable |
| 14:45 | Chousuke | clojurenoob: that's why normal clojure code doesn't use java arrays very often :) |
| 14:45 | Chousuke | the immutable data structures are nicer. |
| 14:45 | AWizzArd | Someone in here posted a link to this video: http://www.infoq.com/presentations/click-fast-bytecodes-funny-languages |
| 14:45 | hiredman | the keyword in that quote from http://clojure.org/rationale is pragmatic |
| 14:46 | AWizzArd | There a byte code expert explained that he found several things that Clojure could improve to run faster |
| 14:47 | hiredman | AWizzArd: I only heard two things |
| 14:47 | hiredman | tagged numbers and clojure does a lot of ephemeral object creation |
| 14:47 | hiredman | which isn't reall much of a slow down when you have a good gc and fast object allocation |
| 14:48 | cconstantine_ | would there be any benefit to having objects with the same value cached, so the next creation of a value-equal object would just return the already allocated object? |
| 14:48 | AWizzArd | ,(time (dotimes [i 1000000] (inc i))) |
| 14:48 | clojurebot | "Elapsed time: 54.802 msecs" |
| 14:49 | hiredman | cconstantine_: I doubt it |
| 14:49 | AWizzArd | try this loop in pure Java |
| 14:49 | hiredman | object allocation on the jvm is very cheap |
| 14:49 | cconstantine_ | hiredman: I can see (very easily) how the caching mechanism would be more costly than the allocation/gc |
| 14:49 | clojurenoob | Chousuke: when you do use mutable Java arrays (for performance) in the context of a bigger application in Clojure (possibly multithreaded), how do you mentally prove that using those mutable Java arrays is safe? |
| 14:49 | clojurebot | for is not used often enough. |
| 14:49 | Chousuke | clojurenoob: you're just careful |
| 14:50 | Chousuke | clojurenoob: or you copy them every time they exit your function |
| 14:50 | cconstantine_ | clojurebot: the reason to use the immutable types is that it saves you from all that stuff; if you don't use them you don't get the benefit. |
| 14:50 | clojurebot | Ok. |
| 14:50 | Chousuke | mutable arrays are meant to be used "locally" in clojure |
| 14:50 | hiredman | http://www.ibm.com/developerworks/java/library/j-jtp01274.html |
| 14:51 | Chousuke | ie. you shouldn't store data that is passed around a lot in java arrays |
| 14:51 | hiredman | "The JIT compiler can perform additional optimizations that can reduce the cost of object allocation to zero." |
| 14:52 | Chousuke | ,(time (dotimes [i 1000000] (let [i (int i)] (inc i)))) |
| 14:52 | clojurebot | "Elapsed time: 59.995 msecs" |
| 14:52 | Chousuke | hmm |
| 14:52 | Chousuke | actually |
| 14:52 | Chousuke | ,(time (dotimes [i 1000000] (unchecked-inc i))) |
| 14:52 | clojurebot | "Elapsed time: 55.9 msecs" |
| 14:53 | AWizzArd | Try this in pure Java: |
| 14:53 | AWizzArd | ,(time (let [x (make-array Integer/TYPE 1000000)] (dotimes [i (count x)] (aset-int x i i)) x)) |
| 14:53 | clojurebot | #<int[] [I@6258e1> |
| 14:53 | clojurebot | "Elapsed time: 653.335 msecs" |
| 14:54 | Chousuke | not too bad :/ |
| 14:54 | AWizzArd | it is not bad |
| 14:54 | hiredman | ,(time (amap unchecked-inc (.toArray (range 1000000)))) |
| 14:54 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$amap |
| 14:55 | AWizzArd | It just is for some reason (which I don't know) just dramatically much slower than Java. |
| 14:55 | hiredman | ,(time (amap unchecked-inc (make-array Integer/TYPE 1000000) (.toArray (range 1000000)))) |
| 14:55 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$amap |
| 14:55 | AWizzArd | no, not dramatically, but it *is* slower |
| 14:55 | hiredman | ,(doc amap) |
| 14:55 | clojurebot | "([a idx ret expr]); Maps an expression across an array a, using an index named idx, and return value named ret, initialized to a clone of a, then setting each element of ret to the evaluation of expr, returning the new array ret." |
| 14:57 | hiredman | ,(amap (.toArray (range 1000000)) 0 (make-array Integer/TYPE 1000000) inc) |
| 14:57 | clojurebot | java.lang.Exception: Unsupported binding form: (make-array Integer/TYPE 1000000) |
| 14:57 | hiredman | ok |
| 14:57 | hiredman | how the hell does amap work? |
| 14:58 | hiredman | ,(amap (.toArray (range 1000000)) 0 a inc) |
| 14:58 | clojurebot | java.lang.RuntimeException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: 0 |
| 14:58 | AWizzArd | hiredman: http://groups.google.de/group/comp.lang.lisp/browse_frm/thread/b24b85f18fee26d7/64a1f1e5ec115ac7?tvc=1#doc_20e2e2efb795f3cf |
| 14:59 | hiredman | AWizzArd: what is this? |
| 14:59 | AWizzArd | There is an example program in Clojure. |
| 15:00 | AWizzArd | In that thread I optimized it a bit, so it runs much faster than the initial version. |
| 15:00 | AWizzArd | But there is still something in which could be faster. |
| 15:00 | hiredman | does it show me how to use amap? |
| 15:01 | AWizzArd | no ;) |
| 15:01 | AWizzArd | I didn't try that |
| 15:01 | hiredman | ,(.toArray (range 1000000)) |
| 15:01 | clojurebot | #<Object[] [Ljava.lang.Object;@1984161> |
| 15:01 | hiredman | ,(into-array Integer/TYPE (range 1000000)) |
| 15:02 | clojurebot | #<int[] [I@1cc946b> |
| 15:02 | AWizzArd | I used (int-array ..) |
| 15:02 | AWizzArd | ,(doc int-array) |
| 15:02 | clojurebot | "([size-or-seq] [size init-val-or-seq]); Creates an array of ints" |
| 15:02 | hiredman | ,(int-array (range 1000000)) |
| 15:02 | clojurebot | #<int[] [I@a8cd58> |
| 15:02 | hiredman | ,(amap (int-array (range 1000000)) idx ret inc) |
| 15:02 | clojurebot | java.lang.IllegalArgumentException: argument type mismatch |
| 15:03 | AWizzArd | ~def amap |
| 15:04 | pjstadig | ,(amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget-int r x)))))) |
| 15:04 | clojurebot | java.lang.Exception: Unable to resolve symbol: aget-int in this context |
| 15:04 | pjstadig | ,(amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x)))))) |
| 15:04 | clojurebot | #<int[] [I@bde56d> |
| 15:04 | hiredman | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x))))))) |
| 15:04 | clojurebot | #<int[] [I@607135> |
| 15:05 | clojurebot | "Elapsed time: 179.273 msecs" |
| 15:05 | hiredman | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x))))))) |
| 15:05 | clojurebot | #<int[] [I@1e0312b> |
| 15:05 | clojurebot | "Elapsed time: 9607.864 msecs" |
| 15:05 | pjstadig | ,(print (seq (amap (into-array Integer/TYPE (range 10)) x r (do (aset-int r x (+ 1 (aget-int r x)))))))) |
| 15:05 | clojurebot | java.lang.Exception: Unable to resolve symbol: aget-int in this context |
| 15:05 | hiredman | woa |
| 15:05 | pjstadig | ,(print (seq (amap (into-array Integer/TYPE (range 10)) x r (do (aset-int r x (+ 1 (aget r x)))))))) |
| 15:05 | clojurebot | (1 2 3 4 5 6 7 8 9 10) |
| 15:05 | pjstadig | just checking if it's doing what I think it's doing |
| 15:06 | clojurenoob | ,(range 10) |
| 15:06 | clojurebot | (0 1 2 3 4 5 6 7 8 9) |
| 15:07 | pjstadig | why is unchecked-add so much slower? |
| 15:09 | pjstadig | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x)))))))) |
| 15:09 | clojurebot | #<int[] [I@14cbf3f> |
| 15:09 | clojurebot | "Elapsed time: 168.047 msecs" |
| 15:09 | gnuvince | I'd like to know too; every single time I've tried an unchecked-* operation, it turned out a *lot* slower than the regular operator. |
| 15:09 | AWizzArd | pjstadig: try that now in TC :) |
| 15:10 | pjstadig | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x)))))))) |
| 15:10 | clojurebot | #<int[] [I@16e1dd8> |
| 15:10 | clojurebot | "Elapsed time: 160.954 msecs" |
| 15:10 | pjstadig | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x)))))))) |
| 15:10 | clojurebot | #<int[] [I@4b1bcd> |
| 15:10 | clojurebot | "Elapsed time: 171.053 msecs" |
| 15:11 | pjstadig | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x))))))) |
| 15:11 | clojurebot | #<int[] [I@1aea0c1> |
| 15:11 | clojurebot | "Elapsed time: 8850.087 msecs" |
| 15:11 | pjstadig | holy crap |
| 15:11 | pjstadig | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x))))))) |
| 15:11 | clojurebot | #<int[] [I@1e84244> |
| 15:11 | clojurebot | "Elapsed time: 8873.324 msecs" |
| 15:11 | pjstadig | must be the int cast? |
| 15:12 | gnuvince | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x)))))) |
| 15:12 | clojurebot | #<int[] [I@15a5aff> |
| 15:12 | clojurebot | "Elapsed time: 171.652 msecs" |
| 15:12 | gnuvince | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset r x (+ 1 (aget r x)))))) |
| 15:12 | clojurebot | #<int[] [I@987e1e> |
| 15:12 | clojurebot | "Elapsed time: 149.145 msecs" |
| 15:13 | pjstadig | it looks like + is doing just about as well as unchecked-add |
| 15:14 | gnuvince | aset and + seem to be a tad faster than aset-int, unchecked-add and int |
| 15:14 | clojurenoob | addition probably isn't the bottleneck there. array read / write is more likely to be one. no? |
| 15:15 | Chousuke | (time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add 1 (int (aget r (int x))))))))) |
| 15:15 | Chousuke | oops |
| 15:15 | Chousuke | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add 1 (int (aget r (int x))))))))) |
| 15:15 | clojurebot | #<int[] [I@10f7ec9> |
| 15:15 | clojurebot | "Elapsed time: 189.218 msecs" |
| 15:15 | Chouser_ | literal ints are boxed |
| 15:15 | Chousuke | ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add (int 1) (int (aget r (int x))))))))) |
| 15:15 | clojurebot | #<int[] [I@798797> |
| 15:15 | clojurebot | "Elapsed time: 149.075 msecs" |
| 15:16 | hiredman | ,(time (.toArray (map inc (range 100000)))) |
| 15:16 | clojurebot | #<Object[] [Ljava.lang.Object;@19cfefb> |
| 15:16 | clojurebot | "Elapsed time: 138.24 msecs" |
| 15:16 | Chousuke | I wish I knew how to write a compiler that could optimise that :( |
| 15:16 | hiredman | Chouser seems to have started on a self hosted compiler |
| 15:17 | AWizzArd | Maybe when Clojure is rewritten completly in Clojure then Rich will add gradual typing to it. |
| 15:17 | AWizzArd | In that case Clojure could be in nearly each situation as fast as pure Java itself. |
| 15:17 | Chousuke | something simple like assuming that if one parameter is unboxed, then others are unboxed too |
| 15:17 | Chousuke | since mixing unboxed and boxed numbers is impossible anyway |
| 15:18 | Chousuke | hmm... |
| 15:19 | Chousuke | Yeah, I'm hoping that after the compiler is rewritten in clojure it'll get more attention :P |
| 15:20 | clojurenoob | GHC is written in Haskell, but real applications are lacking (despite the language being probably 20 years old) |
| 15:22 | Chousuke | easter pudding is funky stuff. looks like shit but tastes good. |
| 15:22 | Chousuke | both impressions are amplified with the addition of some cream |
| 15:24 | SethTisue | does anyone know what made Rich decide to rewrite Clojure in Clojure? |
| 15:24 | SethTisue | I asked him about this at Boston Lisp Meeting and he seemed kind of dismissive about it, like it wouldn't be worth the effort |
| 15:24 | SethTisue | wondering why he seems to have changed his mind. |
| 15:24 | pjstadig | Chouser is the one writing the Clojure compiler in Clojure |
| 15:25 | pjstadig | but Rich is generally supporting, i think |
| 15:25 | SethTisue | ohh, interesting. |
| 15:25 | SethTisue | ok, supportive if someone else does it :-) |
| 15:25 | AWizzArd | SethTisue: he explained it some days ago. |
| 15:25 | kotarak | SethTisue: He said something about it being easier to port to different platforms like .NET and such. |
| 15:25 | AWizzArd | gnuvince asked him 2 days ago or so |
| 15:25 | gnuvince | Saturday around noon iirc |
| 15:25 | AWizzArd | Also Clojure in Clojure would open the door for a static type system. |
| 15:25 | pjstadig | http://github.com/Chouser/clojure-compiler/tree/master |
| 15:26 | pjstadig | ~logs? |
| 15:26 | clojurebot | logs is http://clojure-log.n01se.net/ |
| 15:26 | gnuvince | Basically he talked about: improved performance, doing things that cannot be done at the moment (accepting/returning primitive types), tool support, easier to port to other backends, etc. |
| 15:27 | SethTisue | hmm, that log site stops at Sunday |
| 15:27 | pjstadig | that brings up an interesting point though |
| 15:27 | SethTisue | making it more portable certainly makes a lot of sense |
| 15:27 | hiredman | SethTisue: rich has mentioned self-hosting has a post 1.0 priority |
| 15:27 | pjstadig | there seems to be some backlash in here about writing clojure libraries instead of using a Java lib |
| 15:27 | SethTisue | the other issues, I can imagine. |
| 15:28 | SethTisue | improved performane, though? really? |
| 15:28 | pjstadig | but if Clojure is hosted on .NET as well, then a pure clojure lib would be more portable |
| 15:29 | gnuvince | 11:17 < rhickey> gnuvince_: improved efficiency removes need to drop to Java - a new implements construct replaces proxy with code as fast as implement-the-interface-in-java |
| 15:29 | gnuvince | < rhickey> removal of any impediments keeping you from defining things like the data structures in Clojure itself |
| 15:29 | gnuvince | < rhickey> better modularity, see above |
| 15:29 | gnuvince | < rhickey> much easier porting to other hosts - JS, CLR, AS3, ObjC? etc |
| 15:29 | gnuvince | < rhickey> possible support for primitive args/returns |
| 15:29 | gnuvince | < rhickey> an accessible AST for tools, type systems etc |
| 15:30 | gnuvince | That's pretty much what he said. |
| 15:30 | Chousuke | pjstadig: I think if more clojure implementations start popping up then yeah, we'll need some kind of a portability library |
| 15:30 | Chousuke | but what to call it! |
| 15:31 | Chousuke | clojure.portability sounds weird :( |
| 15:31 | SethTisue | gnuvince: thx |
| 15:32 | Chouser_ | I think there are a set of features that don't seem to hard in theory to add to the Clojure compiler, but when you look at the current Java implementation those additions suddenly look much harder |
| 15:32 | Chouser_ | not to mention less fun, as they would require writing Java code. |
| 15:33 | Chouser_ | So between that and ideas that Rich has had relatively recently about what features would be required to get clojure collections written in clojure to perform sufficiently, he may have changed his mind. |
| 15:33 | gnuvince | A large benefit of switching to Clojure-in-Clojure: one less thing Slava can use to criticize Clojure on proggit ;) |
| 15:33 | SethTisue | when I asked the q originally, fun was definitely one of the issues I had in mind. fun for other people contributing, too |
| 15:34 | eevar_ | losing out on the whole java ecosystem sounds like a loss imo |
| 15:34 | gnuvince | SethTisue: that should be a large reason in favor of such a decision; if you can't attract people to hack with you, that's bad for the project. |
| 15:34 | SethTisue | eevar_: in what sense? |
| 15:34 | Chouser_ | oh, we're not talking about replacing the JVM |
| 15:35 | eyeris | When I run this code, "new.xls" is still 0 bytes and java.exe never closes the file. Am I missing some Clojure detail (something about laziness, perhaps) or is this a problem with the library? |
| 15:35 | eyeris | http://pastebin.ca/1386362 |
| 15:35 | Chouser_ | just replacing (most of) the .java code used currently to implement Clojure. |
| 15:35 | eevar_ | okies, that makes more sense |
| 15:35 | gnuvince | The JVM is the whole point (I think) why Clojure took off so spectacularly |
| 15:35 | gnuvince | A nice clean Lisp with the largest library of any Lisp |
| 15:36 | eyeris | gnuvince: I think it is the vector syntax, etc. There have been Scheme implementations with decent java interop for a while, hasn't there? |
| 15:37 | eyeris | Perhaps that's what you mean by "clean" :) |
| 15:37 | Chousuke | scheme doesn't have as nice a macro system though. |
| 15:37 | SethTisue | or the emphasis on immutability and concurrency |
| 15:37 | SethTisue | or the lack of historical baggage |
| 15:38 | Chousuke | (the problem with scheme's macro system is that I can't understand it. Clojure's is much simpler. :P) |
| 15:38 | SethTisue | :-) |
| 15:38 | hiredman | eyeris: without looking, it sounds like you need to .close the file |
| 15:38 | Chouser_ | jauk: it seems to me that your lazyxml example ought to work -- it should parse all of the first <bound>...</bound> element, and not much more than that before returning |
| 15:39 | Chouser_ | but I haven't tested the laziness of lazyxml or zipfilter since the lazier changes to clojure ... perhaps something broke. |
| 15:39 | eyeris | Oh man, now I feel silly. Thanks hiredman! |
| 15:40 | hiredman | :P |
| 15:50 | pjstadig | Chouser_: oh, we're not talking about replacing the JVM |
| 15:50 | pjstadig | gnuvince: < rhickey> much easier porting to other hosts - JS, CLR, AS3, ObjC? etc |
| 15:50 | pjstadig | what does it mean to port to other hosts? |
| 15:50 | clojurenoob | I'm very much a noob, but some aspects of Clojure seem clunky: strange OO (do people use it), appending to sequences creates different ordering of elements depending on type, True/T/False/Nil/'()/0/null is confusing (I prefer Haskell's approach there) |
| 15:51 | pjstadig | if you're depending on a java lib and clojure has been ported to CLR, then your program won't run on CLR |
| 15:51 | Chouser_ | pjstadig: hm, good point. But the JVM would still be the "primary" host, especially where it's available. |
| 15:51 | pjstadig | yeah which mean's it's not necessarily insane to think about writing a pure clojure lib for processing CSV |
| 15:51 | Chouser_ | pjstadig: right, most apps would not be written for "cross-virtual-platform" support |
| 15:51 | pjstadig | or making HTTP requests |
| 15:52 | pjstadig | i'm not saying it's the most sane thing to do either (it depends on the situation) |
| 15:53 | hiredman | clojurenoob: what OO? |
| 15:53 | AWizzArd | clojurenoob: Clojure generally wants to motivate you to *not* do OO |
| 15:53 | hiredman | data structures have different characteristics |
| 15:54 | Chouser_ | OO is a pretty vague term |
| 15:54 | hiredman | vectors can grow at the end O(1), lists grow at the front O(1) |
| 15:54 | SethTisue | clojurenoob: I assume by strange OO you mean using maps for the purposes you'd use structs or classes in other languages? |
| 15:54 | hiredman | conj is just aware of this, and does the right thing for each |
| 15:56 | AWizzArd | And hashmaps can grow "anywhere" in near constant time |
| 15:56 | Chouser_ | does it seem odd that sortedMap.insert(k, v) might do something different from hashMap.insert(k, v)? |
| 15:56 | AWizzArd | ,(conj {:a 10, :b 20} {:c 30}) |
| 15:56 | clojurebot | {:c 30, :a 10, :b 20} |
| 15:56 | clojurenoob | I meant generic methods (or whatever they are called. it's been a while since I've watched the tutorials on bliptv) |
| 15:56 | Chouser_ | multimethods |
| 15:56 | AWizzArd | What is about them? |
| 15:58 | Cark | if you don't like multimethods, don't use these |
| 15:59 | Chouser_ | Here is some rationale about why clojure does multimethods and hierarchies the way it does, and what is desired for the future: http://groups.google.com/group/clojure/msg/0b500f0eba88eda1 |
| 16:01 | Cark | the one time i thought i would use multimethods, i found that i was trying to do OO |
| 16:01 | Cark | so i reconsidered and went for standard high order functions |
| 16:01 | Cark | in the end, this code is now easier to read |
| 16:03 | hiredman | clojurebot: the world <reply>what the world needs is more higher order functions |
| 16:03 | clojurebot | In Ordnung |
| 16:03 | hiredman | clojurebot: what does the world need now? |
| 16:03 | clojurebot | Huh? |
| 16:03 | clojurenoob | AWizzArd: I can't answer in detail, because it's been a while since I've seen the tutorials. But when I saw them, I got the distinct feeling that there was something tasteless about multimethods. That's all I can recall. I was wondering if this feeling was shared by others. |
| 16:04 | hiredman | clojurebot: tell me what the world needs |
| 16:04 | clojurebot | Pardon? |
| 16:04 | hiredman | oh |
| 16:04 | pjstadig | for got 'is' |
| 16:04 | hiredman | clojurebot: the world is <reply>what the world needs is more higher order functions |
| 16:04 | clojurebot | You don't have to tell me twice. |
| 16:04 | hiredman | clojurebot: what does the world need now? |
| 16:04 | clojurebot | what the world needs is more higher order functions |
| 16:05 | pjstadig | clojurebot: what is our mascot? |
| 16:05 | clojurebot | the official mascot of clojure is a futuristic ninja robot |
| 16:05 | Chouser_ | multimethods are used much less often in clojure than methods are in many languages (such as Java, python, ruby, etc.) |
| 16:06 | Chouser_ | when you need a multimethod in clojure, they often fit quite nicely. Sometimes they solve a problem that would require extreme contortions in "standard" OO systems. |
| 16:07 | marklar | Chouser_: What does GF stand for in that post? |
| 16:07 | SethTisue | Gang of Four? |
| 16:08 | pjstadig | that would be GoF |
| 16:08 | pjstadig | GF = generic function |
| 16:08 | SethTisue | ok maybe not :-) |
| 16:08 | marklar | pjstadig: ah thanks |
| 16:09 | djpowell | Is http://code.google.com/p/clojure/downloads/list working? |
| 16:10 | pjstadig | maybe code.google.com is being DDoS'ed because of all the people trying to get information about GAE/Java |
| 16:11 | cconstantine_ | Has anyone gotten into the Java AppEngine trial? |
| 16:11 | pjstadig | i think i did |
| 16:11 | cconstantine_ | I have, and wonder if anyone has played around with clojure in it |
| 16:11 | pjstadig | i haven't tried to play with it yet |
| 16:11 | hiredman | http://www.thelastcitadel.com/_media/clojure.png |
| 16:11 | cconstantine_ | same here |
| 16:11 | pjstadig | there are some blogs about using clojure on GAE |
| 16:12 | hiredman | clojurebot: delicious |
| 16:12 | clojurebot | delicious is http://delicious.com/clojurebot |
| 16:12 | pjstadig | sweet! |
| 16:12 | pjstadig | futuristic ninja robots! |
| 16:15 | pjstadig | yeah i can't pull up the clojure google code page |
| 16:15 | hiredman | I am in the java appengine trial |
| 16:16 | hiredman | but, uh, I just did it without remembering I hate webapps |
| 16:16 | pjstadig | hehe |
| 16:16 | hiredman | so now I don't know what to do |
| 16:16 | djpowell | I just got into the trial too |
| 16:17 | kotarak | Does someone want to play as guinea pig *coughcough* beta tester with an Ivy patch to contrib? |
| 16:21 | djpowell | Eclipse with clojure-dev and google's clojure plugin is probably pretty cool |
| 16:26 | Chouser_ | google has a clojure plugin? |
| 16:28 | dysinger | you meant google gae plugin probably djpowell |
| 16:29 | pjstadig | http://code.google.com/eclipse/ |
| 16:35 | hiredman | http://jonasboner.com/talks/state_youre_doing_it_wrong/html/all.html (from reddit) mentions clojure and rhickey |
| 16:35 | djpowell | oh, er, yeah - I mean't google's eclipse plugin |
| 16:54 | eyeris | Does anyone here know the predicate form to use for "not equal to" in clojureql? |
| 16:54 | eyeris | (not (= x y )) ;fail |
| 16:55 | eyeris | (not= x y) ;fail |
| 16:55 | eyeris | (<> x y) ;success? |
| 16:56 | cmvkk | not= isn't right? |
| 16:56 | pjstadig | ,(= 1 2) |
| 16:56 | clojurebot | false |
| 16:56 | cmvkk | ,(not= 1 2) |
| 16:56 | clojurebot | true |
| 16:56 | kotarak | eyeris: doesn't <> not work? |
| 16:56 | pjstadig | ,(not= 1 2) |
| 16:56 | clojurebot | true |
| 16:56 | kotarak | eyeris: should translate to SQL <> |
| 16:56 | eyeris | kotarak I think <> works, but I get a null pointer exception. I'm still tracking own if that is in my code or cql |
| 16:57 | eyeris | s/own/down |
| 16:57 | kotarak | do you have an example? |
| 16:57 | eyeris | Not a simple one :) brb |
| 17:07 | djpowell | anybody tried the google stuff? i was trying it without compojure. i got a classloader error - maybe I should set *use-context-classloader* ? |
| 17:09 | eyeris | Is there a shortcut in VimClojure/Gorilla that will evaluate the outer-most s-exp of the block the cursor is in? |
| 17:10 | kotarak | eyeris: \et |
| 17:10 | kotarak | EvaluateToplevel |
| 17:11 | eyeris | Thanks. I don't know how I misinterpreted the documentation to think "top-level" meant the buffer |
| 17:11 | kotarak | eyeris: the whole buffer is \ef (EvaluateFile) |
| 17:13 | eyeris | Why, when I place the cursor inside a defn and press \et, it returns nul instead of the new symbol? |
| 17:14 | kotarak | Is the cursor in the opening/closing paren? |
| 17:14 | kotarak | I meant on the paren. |
| 17:14 | eyeris | No. |
| 17:14 | kotarak | Hmm... Which version are you using? |
| 17:14 | eyeris | Though I get the same behaviour if it is. |
| 17:15 | eyeris | Where is the version number? I don't see it in clojure.vim |
| 17:16 | kotarak | eyeris: there probably is none. Did you download it or use the hg repo? |
| 17:16 | eyeris | It's definitely not 2.0. I didn't realize that was released. |
| 17:16 | eyeris | I will upgrade to 2.0 |
| 17:16 | kotarak | Uh. Pre 2.0? Still the Ruby version? |
| 17:17 | kotarak | Please upgrade! Much better. I plan to release a new update around easter. |
| 17:17 | eyeris | Where do I put ng.exe? |
| 17:17 | kotarak | somewhere in your path. |
| 17:17 | kotarak | Or set the vimclojure#NailgunClient variable to the place where you put it. |
| 17:18 | eyeris | What about ngserver? |
| 17:18 | kotarak | Somewhere in your PATH. |
| 17:18 | eyeris | Ok |
| 17:19 | eyeris | You should really make it more difficult, so I don't look like such a dope asking :) |
| 17:19 | kotarak | hehe. There is a screencast on http://kotka.blip.tv showing the main points. |
| 17:20 | kotarak | Uh. |
| 17:20 | kotarak | The cast refers to the next release. Sorry for the confusion. |
| 17:21 | eyeris | Should I still be using Gorilla? |
| 17:22 | kotarak | No. |
| 17:22 | kotarak | It is merged into VimClojure |
| 17:22 | kotarak | You should remove the old gorilla files from your .vim directory |
| 17:22 | dakrone_hb | I have "(ns app.hello (:gen-class))" and " (defn -main [& args] (println "application works"))" in a clj file and I'm still getting "java.lang.RuntimeException: java.lang.ClassNotFoundException: app.hello$_main__10 (NO_SOURCE_FILE:0)" when I do a (compile 'app.hello), am I doing something wrong? |
| 17:23 | kotarak | dakrone_hb: is the src and the classes directory in the Classpath? |
| 17:25 | dakrone_hb | yea, the source in in "app/hello.clj" and my classpath has "." in it |
| 17:25 | kotarak | dakrone_hb: and the classes directory? |
| 17:26 | dakrone_hb | kotarak, it's not, the classes directory needs to be in the classpath also? |
| 17:26 | eyeris | Hrm. I removed Gorilla and now \ef just beeps |
| 17:27 | dakrone_hb | kotarak, that fixed it, thanks! |
| 17:27 | kotarak | dakrone_hb: yes, and it must exist. |
| 17:27 | dakrone_hb | yep, it works now |
| 17:28 | kotarak | eyeris: you have to put "let clj_want_gorilla = 1" into your .vimrc. And don't forget to start the ng-server before opening a clojure file. |
| 17:31 | eyeris | I have to compile NG myself? |
| 17:32 | eyeris | That's annoying. I have no Java development tools (like Ant) installed on my Windows machine. |
| 17:32 | kotarak | put the line "nailgun-client=ng" into your local.properties. Then it should be automatically compiled. On Windows just use the ng.exe delivered with the distribution. |
| 17:33 | eyeris | ng.exe is the client and the server? |
| 17:33 | kotarak | It's the client. |
| 17:33 | kotarak | The server must be started manually on Windows. (Some .bat guru around?) |
| 17:33 | kotarak | java -cp <your-class-path> com.martiansoftware.nailgun.NGServer |
| 17:34 | eyeris | I can use the shell script provided via cygwin. |
| 17:34 | kotarak | java -cp <your-class-path> com.martiansoftware.nailgun.NGServer 127.0.0.1 is actually better |
| 17:34 | kotarak | eyeris: the script blows up on cygwin. |
| 17:34 | kotarak | At least I had problems. |
| 17:34 | eyeris | I can write my own bat file then. |
| 17:34 | eyeris | I just don't have Ant, so I can't compile the ngserver class files. |
| 17:34 | eyeris | Without a tedious manual compile |
| 17:35 | kotarak | Pfew. Ant would help... You can look into the build.xml on how to compile the server files. |
| 17:36 | AWizzArd | kotarak: maybe you can include a shell script which will call a little clojure program which does the compile stuff and which builds a j |
| 17:36 | AWizzArd | +ar |
| 17:36 | AWizzArd | Then no dependencies are needed, such as ant, maven or even ivy |
| 17:38 | kotarak | AWizzArd: Wait a second for my post on the google group. Then you can test yourself. |
| 17:44 | dmiles_afk | is there a good reason to use ClojureCLR over Clojure on IKVM? |
| 17:46 | dmiles_afk | well i havent trie dlately on IKVM .. but it seems like it might work |
| 17:47 | eyeris | Does nil? match Java Nulls? |
| 17:47 | djpowell | yeah - nil is java null |
| 17:48 | duncanm | can I do internal DEFINEs in Clojure like I can Scheme? |
| 17:48 | hiredman | use let |
| 17:53 | duncanm | anyone using SLIME with Clojure here? |
| 17:54 | AWizzArd | sure |
| 17:54 | dakrone_hb | is there any good way to do profiling on a Clojure program for performance issues? |
| 17:54 | AWizzArd | also works very well in a remote setup, via slime-connect |
| 17:54 | duncanm | AWizzArd: how do you do the remote setup? |
| 17:54 | AWizzArd | dakrone_hb: just use your favourite Java profiler. For example the one in NetBeans. |
| 17:54 | duncanm | AWizzArd: i'm running Clojure-in-a-box right now |
| 17:55 | AWizzArd | duncanm: On the remote machine I have swank in my classpath. Then I log in there via ssh and run Clojure. Then I can (use 'swank.swank) and do something like (start-server "/dev/null" :port 4005) |
| 17:55 | djpowell | if you have a new-ish version of Java 6, there is a profiler built in called jvisualvm |
| 17:55 | djpowell | I've found it to work quite well with clojure |
| 17:56 | AWizzArd | On my local machine I can oppen a ssh tunnel forwarding port 4005 and then M-x slime-connect <Enter> <Enter>, <Happy hacking>. |
| 17:58 | AWizzArd | djpowell: yes, good idea. This jvisualvm works very well. |
| 17:59 | djpowell | it doesn't seem as heavyweight as most profilers i've used |
| 17:59 | djpowell | usually if i have a performance problem, connecting a profiler slows things down so much i usually give up waiting for it |
| 18:01 | dakrone_hb | heh, takes Clojure 478 to do the same thing perl does in 54 seconds. Something must be terribly wrong with my code. |
| 19:52 | dnolen | I don't suppose there is an index-of anywhere in contrib is there? |
| 20:08 | cgrand | dnolen: .indexOf works on lists and vectors |
| 20:09 | dnolen | my java ignorance strikes again, thx cgrand. |
| 20:13 | gnuvince_ | beware of nil though |
| 20:13 | gnuvince_ | ,(.indexOf nil "foo") |
| 20:13 | clojurebot | java.lang.NullPointerException |
| 20:14 | cgrand | true |
| 20:14 | Cark | ,(.indexOf :a ()) |
| 20:14 | clojurebot | java.lang.IllegalArgumentException: No matching method found: indexOf for class clojure.lang.Keyword |
| 20:15 | Cark | ,(.indexOf () :a) |
| 20:15 | clojurebot | -1 |
| 20:34 | dmiles_afk | hrrm CojureCLR.. was IKVM not possible? |
| 20:34 | dmiles_afk | well .. IKVM would probably work .. but the ClojureCLR to do a better job leveraging .NET? |
| 20:37 | Chousuke | dmiles_afk: I think the best way to determine that is to give it a try. |
| 20:43 | dmiles_afk | i am about to.. actually if i have a question it'd be how close http://dotlisp.sourceforge.net/dotlisp.htm this is to clojure |
| 20:43 | scottj_ | How do I get just the 10 from (re-find #"<foo>.+</foo>" "<foo>10</foo>") |
| 20:44 | Chouser | ,(second (re-find #"<foo>(.+)</foo>" "<foo>10</foo>")) |
| 20:44 | clojurebot | "10" |
| 20:44 | dmiles_afk | invoking static vs instance methods are under different syntax rules.. but about other things |
| 20:44 | SethTisue | "I'm not a Lisp expert." |
| 20:45 | SethTisue | - Rich Hickey |
| 20:45 | SethTisue | :-) |
| 20:45 | Chouser | SethTisue: that's an old quote, I would imagine. |
| 20:45 | scottj_ | Chouser: thanks |
| 20:45 | SethTisue | 2003 |
| 20:45 | dmiles_afk | invoking static vs instance methods are under different syntax rules = clojure use to be like this document .. but now differnt? |
| 20:47 | Chouser | dmiles_afk: I've never looked at dotlisp -- interesting similarities |
| 20:47 | SethTisue | it's interesting to learn that something like this was cooking that far back |
| 20:47 | dmiles_afk | i assumed it was the prototype |
| 20:48 | Chouser | dmiles_afk: the relevent clojure docs are here: http://clojure.org/java_interop |
| 20:49 | Chouser | also interesting how long clojure did *not* have (.foo bar) syntax, and that it still doesn't allow x.y for member access |
| 20:50 | dmiles_afk | allot of why we are using DotLisp is even though w have a full Common Lisp on .NET .. we still too in love with the syntax simplicitty |
| 20:51 | Chouser | clearly some ideas came over, but Clojure's equality symantics, immutability, and concurrency support are fundamental and don't appear to have been in dotlisp |
| 20:51 | dmiles_afk | but since we havent written much lines of code yet.. it's early enough to switch to clojure |
| 20:51 | dreish | DotLisp doesn't have any of the persistent data structures or STM. |
| 20:52 | dmiles_afk | i mean wewritten 100s line s of code.. but not .dotlisp code ;P |
| 20:52 | Chouser | dotlisp has an early form of clojure seqs |
| 20:52 | Chouser | hm, lazy seqs even -- maybe not so early |
| 20:53 | dmiles_afk | yeah all the lazy eval.. and them being default .. is what is so neat |
| 20:53 | dreish | Doesn't look like it has the clever ` either. |
| 20:54 | dmiles_afk | is cljure using , instead of ~ ? |
| 20:54 | dreish | No, still ~ |
| 20:54 | Chouser | clojure on the jvm is a good deal more mature now than dotlisp was on clr. Not sure that any clojure on clr is up to snuff yet though. |
| 20:54 | dreish | , is whitespace |
| 20:54 | clojurebot | java.lang.Exception: Unable to resolve symbol: is in this context |
| 20:54 | dreish | It's also clojurebot's sigil. ;) |
| 20:54 | Chouser | dreish is talking about the namespace-based hygine, I think. |
| 20:54 | dreish | Yes. |
| 20:57 | dmiles_afk | i run ABCL on .NET as a IKVM dll.. it makes the java interop become CLR interope very transparently.. maybe clojure might end up the same way oon IKVM |
| 20:57 | dmiles_afk | oon/on |
| 20:57 | dmiles_afk | so int = System.Int32 |
| 20:57 | dmiles_afk | etc |
| 21:06 | dmiles_afk | ikvmc /development/clojure-read-only/clojure.jar built clojure.exe most excelently and it works! |
| 21:09 | dmiles_afk | user=> (.. System (getProperties) (get "java.vm.name")) ==> "IKVM.NET" |
| 21:22 | dmiles_afk | is 'set' == 'set!' ? |
| 21:23 | hiredman | no |
| 21:23 | hiredman | ,(set (range 3) |
| 21:23 | clojurebot | EOF while reading |
| 21:23 | hiredman | ,(set (range 3)) |
| 21:23 | clojurebot | #{0 1 2} |
| 21:24 | dmiles_afk | ok set is a creator of a set ;P |
| 21:48 | chessguy | ok, any enclojure users in the house? i'm working through http://enclojure.net/GettingStarted.html and got all the way to the end, but i don't have an option for "Clojure REPL Manager" to open the REPL |
| 21:59 | marklar | chessguy: I don't really use it, but I've installed it and it added just a "Clojure REPL" option under Window |
| 22:02 | Raynes | chessguy: Make sure you have the newest version of Enclojure. You can open an REPL by going to Window and clicking Create Standalone REPL and then entering the paths you want on your classpath including the path to clojure.jar and then clicking connect. |
| 22:02 | Raynes | You can also create a project specific REPL by right clicking on your project and clicking Create Project REPL |
| 22:02 | Raynes | Er, "Start Project REPL" actually. :) |
| 22:07 | chessguy | thanks guys, i'll play around with it more tomorrow |