#clojure log - Jun 05 2009

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

3:57 alinp: hi

3:57 is it possible in clojure to do something like that: (def x (eval "(+ 1 2)"))

3:57 ?

3:58 I'm sure this is not the function that needs to be used

3:58 but is there a function to be used for this purpose ?

3:58 opqdonut: you're not fine with (def x (eval '(+ 1 2))) ?

3:58 you could always invoke the reader

3:58 i dunno if it's exposed

3:59 ah, read

4:00 slashus2: ,(eval (read-string "(+ 1 2)"))

4:00 clojurebot: DENIED

4:00 slashus2: That is how you would do it alinp

4:00 opqdonut: ,(read-string "(+ 1 2)")

4:00 clojurebot: (+ 1 2)

4:00 opqdonut: yeah

4:01 alinp: read-string, thanks slashus2 & opqdonut

4:37 jdz: did anydoby mention that eval is evil?

4:38 opqdonut: of course it isn't :)

4:39 slashus2: It would be bad if it was.

4:39 jdz: how so?

4:39 eval is the most evil function

4:39 i'm yet to come across a case when i need it...

4:40 opqdonut: not all metaprogramming can be done just with macros

4:42 jdz: i'd like to see an example

4:44 slashus2: A really bad example would be if you wanted to use a macro in a function, and you want to expand the & more arguments. (eval `(amacro ~@more)) I don't know..

4:44 opqdonut: well i have a macro that interprets a series of sexps into a complex data structure describing a computation

4:45 a "dsl" if you will

4:45 but i still want to invoke lisp deep within this sub-language

4:45 so the macro evals some parts

4:47 slashus2: jdz: I think hiredman used it in clojurebot to evaluate form in cond-eval

4:48 jdz: slashus2: if you want to evaluate Clojure code, eval is what you use...

4:49 opqdonut: i'm still not convinced.

4:49 slashus2: yep

5:55 yason: Hmmm, what's the idiomatic way to turn a sequence into a new sequence that contain N-sized chunks of the original sequence?

6:00 lenst: (doc partition)

6:00 clojurebot: "([n coll] [n step coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap."

6:10 opqdonut: gah, just realised why the eval command is , in clojurebot

6:11 yason: ah

6:11 I've seen it before

6:11 thanks

9:06 bstephenson: can anyone online answer a weird clojure.contrib.sql problem we are seeing? Otherwise, I will post the question to the newsgroup.

9:15 eevar2: hard to tell if you don't ask your question..

9:32 bstephenson: sorry, was hoping the SQL author was online....here is our problem:

9:33 we try to use the insert-values function to insert a record into a PostgreSQL database

9:33 turns out eh record was violating a foreign key constraint by referencing an account that was not in the accounts table

9:33 we got this error back from REPL:

9:33 <CompilerException java.lang.IllegalArgumentException: No matching

9:33 method found: println for class java.io.OutputStreamWriter

9:33 (NO_SOURCE_FILE:0)>

9:34 insterad of a JDBC error indicating that FK was violated (which we usually do)

9:34 both ID fields are UUID fields

9:34 once we put in the account intot he accounts table, the record we were trying to write went into the db without a hitch

9:34 wondering why we did not see a JDBC error when the problem was an FK violation?

9:39 ahh, sorry channel, we found the problem. Related to our editor, not clojure.contrib.sql

10:23 ezyang: Hey all; what's the difference between using (if (seq l)) and just directly checking if it's null?

10:25 Chouser: ezyang: an empty collection is logical true

10:25 ,(let [c []] (if (seq c) "something" "nothing"))

10:25 clojurebot: "nothing"

10:25 Chouser: ,(let [c []] (if c "something" "nothing"))

10:25 clojurebot: "something"

10:25 ezyang: Oh. That's different from Scheme

10:25 I thought an empty list was nil

10:25 Chouser: no

10:26 ozzilee: ,(seq [])

10:26 clojurebot: nil

10:26 Chouser: ,(let [c (list)] (if (seq c) "something" "nothing"))

10:26 jdz: ezyang: in scheme empty list is logical true, no?

10:26 clojurebot: "nothing"

10:26 Chouser: ,(let [c (list)] (if c "something" "nothing"))

10:26 clojurebot: "something"

10:26 ezyang: jdz: well, you do something like (null? list)

10:27 jdz: ezyang: same here, you do (seq lst)

10:27 ezyang: OK.

10:28 Chouser: in fact the idiomatic way to test for a non-empty collection is to use (seq x) in a boolean context.

10:28 instead of (if (not (empty? coll)) ...), you say (if (seq coll) ...)

10:28 ezyang: Why is that the case?

10:29 jdz: because saying "something" sounds better than "not nothing"?

10:30 easier on the brain at least

10:30 ezyang: jdz: Oh, ok.

10:30 I would normally use null? and then define the base case, and then do the regular stuff in the else

10:32 Totally unrelated question: is there any way to dynamically update the REPL code

10:32 without quitting the repl, recompiling, and then running again

10:32 s/update the REPL code/update the code while you're in the repl/

10:32 jdz: def?

10:33 well, how did you get the code in the repl in the first place?

10:33 ezyang: jdz: I changed my namespace

10:33 And then the classpath found it

10:33 The idea is I open the repl to debug some clj files, and then I edit those files

10:34 jdz: i have not tried, but maybe remove-ns + require will do

10:34 ezyang: I guess I'm being kind of unreasonable here

10:34 ozzilee: ezyang: (require 'my-ns :reload-all)

10:34 jdz: well, most people use some kind of a developement environment, like emacs + slime or netbeans or something

10:35 ezyang: I spent last afternoon trying to get VimClojure to work

10:35 I think that I'm stuck on some special mvn behavior

10:36 jdz: serves you well for wanting to use vi[m] for lisp developmement *evil grin*

10:37 ezyang: I think it's kind of unreasonable to learn a new text editor (emacs) just to develop in it.

10:37 s/in it/in clojure/

10:37 jdz: well it's reasonable for a lisp developer to want to redefine stuff on the fly without reloading the world

10:37 like redefining functions, for instance

10:37 gnuvince: There's NetBeans, Eclipse, IntelliJ that are coming up with plugins for Clojure if you prefer.

10:38 Emacs is just so tightly knit with Lisp and its community that it's no wonder that the majority of Lispers prefer it.

10:38 Chouser: ezyang: I agree

10:41 ezyang: gnuvince: I totally understand why emacs is +1 for lisp development

10:42 And it's also a text editor that is worth learning

10:42 Chouser: is it? is it really?

10:42 * Chouser sighs

10:42 ezyang: I think you should be proficient in both vim and emacs :-)

10:43 gnuvince: ezyang: thankfully, I am :)

10:43 I use vim at work for Django work, and Emacs at home for Clojure and Haskell

10:43 And I'm pretty happy about my situation

10:46 piyo: ezyang: have you tried technomancy's clojure+emacs guide? http://technomancy.us/126

10:46 ezyang: Not yet

10:46 piyo: It cleared up a number of problems for me

11:18 cemerick: we use netbeans + enclojure to very good effect, FWIW

11:19 the debugger isn't there yet, but I'll bet it's not there for slime, either

11:19 Chouser: the size of all these tools scares me. :-/

11:20 cemerick: If you can understand the whole thing top to bottom, chances are it doesn't do much for you. ;-)

11:20 Chouser: wow

11:20 cemerick: yeah, I always get that kind of reaction when talking to other programmers

11:21 abstractions are good, they give you leverage.

11:21 Chouser: But I don't need to understand how it all works, I just need to understand how to use it. That's sufficiently scary for emacs, netbeans, eclipse...

11:22 cemerick: huh. I've always found NB very friendly. Somewhat more so than eclipse, and quite clearly more approachable than emacs.

11:22 aravind: Chouser: so.. what do you use for development?

11:22 Chouser: I'm always afraid to say. People (Rich included) mock me.

11:22 hiredman: notepad++

11:22 Chouser: text editor. repl.

11:23 ion3.

11:23 hiredman: Chouser: have you seen slime.vim?

11:23 aravind: I see, but don't you like the convenience of having a few key strokes compile/eval what you are working on?

11:23 hiredman: http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/

11:24 Chouser: vim with syntax coloring and indentation support. repl with rlwrap and vi-like bindings for tab completion and history.

11:24 hiredman: it lets you send code to a repl running in screen

11:24 Chouser: aravind: well, I have that. maybe more keystrokes than with slime, but not too bad.

11:25 a couple keystrokes to select a portion of the code, an ion3 keystroke to focus on the repl, a keystroke to paste and execute.

11:25 ezyang: Gave up with vimclojure, am setting up emacs

11:25 aravind: Chouser: ion3 is supposed to be an awesome wm.. I used to use stumpwm for a while, but I finally gave up on tiling wms, switched to openbox (but was able to retain most of my keybindings).

11:25 Chouser: hiredman: I don't think I've tried that particular one. I did use whatever was before gorilla some, but it never really hooked me.

11:26 hiredman: Chouser: it is different from gorilla

11:26 Chouser: And I don't particularly *like* vim (vimscript in particular), but it's what I know, and the keybindings are undeniably powerful.

11:26 piyo: ezyang: what is your os

11:27 aravind: Chouser: how about auto navigating to your function definitions if you want to look some stuff up? You would have to hack it up with etags or something like that for equivalent functionality.

11:27 Chouser: I suppose I should try emacs, but the thought of having to learn elisp in order to customize it makes me gag a little.

11:27 hiredman: you start a repl inside a screen session and then you tell slime.vim the name of the screen session and the name of the window the repl is in, and it just sort of pastes the vode into the repl

11:27 very loosely coupled

11:27 stuartsierra: Chouser: it's not that bad, 99% of the customization you'll ever want is in the *customize* GUI.

11:28 Chouser: hiredman: yeah, that sounds like pre-gorilla (sorry, can't remember the name). He had some vim/ruby code that sent forms to a screen session.

11:28 ezyang: piyo: Jaunty

11:28 Chouser: ...and I really must have vim bindings. the last couple times I tried switching to emacs I tried to do things the Emacs Way. I'm done with that.

11:29 aravind: Chouser: well.. it takes time.

11:29 Chouser: I know Chousuke uses vi bindings in emacs, but my recent attempts at that were unsatisfactory.

11:29 aravind: but then, if you are productive with your env, thats all that really matters.

11:30 Chouser: aravind: oh, I know. My last attempt at emacs went far enough that I was pretty comfortable with emacs bindings for navigating a file. Took time, but was somewhat rewarding.

11:31 ...but then I needed features that were not built in, and spent some time trying to port a plugin from xemacs to emacs (or the other way around, I forget) ... largely failed, and then discovered the feature I needed was built in to vim.

11:31 piyo: ezyang: sudo aptitude install ant open-jdk-devel ... # etc...

11:31 ezyang: ?

11:31 aravind: I was a huge vim proponent, but its a nightmare trying to customize or hack the configs for anything other than the basic tabwidth, or syntax settings in it. So, I have been using emacs for some time now.

11:32 Chouser: now I'm just whining. I want emacs flexibility + vim keybindings + clojure core (for multithreading, customiaztion, etc.)

11:32 when can I have that? :-)

11:33 ezyang: Oh, I already can run Clojure

11:33 (re piyo)

11:33 I was trying to "improve my productivity" with a non-crappy repl environment

11:33 aravind: Chouser: have you give emacs viper mode a chance, it may be just enough vi for you.

11:33 Chouser: I have. I should try again.

11:34 I'm frequently startled by missing features, but I should try to get over it.

11:35 aravind: thats how I switched..

11:35 Chouser: you don't use it anymore

11:35 ?

11:36 aravind: vim, nope.. not unless I am in a remote system, when I need to use it for quick things. (I am a sysadmin).

11:36 Chouser: I mean, you don't use viper mode anymore?

11:37 aravind: oh viper mode.. nope, I used it to get started.. used it for a few months, then I tweaked the viper levels down to make it more and more emacsy, and finally turned it off for good.

11:37 Chouser: I just can't imagine living without command mode.

11:38 aravind: I did stick to pure viper (full vi) mode for a few months though.

11:39 command mode annoys me now, when I go to remote systems and start typing ALT-n and ALT-b in vim :)

11:39 Chouser: Holding down the ALT key seems like an inconvenient sort of command-mode.

11:39 :-)

11:41 aravind: hehe, yeah.. like I said, it takes time :)

11:42 Chouser: see, and that would be fine if I were deeply convinced of the Rightness of emacs. But the language, the lack of concurrency, etc. weaken that conviction.

11:42 aravind: I still do like vi mode for other things though. my mutt is all vi mode and so is lynx (though I don't use that much these days).

11:43 Chouser: for me, it was more of a convenience thing and the fact that its immensely customizable should I need to.

11:43 Chousuke: I finally got visual block mode working properly with emacs/vimpulse.

11:44 turns out I had to disable CUA mode because it was screwing up the rendering for some reason

11:44 Chouser: Chousuke: really? works great here! in vim. :-) :-)

11:44 Chousuke: I still think emacs is fundamentally superior to vim

11:44 the interface is just not as good :)

11:44 Chouser: heh

11:45 Chousuke: elisp lacking concurrency support is a big wart though, but at least it's not vimscript :P

11:46 I wonder how they're going to go about adding threading to emacs.

11:46 aravind: although I will admit, gnus has defeated me, multiple times. I have tried and failed to adopt it as my mail client. Every time I give it a shot, I go running back to mutt :)

11:47 Chouser: I've never been a heavy email user, but I got gnus working nicely last time I tried.

11:47 * Chouser touts what little he can...

11:47 piyo: ezyang: it's just that, when the installation asks you to "M-x clojure-install", it git-clones then does the ant build thing

11:48 ezyang: Oh yeah. No, the project I'm working on has its separate build environment, with hand-rolled jars and eveyrthing

11:48 aravind: Chouser: thats odd! you got gnus to play nice, but you have a hard time with emacs..

11:49 cemerick: does anyone have recommendations for swing app frameworks, aside from the NB RCP?

11:50 Chouser: aravind: I really tried hard last time, getting emacs going. I wasn't even a lisper then...

11:51 aravind: Chouser: it took me a few attempts.

11:53 Chouser: if you want to switch (I am not saying you should), I'd start small. Don't try to get your entire env converted and working the way you think it should.

11:53 Chouser: I'd start with full blown viper mode.. etc..

11:55 * aravind notes that his sysadmin friends make fun of him for using emacs :-)

11:55 Chouser: :-)

11:55 Chousuke: viper doesn't have visual mode though.

11:56 aravind: I have used them both enough, that I don't really mind the taunting.

11:56 I take the zen approach and go "whatever works for you" :)

11:56 piyo: aravind: I like editting with root privs from emacs , /sudo::/etc/hosts , etc

11:56 Chousuke: I still use vim for some stuff

11:57 but for clojure editing I need emacs.

11:57 aravind: piyo: hehe

11:58 piyo: except emacs first needs to be installed into the os, while vi is sitting there

11:58 aravind: piyo: oh wait a minute.. you are serious?

11:59 piyo: aravind: M-x butterfly, baby

11:59 Chousuke: quite often emacs is too; but vi is pretty universal.

11:59 aravind: phew!

11:59 hiredman: piyo: well, the vi freebsd comes with is really vi, not vim

11:59 piyo: so I'm like sudo vi /etc/portage/package.mask # add cutting edge emacs

12:00 hiredman: which, uh, I'd rather not use for coding

12:00 piyo: aravind: you do use emacs TRAMP

12:00 aravind: ?

12:00 aravind: piyo: I do, if I have to do extended editing, and I can't replicate the env locally.

12:01 piyo: I was being serious with /sudo::/etc/hosts

12:01 aravind: no way!

12:01 you can't be!

12:01 piyo: I mean, it works

12:02 ezyang: Huh. Even with emacs+slime, it doesn't dynamically automatically update things. feh

12:02 piyo: I do set sudo so that I don't enter my password

12:02 aravind: piyo: sure does, but its like writing full blown swing application to cat/view a 10 line text file.

12:03 piyo: sometimes you want to M-x rectangle-yank inside a config file

12:03 :)

12:03 oh wait, you said 10 lines

12:04 I guess you could bang on "." for a while

12:04 aravind: piyo: vim + ex commands usually work fine for that kind of stuff for me.

12:04 piyo: aravind: as for me

12:05 hiredman: I only seem to use vi features, not vim

12:05 * aravind isn't sure what we are talking about anymore..

12:06 piyo: </offtopic> ?

12:06 aravind: I am out, have to get ready and head in to earn that paycheck.

12:15 piyo: let's talk about clojure

12:15 hiredman: ~clojure

12:15 clojurebot: clojure is like life: you make trade-offs

12:16 hiredman: ~clojure

12:16 clojurebot: clojure > scheme

12:16 gnuvince: ,(compare "clojure" "scheme")

12:16 clojurebot: -16

12:17 gnuvince: ;-)

12:17 Chouser: ,(expression-info '(Integer. "5"))

12:17 clojurebot: {:class java.lang.Integer, :primitive? false}

12:17 Chouser: ,(expression-info '(int (Integer. "5")))

12:17 clojurebot: {:class int, :primitive? true}

12:17 gnuvince: That's pretty neat

12:18 Chouser: I wish there were a way to use it on expression deep inside a nested context.

12:23 * technomancy noticed the guy running the github clojure mirror has the same name as the illustrator of the League of Extraordinary Gentlemen.

12:24 piyo: hey technomancy thanks for that emacs + clojure blog post, it was useful

12:24 technomancy: piyo: great, glad it was helpful

12:24 piyo: :)

12:42 ezyang: Hmm, I still can't get repl reloading to work

12:45 What was the command to reload the namespace again?

12:45 ozzilee: (require 'my-ns :reload-all) ?

12:46 ezyang: Yeah, doesn't seem to do anything

12:47 http://pastebin.com/mefa4d10

12:47 stuartsierra: It won't delete old definitions.

12:47 ezyang: Oh.

12:47 Ok, how should I do that?

12:47 stuartsierra: Try (remove-ns 'my-ns) first.

12:48 ezyang: Now I get Var plyzrdata.parser/parse-hoststat-line is unbound.

12:50 (an IllegalStateException)

12:50 stuartsierra: Maybe your definitions are out of order?

12:51 ezyang: What do you mean by that?

12:51 ozzilee: ezyang: You have to define functions before you use them, unfortunately

12:51 ezyang: Oh, I know why

12:52 Removing the namespace doesn't remove the function

12:52 ozzilee: It loads fine the first time

12:52 ozzilee: ezyang: Ah, ok.

12:52 ezyang: So how would I remove all of the functions from a namespace...

12:53 hiredman: ns-unmap

12:54 ,(ns-map *ns*)

12:54 clojurebot: {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, pprint-map #'clojure.contrib.pprint/pprint-map, keyword? #'clojure.core/keyword?, val #'clojure.core/val, ProcessBuilder java.lang.ProcessBuilder, Enum java.lang.Enum, SuppressWarnings java.lang.SuppressWarnings, *compile-path* #'clojure.core/*compile-path*, max-key #'clojure.core/max-key, list* #'clojure.core/

12:55 ezyang: Hm, so I would need to map ns-unmap on map

12:56 ,(map (partial ns-unmap `plyzrdata.parser) (ns-map `plyzrdata.parser))

12:56 clojurebot: java.lang.Exception: No namespace: plyzrdata.parser found

12:56 ezyang: Erm, I get the error rclojure.lang.PersistentHashMap$LeafNode cannot be cast to clojure.lang.Symbol

12:56 replaca: hiredman: autodoc json now has :namespace element for each entry in :vars

12:56 hiredman: that's what you were after, right?

12:56 ezyang: Given how difficult this seems to be, I'm probably going about this the wrong way

12:59 hiredman: replaca: yesssir

12:59 ezyang: Can I make clojure start the repl in a specific namespace?

12:59 replaca: hiredman: cool

12:59 hiredman: did you modify clojurebot to ignore autodoc updates?

13:00 hiredman: replaca: yes

13:01 replaca: hiredman: good idea, but I was getting used to the echo :-)

13:02 hiredman: displeasure was expressed in my direction

13:02 replaca: hiredman: yeah, makes sense. no real information there.

13:03 hiredman: (doc xml1->)

13:03 clojurebot: "clojure.contrib.zip-filter.xml/xml1->;[[loc & preds]]; Returns the first item from loc based on the query predicates given. See xml->"

13:04 replaca: nice

13:05 hiredman: so couchdb has no security features built in?

13:07 mrsolo: ah missing :gen-class i am such a dimwit

13:17 technomancy: hiredman: since it's all run over HTTP it's pretty easy to secure at the proxy level

13:17 no need to build it into the DB

13:53 mrsolo: are there some online resource that help you to learn about writing macros?

13:53 dnolen: check the Clojure wiki

13:53 also Practical Common Lisp and On Lisp are good general resources about macro writing and they are available for free

13:53 Chouser_1: mrsolo: I learned by reading On Lisp, which is free online

13:54 mrsolo: ok

13:55 going through core.clj... ` seems to be in random places and i don't see the significants :-)

13:55 Chouser: On Lisp uses mostly Common Lisp and some Scheme, but the bulk of it is meaningful for Clojure, with a few syntactic adjustments

13:55 heh, it's not random, I assure you. :-)

13:55 mrsolo: of course

14:00 ezyang: What are the performance properties of partial application in clojure?

14:01 Does Clojure magically evaluate things it can evaluate when I do a partial application?

14:01 hiredman: partial just returns a new function

14:01 uh

14:01 it is function application, not magic

14:01 ~def partial

14:02 ezyang: Ok :-(

14:02 hiredman: no magic whatsoever, not even a macro

14:02 why the :-( ?

14:02 ezyang: (unrelated) I am currently editing files in Vim, popping over to emacs and using that to run them

14:02 It's great. :-P

14:03 dnolen: ezyang: the cost is an additional function call, but those are cheap.

14:03 er

14:03 no

14:03 rather the speed of apply

14:07 ezyang: So, the question here is there's a pre-computation to one of the parameters that should be done, and I was wondering if I could do it inside the function

14:07 but that's not hte case

14:08 hiredman: ...

14:08 Chousuke: mrsolo: if the appearance of ` seems random to you, remember that it's just one way to write a list data structure that won't get evaluated.

14:08 ezyang: Btw, (load-file) is the magic I was looking for earlier on the channel

14:08 gnuvince: I got a general CS question for you guys: considering that getting the length and splitting a linked list are O(n) operations, is mergesort really a good candidate for sorting them?

14:09 Chousuke: mrsolo: macros must return clojure code, and clojure code is predominantly made of lists. thus, ` is very useful when making macros.

14:09 mrsolo: ah

14:09 Chousuke: mrsolo: you could write every macro without it too, though.

14:09 but that's a lot more complicated.

14:11 actually ` is not limited to quoting lists either, but that's where you see it most often.

14:11 ,(let [a 1] `[1 2 a ~a])

14:11 clojurebot: [1 2 sandbox/a 1]

14:11 mrsolo: chousuke: i got this to work and i want to know why ..it tooks lot of trials and errors http://paste.lisp.org/display/81422 :-)

14:12 so ya reading some information on why and how of macros will be very helpful

14:12 Chousuke: mrsolo: did you try calling (macroexpand '(rp (+ 1 2))

14:13 actually, that macro is a bit weird.

14:13 mrsolo: hmm i didn't.. but that gave (rp (+ 1 2)) back

14:13 Chouser: mrsolo: that macro is not what you want.

14:14 Chousuke: right

14:14 it doesn't return clojure code.

14:14 Chouser: the use of 'eval' is your first hint that something's wrong.

14:14 mrsolo: ok

14:14 Chouser: mrsolo: if you want less than a whole book, we can give you a few tips.

14:15 mrsolo: yet it works somehow

14:15 Chousuke: mrsolo: your macro runs the println and time at *compile time*

14:15 mrsolo: it doesn't actually expand to any code :)

14:15 unless (eval a) expands to code

14:15 mrsolo: (rp (map list-single-files '("/tmp", "/tmp")))

14:15 gives back desired result.. though

14:15 Chouser: for example, first write out an example of calling your macro. Then write out the code you'd like your macro to produce for that example.

14:15 Chousuke: yikes. good point.

14:15 Chousuke: mrsolo: but it doesn't happen at runtime

14:16 mrsolo: it happens at compile time.

14:16 mrsolo: ok

14:16 Chouser: so you've got an example of calling your macro there. that's a great start.

14:16 Chousuke: mrsolo: ask yourself: if rp were a function, what does it return?

14:16 Chouser: now, what code would you like your macro to produce in that case?

14:16 mrsolo: ok

14:17 Chouser: Maybe: (time (println "(map list-...)" (map list-...))) right?

14:18 mrsolo: right

14:18 Chouser: so, your macro should be a function that accepts the list '(map list-...) and returns the list '(time (println ...))

14:19 you can write regular code without ` or ~ do to that.

14:19 if you want

14:19 Chousuke: actually.

14:19 mrsolo: well it was a function origional.. but i was tire dof quoting

14:19 all it does it print the sexp and time to run it

14:20 Chousuke: it might be good practice to actually write a function that does that.

14:20 mrsolo: oh?

14:20 Chouser: it would look something like (defmacro rp [a] (list `time (list `println (str a) a)))

14:20 mrsolo: (rp '(+ 2 3)) gets kinda tedous.. i though macro will let me do (rp (+ 2 3)) instead

14:20 Chouser: do you see why?

14:21 mrsolo: i see

14:21 ezyang: Hey all; what data-structure should I use if I will have a mapping like 0 => :tag1, 1 => :tag2, 2 => :tag3, etc

14:21 There will a dozen-ish elements

14:21 ozzilee: ezyang: Hashmap?

14:21 ezyang: That seems like overkill...

14:21 ozzilee: Er. array I suppose.

14:21 ezyang: Is the array functional?

14:21 hiredman: ozzilee: vector

14:21 ozzilee: [:tag1 :tag2 :tag3 :tag4]

14:22 mrsolo: chouser: thanks!

14:22 ozzilee: Yeah, vector, sorry :-)

14:22 hiredman: ozzilee: that is a vector

14:22 stuhood: if the indexes will always be incrementing integers, then yea... a vector

14:22 ezyang: Does the vector give me O(1) access?

14:22 dnolen: yup

14:22 ezyang: Yup, always will be incrementing integers

14:22 Awesome

14:22 hiredman: ,(keys [:a :b :c])

14:22 clojurebot: clojure.lang.Keyword cannot be cast to java.util.Map$Entry

14:22 hiredman: :(

14:23 stuhood: aw... that should work

14:23 hiredman: ,(keys (map vector [:a :b :c] (range 20)))

14:23 clojurebot: clojure.lang.LazilyPersistentVector cannot be cast to java.util.Map$Entry

14:23 hiredman: Grrr

14:23 ,(map (comp second vector) [:a :b :c] (range 20))

14:23 clojurebot: (0 1 2)

14:24 ezyang: Hm. How do I convert a list to a vector...

14:24 hiredman: ,(vec '(1 2 3 4))

14:24 clojurebot: [1 2 3 4]

14:24 ezyang: Sweet

14:24 hiredman: ezyang: clojure.org/api

14:25 ezyang: Yeah, sorry about that; should have looked that up first

14:25 Chousuke: (let [myfn (fn [lst] (concat lst '(2)))] (myfn '(+ 1))); mrsolo

14:25 ,(let [myfn (fn [lst] (concat lst '(2)))] (myfn '(+ 1))); damn

14:25 clojurebot: (+ 1 2)

14:25 ezyang: Here's anot so easy to lookup question: when does clojure approve of (comp)?

14:25 Chousuke: mrsolo: see how that function returns clojure code?

14:25 hiredman: ezyang: "approve" ?

14:26 ~def comp

14:26 Chousuke: mrsolo: now, if you wanted to use myfn to write a macro that appends a 2 at the end of a clojure list form, you'd just do: (defmacro foo [form] (myfn form))

14:26 ezyang: For example, I could do something like (comp vec map) but that seems a little poor...

14:26 hiredman: "poor"?

14:27 Chousuke: mrsolo: notice, no quotes; myfn already returns clojure code :)

14:27 ezyang: as in, poor form

14:27 hiredman: why would you say that?

14:27 Chousuke: mrsolo: if you can understand why this works, then you already are well on your way to understanding macros.

14:28 ezyang: hiredman: Sort of gut feeling. No good reason

14:28 hiredman: my feeling is partial and comp don't get used often enough

14:28 ezyang: New question: I'm looking at some code that is building maps using a reduce()

14:28 I feel like there is a... better way of doing this

14:28 hiredman: people just use function literals everywhere

14:29 ezyang: maybe involving zipmap

14:29 hiredman: ezyang: better way of composing functions?

14:29 ezyang: Oh, sorry, I'm on another topic now :-P

14:30 mrsolo: chousuke: nice big difference between reading and writing though.. still lot a long way to go

14:30 Chouser: ezyang: did you look at 'into'?

14:30 stuhood: ezyang: reduce is a relatively good way, 'into' would be another

14:30 hiredman: ~def vec

14:30 Chousuke: mrsolo: yeah, but it's not that difficult once you really understand what macros do

14:30 hiredman: I imagine vec is faster then into

14:30 than

14:31 digash: Does anybody know Scala here? I need to do a presentation on Clojure to Scala NY group. I've done Clojure to Java programmers before, but what Scala guys would want to here?

14:32 ezyang: stuhood: Why wouldn't zipmap work?

14:32 Chouser: digash: they want to talk about contravarient type signatures

14:32 ezyang: Say I have a vector [:a, :b, :c] and a list (1, 2, 3) and I want {:a 1, :b 2, :c 3}

14:32 hiredman: digash: my guess is smooth interop with java Collections

14:32 stuhood: ezyang: in that case, zipmap is the perfect fit

14:32 ezyang: ,(zipmap '[a b c] '(1 2 3))

14:32 clojurebot: {c 3, b 2, a 1}

14:32 mattrepl: digash: macros over automated closures for designing DSLs

14:32 hiredman: scala is having a huge shakeup over their collections stuff right now

14:32 ezyang: Ok.

14:33 hiredman: ~scala

14:33 clojurebot: "you can usually accomplish a lot by laboriously enumerating type arguments everywhere." -- seen in #scala

14:33 Chousuke: mrsolo: they take clojure code as parameters: if you have a (foo [a]) macro and call it as (foo (+ 1 3)) then (= a '(+ 1 3)) is true. Then you operate on the parameters like any other function, and return new code (my earlier example would concat '(+ 1 3) and '(2), returning '(+ 1 3 2))

14:33 mrsolo: this function is then run at compile time, and the macro invocation is replaced with its return value.

14:34 Chouser: digash: though I was never a committed Scalar, what brought me to Clojure was how much you could get done without ever declaring a type, and how easily a DSL can be made without needing scala's too-clever auto-casting (or whatever it's called that I've now forgotten)

14:34 Chousuke: Scalar :P

14:34 Chouser: :-)

14:35 hiredman: yeah, I think clojure's java interop is (surprisingly?) better then scalas except possibly for Annotations stuff

14:35 Chousuke: mrsolo: you can have side-effects like println in macros, but usually it's not what you want, since it's run at compile time.

14:35 digash: Chouser: thanks, I try DSL. Then the next questions what are the best DSL examples in Clojure?

14:36 Chousuke: mrsolo: however, what you DO often want is *return* code from a macro that has side-effects

14:36 hiredman: digash: you could ask in #scala to see what they want to hear about

14:36 Chouser: digash: enlive

14:36 digash: hiredman: thanks, i would go there but first wanted to swim in the friendlier waters.

14:36 hiredman: heh

14:37 those darn scalars!

14:37 Chousuke: mrsolo: if returning code from a function makes sense to you, then you understand what "code as data" really means.

14:37 mrsolo: ya

14:37 i see why not

14:37 so

14:38 * digash cloning enlive

14:38 mrsolo: defmaco can be used to intentionally run some code during compile time?

14:38 for whatever the reason

14:38 Chouser: digash: http://github.com/Lau-of-DK/clojureql/tree/master

14:38 mattrepl: digash: someone in the crowd will probably ask about performance, so having some information on type annotations and unchecked arithmetic would be prudent

14:38 stuhood: digash: incanter seems pretty cool too http://github.com/liebke/incanter/tree/master

14:39 Chousuke: mrsolo: there are rules.

14:39 digash: mattrepl: is Scala performance on the par with Java native types?

14:39 Chousuke: mrsolo: it's not really compile time I guess, but "macro expansion time". usually macros are expanded first, and THEN stuff gets compiled.

14:40 mrsolo: what are the rules?

14:40 mattrepl: digash: I believe idiomatic Scala is more on par with Java than idiomatic Clojure

14:40 Chouser: mrsolo: sure, On Lisp shows some interesting performace tweaks by computing stuff at macro-expand time.

14:40 mrsolo: one can implement something similar to perl BEGIN i guess

14:41 Chousuke: mrsolo: a macro can't depend on runtime data, obviously :)

14:42 hiredman: mattrepl: scala still does a lot of intermediate object allocation

14:42 Chousuke: mrsolo: you can use whatever is available at macro expansion time, though. global vars etc.

14:42 hiredman: they also do what they call "de-scalafying" to get closer to java performance

14:43 Chousuke: scaling down? :)

14:43 (the mountain)

14:44 Chouser: toward the Java lowlands?

14:44 hiredman: yeah

14:44 Chousuke: clojure people can just take a paren and use it as a sled.

14:45 mattrepl: digash: destructing bind and keyword and rest params might be good material too

14:45 Chousuke: though the ride down might be fun but hitting the ground probably isn't.

14:45 hmm

14:46 hiredman: http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-1

14:46 Chousuke: about destructuring bind, I was wondering if it is possible to improve the destructuring that it's always equivalent to a sequential let when the source form is known at macro expansion time to match the target. :/

14:47 ezyang: Is there a list of clojure's string -> FOO conversion functions?

14:47 Chouser: ezyang: clojure doesn't have many of those. Mostly you use Java methods.

14:47 ezyang: ick

14:48 Chouser: ezyang: 'keyword' and 'symbol' take strings...

14:48 ezyang: ick?

14:48 Chousuke: eg. expanding (let [[a b c] [1 2 3]]) to (let [a 1 b 2 c 3]) instead of the weird (let [a (get somegensym 0 nil) ...])

14:48 Chouser: ,(Integer/parseInt "F00" 16)

14:48 clojurebot: 3840

14:48 hiredman: ,(.toUpperCase "foo")

14:48 clojurebot: "FOO"

14:49 Chousuke: I have seen complaints about destructuring let being inexplainably slower than non-destructuring let, and I think it could be fixed :/

14:49 hiredman: ,(-> "foo" .toUpperCase .toLowerCase ((partial map int)) ((parital reduce *)))

14:49 clojurebot: java.lang.Exception: Unable to resolve symbol: parital in this context

14:50 hiredman: ,(-> "foo" .toUpperCase .toLowerCase ((partial map int)) ((partial reduce *)))

14:50 clojurebot: 1256742

14:50 ezyang: Why did... Integer/parseInt take two parameters?

14:50 clojurebot: why not?

14:50 Chousuke: ezyang: it's overloaded.

14:50 hiredman: ezyang: because you have to give it a base

14:50 ezyang: Ok... I need to curry the second parameter

14:50 hiredman: ,(Interger/parseInt "10" 2)

14:50 clojurebot: java.lang.Exception: No such namespace: Interger

14:50 ezyang: This is going to be complicated

14:50 hiredman: ,(Integer/parseInt "10" 2)

14:50 clojurebot: 2

14:51 hiredman: ,(Integer/parseInt "10" 8)

14:51 clojurebot: 8

14:51 Chousuke: ,(Integer/parseInt "10"); works too I think

14:51 clojurebot: 10

14:51 ezyang: Oh, ok

14:51 cemerick: Chousuke: I can vouch for that. Got a 10% speedup on a key inner loop by eliminating [[v0 v1]] and using [v] with (v 0) and (v 1)

14:51 ezyang: ,Integer/parseInt

14:51 clojurebot: java.lang.Exception: Unable to find static field: parseInt in class java.lang.Integer

14:52 ezyang: Hmm... is it a first class function?

14:52 mrsolo: cemerick: ack!

14:52 Chouser: ,(let [from-hex #(Integer/parseInt % 16)] (from-hex "fa7"))

14:52 clojurebot: 4007

14:52 ezyang: But you anonymized it...

14:52 cemerick: mrsolo: ack?

14:52 ezyang: I guess that works

14:53 mrsolo: cemerick: huge performance penality for such an innocent construct

14:53 Chouser: ezyang: no, it's a static method, not a Clojure function.

14:53 Chousuke: cemerick: the problem is that I don't think it's possible to help in the case where you do destructuring like [[v0 v1] v]

14:53 ezyang: :-* Well, I guess that's the price you pay for getting Java

14:53 Chousuke: cemerick: since the form of the source is not known

14:53 cemerick: mrsolo: yeah...well, it was a *very* hot spot, FWIW

14:53 Chouser: Chousuke: [v0 (v 0) v1 (v 1)] ?

14:53 oh, if you want to allow for lists

14:54 cemerick: yeah, I don't think it's such a big deal.

14:54 I got that particular hint from a post that gnuvince made recently, and I remember some commenters trashing on clojure due to the current state of affairs, so maybe CL doesn't have that issue. *shrug*

14:55 Chousuke: so why would (nth v 1) be slower than (v 1)? :/

14:55 cemerick: one fewer method call?

14:57 Chousuke: ~source nth)

14:57 clojurebot: No entiendo

14:57 Chousuke: gah

14:57 ~source nth

14:57 ezyang: Does clojure have a built-in no-op?

14:57 Chouser: ,(do)

14:57 clojurebot: nil

14:57 Chousuke: identity?

14:58 cemerick: ezyang: identity

14:58 Chouser: nil

14:58 ezyang: Ok.

14:58 Chousuke: depends on the context I guess.

14:58 dnolen: ,(do nil (+ 4 5))

14:58 clojurebot: 9

14:58 cemerick: Chousuke: See, there's actually a number of levels indirection with nth

14:58 ezyang: ,(nil 1)

14:58 clojurebot: java.lang.IllegalArgumentException: Can't call nil

14:58 ezyang: ,(identity 1)

14:58 clojurebot: 1

14:58 gnuvince: The doc says that nth is O(n) for sequences while Vectors can index in O(log_32 n)

14:59 Chousuke: cemerick: I think it should inline the not-found case too :/

14:59 gnuvince: (v 1) is O(log_32 n) too, that's no different :)

15:00 cemerick: Chousuke: the function-call overhead could have been the difference in my case.

15:00 Chousuke: I think it's just that in destructuring, nth is used with the default value and it's not inlined.

15:01 Chouser: (v 1) compiles to (.invoke v 1), which calls v.nth((1).intValue())

15:01 Chousuke: okay, so it's basically equivalent.

15:02 I wonder if the slowdown goes away if the 3-parameter case is added to inline arities as well

15:02 Chouser: I wonder if the Var lookup for 'nth' itself hurts much.

15:04 Chousuke: or perhaps c.lang.RT/nth does instanceof lookups that slow it down :/

15:07 there's an enormous difference between doing (nth v 3) and (nth v 3 1) 10 million times.

15:08 Chouser: wild

15:11 ,(let [v [1 2 3]] (time (dotimes [_ 10000] (v 1))))

15:11 clojurebot: "Elapsed time: 6.454 msecs"

15:11 Chouser: what am I doing wrong here?

15:11 ,(let [v [1 2 3]] (time (dotimes [_ 1000000] (v 1))))

15:11 clojurebot: "Elapsed time: 101.76 msecs"

15:12 Chouser: hm, that looks vaguely sane. On my machine doing the lookup *100 more times only costs 0.5 more msecs.

15:12 ,(let [v [1 2 3]] (time (dotimes [_ 10000000] (v 1))))

15:12 clojurebot: "Elapsed time: 85.344 msecs"

15:12 hiredman: "Elapsed time: 390.49132 msecs"

15:12 :(

15:13 Chouser: Chousuke: oh!

15:13 destructuring uses (nth v x nil)!

15:14 Chousuke: the notFound slowdown you spotted may be the main culprit for destructuring

15:14 Chousuke: inlining the 3-parameter case is still slower, but saves 200ms for 10 million lookups compared to not inlining

15:15 Chouser: what do you mean by inlining there?

15:15 Chousuke: nth has {:inline (fn [c i] `(. clojure.lang.RT (nth ~c ~i))) :inline-arities #{2}}

15:15 just adding the 3-parameter version there

15:16 Chouser: ah!

15:17 ezyang: Let's say I have a map of values and a map of functions and I'd like a map of (function value). What do I do?

15:18 (the maps keys perfectly align)

15:19 Chousuke: hm

15:19 hiredman: (map #(%1 %2) (vals functions) (vals values)) would return a seq of (function value)

15:19 Chousuke: right... (map apply (vals fmap) (vals values))

15:19 hiredman: or that

15:20 Chousuke: hmm

15:20 mrsolo: clojurebot runs on fast machine!

15:20 hiredman: uh

15:21 Not Really

15:21 Chouser: I'd be nervous about using val seqs from two different maps

15:21 mrsolo: "Elapsed time: 222.746 msecs"

15:21 or mine is a very slow one

15:23 hiredman: (let [fmap {:a idenity :b identity} vmap {:a 1 :b 1}] (reduce #(assoc %1 %2 ((fmap %2) (vmap %2))) {} (vals fmap))

15:23 ,(let [fmap {:a idenity :b identity} vmap {:a 1 :b 1}] (reduce #(assoc %1 %2 ((fmap %2) (vmap %2))) {} (vals fmap))

15:23 clojurebot: EOF while reading

15:23 hiredman: bah!

15:24 Chousuke: hmm

15:24 Chouser: ,(let [funcs {:a inc :b dec} values {:b 5 :a 10}] (into {} (for [[k f] funcs] [k (f (values k))])))

15:24 clojurebot: {:b 4, :a 11}

15:25 tashafa: qq

15:25 Chousuke: ,(map (comp apply apply) (vals (merge-with vector {:foo + :bar -} {:foo 5 :bar 1})))

15:25 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: LazilyPersistentVector

15:25 tashafa: how do you install clojure-mode.el thru ELPA?

15:26 Chousuke: (vals (merge-with vector {:foo + :bar -} {:foo 5 :bar 1})))

15:26 gah

15:26 ,(vals (merge-with vector {:foo + :bar -} {:foo 5 :bar 1})))

15:26 clojurebot: ([#<core$_PLUS___3949 clojure.core$_PLUS___3949@482bad> 5] [#<core$___3975 clojure.core$___3975@46a55e> 1])

15:26 mrsolo: M-x package-install clojure-mode

15:26 tashafa: mrsolo thanks!

15:27 Chouser: Chousuke: ooh, I like where you're going.

15:27 Chousuke: safer than relying on the order anyway

15:27 tashafa: mrsolo: hmm, no match

15:27 Chousuke: (apply hash-map (merge-with vector {:foo '+ :bar '-} {:foo 5 :bar 1}))))

15:27 ,(apply hash-map (merge-with vector {:foo '+ :bar '-} {:foo 5 :bar 1})))) ;a hsfjslkfjg

15:27 clojurebot: {[:foo [+ 5]] [:bar [- 1]]}

15:28 Chouser: , (let [funcs {:a inc :b dec} values {:b 5 :a 10}] (merge-with #(%1 %2) funcs values))

15:28 clojurebot: {:a 11, :b 4}

15:28 Chousuke: aha, even better.

15:28 mrsolo: tashafa: package-list-packages will list available packages

15:28 tash: it should be in there

15:29 tash: you can navirage then do package-menu-execute afterward 'I' to mark for install

15:31 tashafa: go it

15:31 thanks man

15:31 got it*

15:31 mrsolo: np

15:32 Chousuke: (let [fs {:foo + :bar - :zonk reduce} params {:foo [1 2] :bar [10 5] :zonk [conj #{} [1 2 3]]}] (merge-with apply fs params)); fun

15:32 ,(let [fs {:foo + :bar - :zonk reduce} params {:foo [1 2] :bar [10 5] :zonk [conj #{} [1 2 3]]}] (merge-with apply fs params)); ASDFSDJFK

15:32 clojurebot: {:foo 3, :bar 5, :zonk #{1 2 3}}

15:33 Chousuke: how is it that I ALWAYS forget the comma

15:33 ezyang: So, merge-with is the magic?

15:33 Chousuke: yeah

15:34 ezyang: I wonder if it'll 'splode if the keys don't match up

15:34 Chousuke: it probably will

15:35 or rather, this happens:

15:35 ,(let [fs {:foo + :bar - :zonk reduce} params {:foo [1 2] :bar [10 5] :zonk [conj #{} [1 2 3]] :nonexistent 5}] (merge-with apply fs params));

15:35 clojurebot: {:nonexistent 5, :foo 3, :bar 5, :zonk #{1 2 3}}

15:36 ezyang: ,(merge-with apply {:foo +} {})

15:36 clojurebot: {:foo #<core$_PLUS___3949 clojure.core$_PLUS___3949@482bad>}

15:37 ezyang: Ew

15:37 Chousuke: yeah, the function printing thing is ugly ;(

15:37 need metadata for functions so it can be made prettier!

15:38 should say something like #<Fn clojure.core/+>

15:41 hiredman: clojure.core/+ is a symbol

15:42 Chousuke: that's why it says Fn in there

15:42 hiredman: why would the function care about a symbol it might be bound to?

15:42 Chousuke: okay, well, it could be just #<Fn +>

15:42 hiredman: + is also a symbol

15:42 Chousuke: yes, but it's the function's name.

15:42 and if it has no name #<lambda 2398449> or something

15:43 point being, something that easily identifies the function's name and possibly origin

15:44 hiredman: the only thing a function really maps to is a java class, which is what the current .toString is

15:44 ,(.toString (fn []))

15:44 clojurebot: "sandbox$eval__1992$fn__1994@1be0369"

15:44 Chousuke: hiredman: that's why functions need metadata.

15:46 the .toString is useless and icky anyway so if there were metadata it could be used

15:49 I wonder if there's something that prevent IFn or AFn or something from just extending IMeta :/

15:52 ezyang: Question: I want to dynamically define a function, like (def func (func-gen 0))

15:52 But it would be a defmethod

15:52 So I'm a little confused how to do it (defmethod being a macro and such)

15:53 Can I put the defmethod inside of another function?

15:54 Chouser: ezyang: usually best in these cases to do what the macro does, rather than try to call it.

15:54 (.addMethod multifn :value (fn ...))

15:55 stuartsierra: Chouser: where are the dispatch arguments?

15:55 Oh, :value, I get it.

15:56 Speaking of multimethods, did anyone ever figure out multiple-arg dispatch with inheritance?

15:56 That is, (defmulti m (fn [x y] [(class x) (class y)]))

15:59 Oh, never mind, isa? works on vectors of derived types.

16:05 ezyang: repl is giving me an exception, but not telling me where it came from...

16:05 Chouser: (.printStackTrace *e)

16:06 ezyang: Thanks!

16:12 Hmm... apparently, #(%1 %2) is not equivalent to apply

16:12 Chouser: indeed not

16:12 apply wants its final arg to be a collection, which it "unrolls" into the final args of the call.

16:13 ,(apply + 1 2 [3 4 5])

16:13 clojurebot: 15

16:13 ezyang: savvy

16:26 How do I introspect the contents of a multimethod?

16:26 Chouser: "contents"?

16:29 ,(doc methods) ; perhaps

16:29 clojurebot: "([multifn]); Given a multimethod, returns a map of dispatch values -> dispatch fns"

16:31 cemerick: it's unfortunate that the names of the fns installed as multimethods don't consist of, say, a concatenation of the method name and the dispatch value. That'd be handy, though probably dicey to implement safely.

16:33 stuartsierra: especially since the dispatch value could be absolutely anything

16:36 ezyang: Hey, does (load) do any dicey caching based on filemtimes?

16:38 Chouser: it checks file mtimes to determine if it should load .class or .clj

16:38 ezyang: Ouch

16:39 mrsolo: what if it is in resource file?

16:39 ezyang: A behavior of this is that multimethods don't get reinitialized properly

16:40 * hiredman doubts

16:40 mrsolo: i mean if a resource file has both .class or .clj, what gets loaded?

16:40 hiredman: mrsolo: if the clj is newer, it gets loaded

16:42 Chouser: http://code.google.com/p/clojure/source/browse/trunk/src/jvm/clojure/lang/RT.java#373

16:43 ezyang: This is a likely bug, then

16:46 * hiredman doubts

16:48 jkantz: in a single namespace make file_a, add a multimethod definition and (load "file_b")

16:48 add a defmethod to file_b

16:48 add another to file_c

16:49 compile the namespace

16:49 now change the file_b multi method

16:49 and load-file on file_a

16:49 the method in file_c will be gone

16:50 hiredman: a) you must be missing steps

16:50 b) if by compile you mean AOT compile, you should not compile single segment namespaces

16:51 jkantz: "single segment namespaces"?

16:51 hiredman: ~namespaces

16:51 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

16:52 hiredman: ~compile

16:52 clojurebot: the unit of compilation in clojure is the namespace. namespaces are compiled (not files). to compile a namspace the namespace needs to be on the classpath and so does ./classes/ (and the directory needs to exist) because clojure writes the class files to that directory. http://clojure.org/compilation

16:53 ezyang: The real code isn't single segment

16:54 jkantz: hiredman by b) do you rather mean you should not compile namespaces that have calls to load?

16:55 hiredman: no

16:55 compiling namespaces that call load is fine

16:56 it will cause the loaded code to be compiled

16:56 replaca: stuartsierra: it looks like the autodoc is right now. Can you confirm? http://code.google.com/p/clojure-contrib/wiki/StrUtils2ApiDoc

16:56 hiredman: jkantz: pastebin your test case

16:56 jkantz: right and then run into issues with defmulti and and defmethods in the loaded files when you try to reload the main file.

16:57 stuartsierra: replaca: closer, but not complete

16:57 replaca: what's missing?

16:57 jkantz: k, just a sec

16:57 hiredman: jkantz: I imagine you are running (defmulti ...) again which creates a new multimethod

16:57 stuartsierra: upper-case, lower-case, split, trim, contains?, get, split-lines, ltrim, rtrim...

16:58 hiredman: the new multimethod will not have any methods attached

16:58 replaca: k, I'll take a look

16:58 thanks

16:58 stuartsierra: sure, thanks for working on autodoc

16:58 ezyang: Right, but then when we (load) the sub files, the multimethod should then get repopulated

16:58 What's happening is that (load) is not loading the subfiles

16:58 jkantz: hiredman, right, and due to the other files not being modified they aren't reloaded to re-add themethods

16:59 hiredman: so how is that a bug?

16:59 jkantz: not so much as a bug as a gotcha

16:59 ezyang: I would argue it's a bug

17:00 There should be no functional difference between loading the clj and loading the class

17:00 hiredman: well, java cannot reload classes (unless you monkey with the classloader, I believe)

17:00 so there must be

17:01 stuartsierra: Clojure monkeys with the classloader

17:01 jkantz: you'd have to pass on the dependency information to subsequent loads

17:01 replaca: stuartsierra: functions with no doc strings don't get put in the autodoc. Put an empty doc string if you believe they're that obvious

17:02 jkantz: ~load

17:02 clojurebot: download is http://code.google.com/p/clojure/downloads/list

17:02 stuartsierra: Ah, ok

17:02 jkantz: ,(doc load)

17:02 clojurebot: "([& paths]); Loads Clojure code from resources in classpath. A path is interpreted as classpath-relative if it begins with a slash or relative to the root directory for the current namespace otherwise."

17:02 replaca: stuartsierra: I think that explains all the funcs that were missed

17:04 hiredman: jkantz: is there a reason you are using load instead of require, use, etc

17:05 technomancy: I've played with defining methods in a different file from the defmulti. It's not a lot of fun when dealing w/ reloads.

17:06 hiredman: never had an issue with it with clojurebot

17:06 jkantz: hiredman, many individual methods organized each into their own file, don't want the extra namespaces

17:07 hiredman: ugh

17:07 technomancy: I think there's a way to force files to load even if they haven't changed.

17:08 but yeah, if you step outside the one-file-per-namespace path, you're going to hit trouble

17:08 no way around that

17:08 hiredman: is this a chrome thing? or is github's source code numbering brolen

17:08 broken

17:08 jkantz: anyway touch * is the work around of the day

17:08 * mrsolo just learned slime's macroexpansion... omg...

17:08 jkantz: hiredman why ugh? you find it gauche

17:08 clojurebot: why not?

17:09 hiredman: jkantz: sorry I was refering to loading up github and noticing the line numbers are off

17:10 jkantz: ah ok, I'm out of here, have a good weekend

17:16 replaca: stuartsierra: ok, I think the autodoc is right now

17:19 stuartsierra: replaca: yes, looks good. Thanks!

17:19 replaca: stuartsierra: thank you!

17:25 btw, for anyone who was here on Wednesday - turns out we broke the cable to the projector and that's why everything turned pink. A new cable fixed everything.

17:28 stuartsierra: Now you can copy files and streams in pure Clojure!

17:28 technomancy: oh, I was going to write that.

17:28 nice. =)

17:28 how about recursive copy now? =)

17:29 stuartsierra: You mean recursive copy of directories?

17:29 technomancy: yeah, so I don't have to shell out to "cp -r"

17:30 stuartsierra: Hmm. Worth having, although I was aiming to handle streams.

17:30 technomancy: stuartsierra: would you take that as a patch?

17:30 yeah, it doesn't seem to belong in duck-streams

17:30 there's probably enough stuff that could go into a file-utils namespace to justify its creation

17:31 stuartsierra: surely

17:32 technomancy: I've also got an extract-jar function that I thought should go in jar.clj

17:33 but jar.clj could be subsumed into file-utils too

17:33 stuartsierra: Go for it.

17:33 technomancy: since there's only two functions in it

17:33 stuartsierra: want me to make an issue+patch?

17:34 stuartsierra: Do you have a CA? Or commit access on contrib?

17:35 technomancy: just a CA

17:36 stuartsierra: Ok, you can make a patch or just email me the code.

17:37 technomancy: all righty

17:37 just for extract-jar right?

17:37 I haven't written recursive copy yet

17:37 stuartsierra: yeah, sure

17:37 Well hop to it, then! :)

17:38 technomancy: hehe

17:48 replaca: stuartsierra: you're going crazy today!

17:49 stuartsierra: I'm shirking real work. :)

17:50 replaca: you and me both, man

18:00 stuartsierra: can I add fnmap.PersistentFnMap to compiled_classes in build.xml (that's where I'm putting anything that needs to be gen-classed to help support the autodoc)

18:00 I think that's fix the fnmap autodoc

18:01 stuartsierra: sure

18:01 replaca: k, thanks

18:04 stuhood: i have 1 hour and 30 minutes to write a mapreduce job in clojure for the first time

18:04 let's see how this goes.

18:05 technomancy: stuhood: a hadoop mapreduce or just a pure-clojure one?

18:05 stuartsierra: stuhood: you've seen mine?

18:05 stuhood: technomancy: using the hadoop api from clojure... we already have some base classes in java

18:05 stuartsierra: not yet... is it painful?

18:06 stuartsierra: The Clojure part is easy. The Hadoop API is... dense.

18:06 technomancy: stuartsierra: I read through yours. I think it would be super-helpful if you could make a blog post or something about how that works.

18:06 stuartsierra: I spent about a month learning Hadoop before I made serious use of it.

18:07 technomancy: reading the altlaw code was helpful, but trying to figure out which parts were specific to the task at hand vs which parts you need to copy was tricky.

18:07 stuartsierra: technomancy: yeah, it's on my agenda for... July?

18:07 technomancy: heh; ok cool.

18:08 the job input and output formats are a lot to wrap your head around too

18:08 I just got my example to the point where it would run; didn't actually get it to produce meaningful output. =)

18:22 stuartsierra: Good luck. I'm off.

18:22 triddell: technomancy: just created a blog and updated my tutorial: http://riddell.us/blog/2009/06/05/tutorials-available.html

18:23 now mentions you're approach

18:23 your that is

18:24 technomancy: cool

18:24 stuhood: if you don't add a ':state true' clause to gen class, do you still get a 'this' parameter added to your method calls?

18:24 hiredman: erm, I believe so

18:25 technomancy: triddell: I'm really _not_ trying to just drive hits to my blog, honest. It just comes off that way. =)

18:25 hiredman: wait

18:25 stuhood: this is only in proxy

18:25 triddell: technomancy: just want the best info out there... that was my intent with the tutorial

18:25 hiredman: for gen-class the this parameter is explicit

18:26 triddell: technomancy: gotta run though... just wanted to give you and other an fyi

18:26 technomancy: cool; have fun w/ your new blog

18:26 triddell: technomancy: thx ;-)

18:26 hiredman: like, a function backing a two arg method needs to have arity 3

18:26 stuhood: hiredman: explicit, in that i have to ask for it by saying :state true?

18:26 gotcha

18:26 hiredman: no

18:28 rsynnott: technomancy: so that you can make a VAST FORTUNE on google ads? :)

18:28 technomancy: rsynnott: you've found me out!

20:13 mrsolo: hmm aquaemacs doesn't have locate-dominating-file ....

20:59 dbudworth: Just checking to see if my IRC client is functioning, no one is saying anything...right?

20:59 ctdean: right

20:59 dbudworth: ahh, good. thought i was crazy (or this mac irc client was)... (usually it's me)

21:00 ctdean: Just the time and day I think, not much going on

21:06 dbudworth: any idea how to get the classpath set when using emacs-starter-kit + slime + swank-clojure? the username.el in .emacs.d is loaded too late it seems to take effect

21:06 ctdean: nope, sorry. I always set the classpath by hand

21:06 dbudworth: trying to go through the "programming clojure" book, but when using slime I can't get the classpath to include the book root dir (which is needed for things like (use 'examples.foo)

21:07 * durka42 wishes my book would come

21:07 dbudworth: you can set it inside clj? is there a way to dynamically add to the cp?

21:07 durka42: yes and no, there is add-classpath but it's discouraged

21:07 ataggart: highly

21:08 dbudworth: normally, wouldn't even need it. but for this particular case (book examples) they make a big assumption about your working dir (or at least having the root be in the cp)

21:09 ataggart: skipping over and just using the book's repl.sh made life easier

21:09 though I haven't gotten too far into the books code

21:10 dbudworth: yeah, that was the other choice. just use a regular shell. just thought slime was neat. IntelliJ's clojure plugin actually has a repl (and the standard Idea project classpath setup).. just wanted to use emacs' fanciness

21:11 ataggart: being neither an emacs user nor lisper, having to deal with emacs as well as learn the language was just too much to bear

21:11 now I just need to figure out how to kill the IntelliJ REPL

21:12 dbudworth: there's a "delete repl" or something like that, that kills it... checking

21:15 tools -> add / remove reply (option-command-a/option-command-m on a mac)

21:15 s/reply/repl

21:15 ataggart: ah thx

21:16 running doseq on an infinite fibonacci seq tends to bog things down

22:53 mattrepl: anyone been using c.c.error-kit?

Logging service provided by n01se.net