#clojure log - Jan 17 2010

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

0:42 alexyk: can transients be passed into defn's outside of those they were created in?

0:46 aldebrn: ,(for [n (range 3)] (do (println "hello")))

0:46 clojurebot: (nil nil nil)

0:46 aldebrn: ^ how come it doesn't println my "hello"'s?

0:47 (In my real example I have more in the (do) but they don't print)

0:47 kanak1: ,(for [n (range 3)] (doseq (println "hello")))

0:47 clojurebot: java.lang.IllegalArgumentException: doseq requires a vector for its binding

0:48 kanak1: ,(for [n (range 3)] (doall (println "hello")))

0:48 clojurebot: (nil nil nil)

0:49 qbg: ,*out*

0:49 clojurebot: #<StringWriter >

0:50 qbg: ,(println "Foo")

0:50 clojurebot: Foo

0:50 aldebrn: ,(doseq [n (range 3)] (println "hello"))

0:50 clojurebot: hello hello hello

0:50 qbg: I guess the printing needs to happen before the value is returned...

0:51 aldebrn: (doseq [n (range 3)] (println "thank") (println "you"))

0:51 * aldebrn was smote

0:51 kanak1: ,(for [n (range 3)] (dorun (println "hello")))

0:51 clojurebot: (nil nil nil)

0:52 kanak1: weird. in my repl, either one of dorun or doall also displays hello

0:53 qbg: ,(dorun (for [n (range 3)] (println "hello")))

0:53 clojurebot: hello hello hello

0:53 qbg: for returns a lazy seq

0:53 aldebrn: Gotcha!

1:00 alexyk: is there update-in! finally?

1:00 for transients

1:00 qbg: Not in the latest master branch

1:01 alexyk: rrr

1:04 I'm not fond of this:

1:04 ,(persistent! (binding [assoc assoc!] (update-in (transient {:a 1}) [:a] inc)))

1:04 clojurebot: {:a 2}

1:04 qbg: Why not write update-in! then?

1:05 alexyk: qbg: am not sure how :)

1:05 qbg: Since that horrible hack you just did seems to work

1:06 alexyk: it's chouser's so it should have :)

1:06 or _ato's

1:06 qbg: (defn update-in! [m ks f & args] (binding [assoc assoc!] (apply update-in m ks f args)))

1:06 (something like that)

1:06 alexyk: ah ok, you mean just defn'ize the hack

1:07 I was wondering if there's something deeper

1:07 qbg: This is Clojure; the obvious often works

1:08 alexyk: :)

1:10 qbg: The only real black magic I have found so far in Clojure is setting the :arglists metadata in a macro.

1:10 And I was only convinced my solution was right once I saw defn did that.

1:11 Weird stuff, but other than that good :)

1:13 alexyk: alas, the hack fails: (persistent! (update-in! (transient {:a {:b 1}}) [:a :b] inc)) doesn't work

1:14 and that's my use case

1:17 hiredman: ~def update-in

1:20 alexyk: hiredman: so for transients, is it only the first assoc which must become assoc!, and the rest stay assoc?

1:21 or nested map must become transient too?

1:21 hiredman: ah

1:21 yeah

1:22 alexyk: (persistent! (update-in! (transient {:a (transient {:b 1})}) [:a :b] inc)) => {:a #<TransientArrayMap clojure.lang.PersistentArrayMap$TransientArrayMap@1d840cd>}

1:22 so I guess I need to persistent! every nested map too

1:22 hiredman: update-in recursively calls update-in

1:23 qbg: Hmm... You can't seq a transient

1:23 I guess that makes sense...

1:25 alexyk: (let [half-there (persistent! (update-in! (transient {:a (transient {:b 1})}) [:a :b] inc)) keys (keys half-there) vals (vals half-there)] (zipmap keys (map persistent! vals)))

1:25 => {:a {:b 2}}

1:27 I guess a transient map of transient maps makes sense for a nested structure

1:27 hiredman: hmmm

1:27 I don't think so

1:30 gibranian: why doesn't my entries reach to other users, freenode says i should register, did flood of lasy night cause this?

1:30 qbg: I assume that you really need the transients for performance...

1:30 gibranian: hmm, they are successfully sent here, weird :)

1:31 alexyk: hiredman: indeed, hack fails: (update-in! (transient {}) [:a :b] #(inc (or % 0))) => null pointer exc.

1:33 gibranian: why is clojure case-sensitive? is it for better communication with java or is it an independent design decision?

1:33 chouser: gibranian: in a unicode world, case-insensitive is a bit scary

1:34 hiredman: why would anyone write a case insensitive language?

1:34 gregh: case insensitive is so 80s

1:34 alexyk: to please Lord Fortran

1:34 chouser: besides, it helps prevent CLers from shouting all the time

1:35 alexyk: and Mac HPFS non-plus

1:35 qbg: Hey, that was just the reader's default behavior!

1:35 chouser: CAR

1:35 what did you say?

1:35 CDAAADADR

1:35 shhh...

1:35 qbg: You set the reader to case-invert ;)

1:35 alexyk: chouser: how would yolu write update-in! ? :)

1:35 you

1:36 to it works for this case: (update-in! (transient {}) [:a :b] #(inc (or % 0)))

1:37 chouser: hm, I thought I pasted code that did nested transients

1:37 but it was a pain, and ended up rather slow

1:37 gibranian: so your argument is that it is old-fashioned, i see

1:38 chouser: gibranian: we're mostly goofing off, I think.

1:38 hiredman: gibranian: why would you want it case insensitive?

1:38 alexyk: chouser: I missed the nested ones

1:38 chouser: alexyk: not today, and I'm having trouble finding it now...

1:38 gibranian: chouser: sorry :) not yours, you had a point

1:40 qbg: You know what CL has that Clojure doesn't? third.

1:40 chouser: this does not seem right. I'm looking at http://paste.lisp.org/list/clojure?0 and not believing that's all the pastes.

1:40 hiredman: http://delicious.com/clojurebot/pastbin

1:41 gibranian: hiredman: i think naming conventions based on case sensitiviry like fooBar causes repetitive strain injury

1:41 :D

1:41 qbg: This is why we have Emacs

1:42 chouser: Clojure avoids both excessive caps and underscores

1:42 gibranian: qbg: emacs also causes repetitive strain injury, search for emacs pinky :)

1:42 hiredman: gibranian: fooBar can just as easily be used in a case insensitive language

1:42 chouser: oh, I just annotated someone else's

1:42 hiredman: it just doesn't force you to use the same case everywhere

1:42 chouser: alexyk: this is what I was thinking of: http://paste.lisp.org/display/92238#2

1:42 hiredman: http://delicious.com/clojurebot/pastbin+chouser

1:43 qbg: Emacs pinky is for the weak!

1:43 alexyk: right right, now I remember

1:43 gibranian: qbg: anyway, i'm just fooling, i love emacs.

1:43 alexyk: it was damn slow, but I wonder is it because of the transients nested?

1:44 qbg: Lazy way not to get Emacs pinky: spend more time in IRC than in Emacs

1:44 chouser: alexyk: oh, I wouldn't assume so. Just in that case it was a poor solution.

1:44 fanatico`: qbg: doctor's orders.

1:44 chouser: hiredman: handy, thanks!

1:45 hiredman: :)

1:45 alexyk: ok, sleepy time, dreaming of transient sheep

1:45 fanatico`: remapping capslock to ctrl is also pinky-friendly.

1:49 qbg: Emacs foot pedals could be cool

1:50 chouser: qbg: wow. just... wow.

1:50 qbg: I only have two feet though...

3:37 quizme: can you compile your own clj files into jars ?

3:37 tomoj: jars are just zip files

3:38 lypanov: quizme: http://clojure.org/compilation

3:38 tomoj: leiningen helps with clojure

3:38 (or steal someone's build.xml and use ant)

3:42 quizme: ok that's neat

3:42 lypanov: leiningen lets you basically just call "lein uberjar" and it builds you the jar you need, using the above aot compilation. super easy.

3:43 * lypanov wonders why not just call the project lein...

3:46 quizme: i c

3:48 can i ask a dumb question?

3:50 let's say you wanted to make a big graph (with cycles) and do a depth first search, and update a counter on each node everytime you stepped on it. what data structures should you use?

3:51 and would the counter be refs ?

4:20 * lypanov would like, totally help, but he's spent more time getting a nice environment than actually learning clojure up to now.

6:06 esbena: when porting a java program (which uses a lot of polymorphism and overloading) to Clojure: is the idiomatic Clojure way to pass structs around, use multimethods for overloading, and redefine methods for polymorphism?

7:37 LauJensen: I'm becoming more an more troubled by this lack of feedback from futures and agents when they fail - The fact that they can fail silently is adding a huge amount of insecurity to the program and should get some attention

7:43 the-kenny: LauJensen: There's a proposal or something like this for better error handling in agents

7:44 LauJensen: I don't need to it be happen particularily graceful, I just need to know when something breaks.

7:46 the-kenny: LauJensen: Maybe this patch is interesting:

7:46 http://www.assembla.com/spaces/clojure/tickets/30

8:06 dabd: would it make sense to support same arity overloading of functions if the user supplied type hints? http://pastebin.com/m14bcb6ad Or this should only be possible via multimethods?

8:30 opqdonut: that would make sense wrt. the java dispatch system

8:32 LauJensen: dabd: that sounds like the case for multimethods

8:41 dabd: LauJensen: I know multimethods support that I was just wondering if this could be also an alternative for overloading

8:41 LauJensen: Not to my knowledge

8:53 Can anyone tell me why lein doesn't find javax.mail here http://download.java.net/maven/2/javax/mail/mail/ when targeted with [javax.mail/mail "1.4.2"] ?

9:00 Raynes: LauJensen: Did you add it as a repository?

9:00 If not, you're going to need to do so.

9:00 LauJensen: Maven2 is automatically included

9:01 Raynes: Maven central is included. I'm pretty sure you'd need to add a repo for that.

9:01 LauJensen: Downloading: javax/mail/mail/1.4.2/mail-1.4.2.jar from central

9:01 Thats a line from lein, and that file exists in central

9:02 Raynes: Well if the fine exists in central, of course it will find it.

9:02 LauJensen: eh?

9:02 Raynes: But it isn't going to find it at the repo you linked.

9:02 file*

9:03 Unless I'm misunderstanding something very crucial.

9:04 I just woke up, you know.

9:04 * Raynes is off to find breakfast!

9:08 LauJensen: Whats the syntax for :repositories?

9:22 [["id" "url"]]

9:27 Raynes: LauJensen: It's a map of repository names to urls IIRC.

9:27 I'm eating a large bowl of chili at 8:30AM for breakfast.

9:27 LauJensen: Maybe I am a redneck after all.

9:27 :o

9:35 LauJensen: hehe, sure sounds like it

11:13 neotyk: Hi *

11:13 looking for some help with ns macro

11:14 Have no idea how to do following: (ns test-clean (:refer-clojure :exclude [compile]) (:use [leiningen.compile :only [compile]]))

11:15 I get: compile already refers to: #'clojure.core/compile in namespace: test-clean

11:32 Raynes: neotyk: (:refer-clojure :exclude (compile)) and (:use [leiningen.compile :only (compile)]) would work, I imagine.

11:33 neotyk: Raynes: let me try

11:34 Raynes: this: (ns test-clean (:refer-clojure :exclude (compile)) and (:use [leiningen.compile :only (compile)])) fails with: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

11:35 Raynes: I didn't mean for you to literally copy and paste what I said. :p

11:35 Hold on.

11:35 somnium: neotyk: did you add the exclude after compiling once?

11:35 seths: neotyk: rather than use :use, is it too painful to fully qualify the path to leiningen/compile?

11:35 as a temporary workaround?

11:36 somnium: neotyk: your first example looks okay, but the runtime may have already refered clojure.core/compile into the ns

11:36 Raynes: neotyk: http://gist.github.com/279440

11:36 neotyk: seths: no it should be fine, but I'm trying to understand how to use ns

11:36 Raynes: I wasn't sure how the :refer-clojure stuff worked. Never used it before.

11:37 neotyk: somnium: it might be the case as I run it in slime

11:37 r2q2: What is the name of that clojure made package manager?

11:37 it uses leinengen

11:37 seths: r2q2: leiningen is a build tool that can build jar files and download dependencies

11:38 o

11:38 neotyk: r2q2: clojars yoy mean ?

11:38 r2q2: yea yea

11:39 neotyk: r2q2: this is called repository not manager

11:39 r2q2: yea sorry about the confusion

11:39 somnium: neotyk: in that case unmapping c.c/compile or restarting slime should get it to compile (if thas indeed the problem)

11:41 neotyk: somnium: when disconnected slime and swank-p... again still getting same error

11:42 r2q2: How do i get a listing of the jars on clojars?

11:43 seths: http://clojars.org/repo/

11:44 r2q2: seths: Thanks.

11:44 neotyk: works with lein test

11:45 so swank is bringing c.c/compile into ns

11:49 r2q2: If I want to keep my code private do I never do a lein push?

11:49 seths: r2q2: yes

11:49 you can do a lein install

11:49 that just moves your jar to the local m2 repo, $HOME/.m2 for me

11:53 neotyk: why for lein test on http://gist.github.com/279445 reports contains 0 assertions

11:54 seths: what's the file name?

11:54 should match the ns

11:54 neotyk: seths: test_clean.clj

11:58 the-kenny: ,(doc for)

11:58 clojurebot: "([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr ...], :while test, :when test.

11:58 the-kenny: seths: for is lazy

11:58 seths: neotyk: there may be an issue with having "-" in the namespace

11:59 I have test-foo.clj and test_bar.clj in my test dir

11:59 neotyk: the-kenny: so I should take from it,

11:59 seths: full of blatant syntax errors and they aren't being reported

11:59 the-kenny: neotyk: Wrap it in a (doall

11:59 neotyk: ,(doc doall)

11:59 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

12:00 neotyk: awesome

12:00 seths: neotyk: my guess is your test file is not being evaluated at all... try putting random characters in it

12:01 er /s/evaluated/executed/

12:01 neotyk: seths: it is getting executed, doall did the trick

12:01 seths: d'oh

12:01 neotyk: or not :/

12:01 seths: same thing?

12:02 neotyk: now it reports that there are two assertions

12:02 but they should fail

12:02 must be something with my test

12:07 ,(doc doseq)

12:07 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

12:08 neotyk: the-kenny: doseq seems like better than (doall (for ... for my case

12:25 dabd: the only way to add documentation to a defmethod is through metadata?

13:52 LauJensen: Back in the day I used some getClassLoader/findResource hack to access resources in my project - Is there some helpers for Clojure that does that these days?

14:05 esbena: I'd like to create an anonymous class, and invoke the constructor of the super class: new AbstractAction("Quit") { ... }, but how do I invoke the constructor using the clojure (proxy [AbstractAction] ...)?

14:09 LauJensen: Whats the fn to print the stacktrace from *e ?

14:18 qbg: LauJensen: (.printStackTrace *e)

14:18 LauJensen: sanx

14:30 Drakeson: how do you add extra repositories in a project.clj file?

14:31 defn: Drakeson: :repositories [["repo-name" "url"]]

14:33 Drakeson: thanks

14:34 how do you exclude certain jars from bein installed?

14:35 robwolfe: Drakeson: you can't unfortunately

14:37 Raynes: defn: Really? Phil said it was a map of repo names to urls...

14:37 robwolfe: I'm pretty sure you can...

14:38 defn: Raynes: what i just showed you works fine

14:38 Raynes: defn: Then technomancy lied to me.

14:38 :p

14:38 defn: damn phil

14:38 lol

14:39 LauJensen: [log4j "1.2.15" :exclusions [javax.mail/mail

14:39 javax.jms/jms

14:39 com.sun.jdmk/jmxtools

14:39 com.sun.jmx/jmxri]]

14:39 Raynes: robwolfe: Yeah, you can exclude indirect dependencies like LauJensen just showed.

14:39 Drakeson: LauJensen: wow! that's _exactly_ what I wanted to exclude!

14:39 LauJensen: Drakeson: :repositories [["maven2-repository.dev.java.net"

14:39 "http://download.java.net/maven/2/&quot;]]

14:39 Raynes: Drakeson: He can read your mind.

14:39 * ordnungswidrig fights some macro.

14:40 Drakeson: LauJensen: yeah, I just called it java.net, though :)

14:40 robwolfe: Raynes: you can exlude dependencies, but not what will be installed

14:41 LauJensen: Drakeson: That just didn't work for me, thats why I posted the whole thing

14:42 * Drakeson wishes for nailgun or similar to be integrated in clojure someday.

14:42 ordnungswidrig: I have a macro that expands to a call to defn, say (defmacro foo [] `(defn bar [baz] baz))

14:43 At runtime I get "Can't use qualified name as parameter: compojure-rest.r2/request"

14:44 qbg: Do you need parameter to be readable?

14:45 ,(defmacro foo [] `(defn bar [~'baz] ~'baz))

14:45 clojurebot: DENIED

14:45 ordnungswidrig: qbg: Yes, I want it — I know I can gensym some. But

14:45 qbg: ,(macroexpand '(defmacro foo [] `(defn bar [~'baz] ~'baz)))

14:45 clojurebot: DENIED

14:45 ordnungswidrig: Oh, I only tried '~

14:46 qbg: I can't macroexpand with clojurebot? :(

14:46 ordnungswidrig: qpb: nope

14:46 qbg: AFAIR

14:46 Hmm, you can't defmacro actually

14:46 ,(macroexpand (defn foo [])

14:46 clojurebot: EOF while reading

14:47 ordnungswidrig: (,macroexpand (defn foo []))

14:47 qbg: Remember to quote

14:47 ordnungswidrig: last trial:

14:47 qbg: ,(macroexpand '(defn foo [] bar))

14:47 clojurebot: DENIED

14:47 qbg: I think it uses a regex...

14:47 ordnungswidrig: defn is forbidden as well

14:48 ,(defmacro cond)

14:48 clojurebot: DENIED

14:48 qbg: ,(eval (read-string "(+ 2 2)"))

14:48 ordnungswidrig: ,(macroexpand 'cond)

14:48 clojurebot: DENIED

14:48 cond

14:48 ordnungswidrig: ,(macroepand 'cond :a :b :c :d)

14:48 clojurebot: java.lang.Exception: Unable to resolve symbol: macroepand in this context

14:49 ordnungswidrig: ,(macroexpand 'cond :a :b :c :d)

14:49 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$macroexpand

14:49 ordnungswidrig: ,(macroexpand '(cond :a :b :c :d))

14:49 clojurebot: (if :a :b (clojure.core/cond :c :d))

14:49 ordnungswidrig: hell, polluting the logfile :-)

14:49 qbg: but macro expansion is acutally allowed

14:50 qbg: I hope you can't call a certain static java method...

14:50 Killing clojurebot would be sad...

15:01 chouser: ,(System/exit 0)

15:01 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)

15:01 chouser: qbg: that one? :-)

15:02 qbg: ,(.getUptime (java.lang.management.ManagementFactory/getRuntimeMXBean))

15:02 clojurebot: 4466784

15:02 qbg: chouser: yes

15:03 mabes: what is wrong with my syntax here? (use 'clojure.walk :only [:macroexpand-all]) (I know how to do this from the ns macro but from outside it)

15:03 qbg: Hmm... That is kind of low...

15:03 mabes: er.. I had (use 'clojure.walk :only [macroexpand-all]) but that doesn't work

15:03 chouser: mabes: (use '[clojure.walk :only [macroexpand-all]])

15:04 mabes: chouser: ah ok. thanks for answering

15:07 chouser: mabes: sure!

15:07 the use/require stuff is unnecessarily confusing, and up for a redesign.

15:16 neotyk: chouser: looking forward to that

15:17 chouser: me too!

15:17 mabes: I'm glad I'm not the only one that gets tripped up by it then :)

15:19 robwolfe: mabes: welcome to the club ;)

15:25 neotyk: chouser: is there a time line for this redesign?

15:27 esbena: anonymous function in Swing: how do I call 'this.dispose()'?

15:53 Raynes: Pattern match you say.

15:54 Who wrote that? I have a bone to pick with them. It was my idea - I just hadn't actually done it yet. :<

16:50 dabd: is it true that if a Java class extends Iterator I can automatically seq over it?

16:51 chouser: you need to call iterator-seq on it

16:53 dabd: ok I see. seq only works directly on classes implementing Iterable

16:56 chouser: ah right, because you want to be aware when a seq might be (lazily) pushing your mutable Iterator around.

16:58 ordnungswidrig: hmm, macros again. How can I use an argument to a macro as keyword at runtime?

16:58 the-kenny: ordnungswidrig: maybe '~foobar?

16:59 ordnungswidrig: Say (defmacro foo [bar] …) And I want :bar at runtime

17:00 the-kenny: There's a function, wait

17:00 ,(keyword 'foobar)

17:00 clojurebot: :foobar

17:02 the-kenny: ,(let [foo 42] `(keyword ~foo))

17:02 clojurebot: (clojure.core/keyword 42)

17:02 the-kenny: ,(let [foo 'bar] `(keyword ~foo))

17:02 clojurebot: (clojure.core/keyword bar)

17:05 ordnungswidrig: (defmacro foo [bar] `(keyword ~bar)) then (foo a) will expand to (keyword a). I want it to expand to (:a)

17:06 you see the conversion to keyword must happen at macro time, right=

17:06 s/=/?

17:09 Chousuke: ordnungswidrig: `(~(:keyword bar))

17:09 oops

17:09 without the :

17:10 ordnungswidrig: Chousuke: thanks. thats exactly what I see in my REPL, now :-)

17:20 ynniv: anyone use queries with SC.DateTime's?

17:30 nuggien: is it possible to use the "for" macro with a binding list that is determined at runtime?

17:31 qbg: nuggien: how evil do you want to get?

17:31 nuggien: not sure, clojure newbie still...

17:32 qbg: Since for is a macro, it doesn't have access to runtime values

17:33 You could use eval, but yuck.

17:33 What kind of stuff do you want in the binding list?

17:33 nuggien: qbg: right, I saw http://bit.ly/88RZxj

17:35 qbg: "for" was just an easy way for me to turn [[\a \b \c] [\y \z]] into ay, az, by, bz, cy, cz so I was just wondering if I could do this when the original vector is something determined at runtime

17:36 qbg: If you just want all combinations of two items, you don't need to create the binding list at runtime

17:37 (defn pairs [a b] (for [x a y b] (list x y)))

17:37 nuggien: qbg: exactly my problem though, the two items vec is just an example. I won't know how many items will be passed into my function until runtime

17:37 qbg: If you want n combinations, you could do it recursively.

17:38 nuggien: right, just thought there was something built into clojure i could use :)

17:38 qbg: There might be something in clojure-contrib

17:39 (that does what you want)

17:39 nuggien: thanks, i'll have a look

17:39 qbg: Hmm, since for is just the list monad, in theory you could build the chain at runtime...

18:02 dabd: why the documentation for empty? discourages the idiom (not (empty? and encourages (seq if the first is more intuitive http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/empty?

18:12 chouser: (if (not (empty? ...))) is a double-negative and needlessly deeply nested

18:13 Chousuke: And (seq foo) is just as clear to anyone familiar with clojure. :)

18:45 dabd: chouser: but the primary intention of (seq is to create a sequence not to use as a predicate, so it would be more natural to use (not (empty? when testing for emptiness

18:45 but of course (seq is a "clojurism"

18:46 and shouldn't we let the compiler bother with removing the double negative? after all it is a hidden implementation detail...

18:52 chouser: another primary use of 'seq' is to return null when collections are empty

19:19 Raynes: Thank Fontosius, the greek God of fonts, for Deja Vu Sans Mono 9pt.

19:27 alec: would anyone know of a clojure mode for gedit?

20:12 dabd: for a mixed Java/Clojure project what is the recommended build tool?

20:13 datka: Maven is always nice

20:15 dabd: clojure itself is build using just ant right?

20:15 datka: Yes

20:16 chouser: clojure includes a build.xml file for ant that compiles both java and Clojure AOT

20:16 dabd: I'm not familiar with ant or maven but I guess it would be better to learn maven

20:17 even if people say it is scary

20:18 datka: Maven is scary, but once you get used to it, its very nice

20:19 Especially if you find yourself using many dependencies

20:19 dabd: does maven completely replace Ant or it is necessary to use both?

20:20 chouser: I don't suppose anyone remembers if deftype on a protocol is still faster when the protocol is on an interface?

20:20 datka: No, you'll use the clojure-maven-plugin to compile

20:21 You can still call out to ant if you want

20:21 somnium: chouser: I thought :on was removed from defprotocol

20:23 chouser: oh, perhaps you're right.

20:23 rhickey: aargh - with metadata on functions, AOT-compiled core__init runs into a code size limitation...

20:25 and I thought I was almost done

20:26 :(

20:29 chouser: code size!? I thought Java classes got pretty big.

20:29 how can defprotocol generate its own named interface and not require AOT?

20:29 rhickey: the init code is one big load method and one big static initializer

20:29 r2q2: why is everyone saying stuff twice

20:31 somnium: r2q2: it may be your client

20:31 r2q2: it may be your client

20:31 rhickey: chouser: there is now a peer cache for Clojure's dynamic classloaders

20:32 * chouser sighs and files it away under "magic"

20:32 rhickey: I figured why should the OSGi, Netbeans et al classloaders have all the fun?

20:33 none-of them are strictly hierarchical

20:35 this cache accomplishes 2 things - it makes the (dynamic) classes available across loaders, and it makes the load of bytecode with the same hash a no op, instead reusing the already-created class. Using the interface by name still requires AOT for proper resolution in all cases

20:35 chouser: I do remember you mentioning that before...

20:35 rhickey: the generated interface is a nimplementation detail of dynamic use of protocols

20:36 chouser: I was asking because of the performance benefits of the real interface

20:36 no types on protocol method args?

20:36 seriously, it's like I look away for a week and everything that was once in my head is gone.

20:37 rhickey: the benefit is best ascribed to defining protocol methods inside the deftypes

20:37 chouser: ok

20:43 alexyk: is there a shorter way to achieve this:

20:43 ,(let [string nil] (if string (.toLowerCase string) nil))

20:43 clojurebot: nil

20:43 alexyk: i.e. lowercase if non-nil, nil if nil

20:44 chouser: (when string (.toLowerCase string))

20:44 alexyk: so when returns nil when the cond if false?

20:45 chouser: yes

20:45 alexyk: is

20:45 ok, thx!

20:45 somnium: alexyk: so does if, for the record

20:45 alexyk: ha! so else-less if is the same as when

20:46 is "when" just a prettier clearer else-less if then?

20:46 somnium: kind of, when inserts a do

20:46 chouser: right, both.

20:46 alexyk: ah ok, with a body helper

20:47 chouser: it helps indicate that there is no else, and also that there may be multiple steps in the then

20:48 alexyk: rhickey: I was surprised to find no update-in! in the core... Is there a reason it's omitted?

20:49 my large reduce-able data are nested maps which I grow e.g. when scannin 100M twits. I'd really like to quickly do it with transients

20:49 e.g. a graph is {:from {:to [list of messages]}

20:49 }

20:50 it would be really useful to have an efficient (update-in! graph [:a :b] some-f)

20:50 somnium: alexyk: did bashing directly on the cursors help performance any?

20:51 alexyk: somnium: didn't implement that yet, will try

20:52 but seeing no update-in! in the core still disturbs me, so I hope to shed the light to the top here :)

21:07 chouser: transients are relatively new. I wouldn't read too much into the current lack of any particular helper fn

21:07 alexyk: have you tried to write update-in! ?

21:09 hiredman: does update-in! recursively create transient maps? does it persist them afterwards? it is not as simple as pressing a button and making it happen

21:12 chouser: automatically persisting doesn't make much sense, I think.

21:13 if it's assuming all the interior maps and vectors are transients, then the ones it makes should be transient as well.

21:13 a recursive transient or persistent! fn is probably trickier

21:14 hiredman: alexyk: if you are heavily using transients on nested structures I would suggest just biting the bullet and going back and forth from mutable maps

21:15 you are going through all this to pretend to have mutable maps

21:19 chouser: ah, that was the problem. converting a single transient to persistent is O(1), but converting vector of transients to persistent is O(n)

21:29 alexyk: hiredman: probably it's one way, growing the map as mutable

22:25 chouser: just converted fingertrees from older syntax (with extend for protocols) to modern deftypes.

22:27 mostly just deleted boilerplate -- looks much better.

22:34 technomancy: Raynes, defn: the correct answer is a map of repo names to URLs, but because of the way destructuring works, a vector of two-element vectors will have the same effect

22:34 (specifying your own lein repos)

22:40 wilig: oh dang! thanks a bunch.

22:40 I've been looking forward to getting that fixed for quite some time.

22:41 wilig: technomancy: Well, it's probably got bugs ;-) But it does work for me.

22:41 How would you like it delivered?

22:41 technomancy: have you got a github fork of the project?

22:42 wilig: hmm, you know I have a github account, I guess that will work.

22:42 technomancy: pulling from a git remote (github or not) is the most convenient for me

22:42 wilig: give me a few minutes to tie up a loose end and I'll throw it up there.

22:42 technomancy: excellent

22:43 feel free to use github pull requests, messages on the swank-clojure mailing list, or just bugging me on IRC to notify me of patches in the future.

22:44 wilig: heh, cool.

22:44 technomancy: good heavens: http://www.piratejesus.com/nerdcore/nerdcore017.gif

22:46 wilig: lol

22:46 that's alot of work, to make a point.

22:51 Raynes: technomancy: <3

22:51 defn: I win.

22:53 technomancy: from a destructuring perspective, the only difference between a (hash-)map and a vector of two-element vectors is guaranteed ordering

22:56 Raynes: Regardless. I still win.

22:56 * technomancy hands Raynes a certification of winnerhood.

22:57 Raynes: I'd like to thank the academy...

22:58 chouser: did I miss something? what are you guys talking about?

22:58 Raynes: chouser: Somebody asked how you add repositories in a Leiningen project file.

22:58 I said a map, defn said a vector of vectors.

22:59 chouser: ah, ok. thanks.

23:06 seba_: I'm using c.c.generic.arithmetic to implement + - multimethods for my types. What do I do to avoid the need of refer-clojure :exclude [+ -] in the clients of _my_ ns ?

23:06 technomancy: wilig: gotta go offline for a while (train going underground), but I'll catch up later.

23:06 wilig: sounds good

23:06 technomancy: thanks for the help; much obliged.

23:06 wilig: my pleasure

23:07 chouser: seba_: I don't think there's anything you can do. If they don't want clojure.core/+, they have to say so.

23:08 seba_: chouser: how would you merge, in client code, + implementations from several namespaces and different types?

23:09 chouser: "merge"? you can pick which one you want to get when you use an unqualified +, and then have to use namespace names or aliases for the others.

23:13 seba_: chouser: Hum ... I see .... so, if I have (deftype foo) in foos ns and (deftype bar) in bars ns, and both namespaces implement + multimethod, client code should use (foos/+ foo1 foo2) (bars/+ bar1 bar2) (+ 1 2)

23:13 chouser: sure

23:13 hiredman: seba_: if you are using the + multimethod in c.c.generic.arithmetic they would both use c.c.generic.arithmetic/+

23:13 chouser: now, a defmulti lives in a single namespace ... well, yeah, what hiredman said

23:17 seba_: then clients of my ns need to _know_ how to call +. Wouldn't be nice to have encapsulation there? is not the fact that my ns uses c.c.g.a/+ an implementation detail?

23:18 is there any way to trick clients to use c.c.g.a/+ without them knowing it? given that generic already has an implementation for Number

23:22 I'm thinking, for instance, on a DSL. I would want clients to call + for numbers and for DSL types without needing to know the inners of c.c.generic

Logging service provided by n01se.net