#clojure log - Jul 24 2010

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

0:29 SandGorgon: any examples of nifty web apps using clojure ? (I have already taken a look at cow-blog and compojure)

0:39 TakeV: Are there any other books out there on Clojure, aside from Mr. Halloway's awesome book?

0:55 slyrus: chouser: earlier we were talking about the "type" that extend takes and you said that it's a type/class/interface. can it extend a protocol?

1:31 ok, here's the situation I find myself in repeatedly. I define a protocol. I have some "low-level" issues that are handled by, say, a defrecord, then I want to define some operations that work on objects that implement that protocol. I can just have these operations be defns, or I can extend the original protocol and the defrecord to match. Is there anything "in between", like defining...

1:31 ...methods that act on all objects that implement the protocol -- not just ones tied to this particular defrecord??

1:32 mmarczyk: slyrus: protocols are backed by interfaces -- see (:on-interface the-interface)

1:33 slyrus: yeah, but I couldn't seem to make extend extend a protocol. not sure what I'm doing wrong tho.

1:33 mmarczyk: you wouldn't extend a protocol, but the underlying interface

1:33 (defprotocol Foo (foo [this])) -> (extend-type user.Foo ...)

1:33 user.Foo as opposed to user/Foo

1:34 slyrus: oh, I see. brain hurts more.

1:34 mmarczyk: I suppose you could do (defprotocol FooExt ...)

1:34 and (extend-protocol FooExt Object ...) / (extend-type Object FooExt ...)

1:34 where all impls would use methods from Foo

1:35 btw, I was looking at shortcut and got quite excited actually :-)

1:36 slyrus: ah, glad to hear it. i've gone and broken everything though :)

1:36 git reset --hard to the rescue!

1:36 mmarczyk: hopefully I might be able to use it or perhaps add an algorithm or two and then use it... note I'm not too sure what I'm doing yet ;-)

1:36 ohhhh

1:37 slyrus: on a second thought, I guess I'd go with regular defns for functions on "anything which implements Foo"

1:39 slyrus: there's a way to declare the type of defn args in defn lambda-lists -- um I mean lambda-vecs or whatever they're called in this newfangled lispish --, right?

1:39 mmarczyk: you can type-hint defn args, yes

1:40 see e.g. (source subs)

1:40 that's clojure.contrib.repl-utils/source

1:40 Lajla: ((fn [] "I Worship His Thunk))

1:40 ,((fn [] "I Worship His Thunk))

1:40 clojurebot: Lajla: Pardon?

1:41 Lajla: mmarczyk, why not?

1:41 slyrus: mmarczyk: c.c.subs too :)

1:41 mmarczyk: slyrus: hm?

1:41 Lajla: slyrus, what wrongs have I wroth upon this bot for her to defy me?

1:42 slyrus: oh, never mind

1:42 Lajla: Perhaps hers was the shadow for me to have worshipped.

1:42 replaca: Lajla: you forgot the closing quote

1:42 Lajla: Ahh

1:42 Cool

1:42 slyrus: I thought you were saying it is was c.c.r-u/subs

1:42 Lajla: ,((fn [] "I Worship His Thunk"))

1:42 clojurebot: Lajla: Gabh mo leithscéal?

1:43 replaca: that oughta work

1:43 Lajla: slyrus any more suggestions

1:43 replaca, you try it.

1:43 * thunk pricks up his ears

1:43 Lajla: I think they hooked the bot upt o ignore me.

1:43 replaca: ,((fn [] "Hello there"))

1:43 clojurebot: "Hello there"

1:43 * slyrus suggests /ignore

1:43 Lajla: ,((fn [] "Hello there"))

1:43 clojurebot: Lajla: I don't understand.

1:43 Lajla: Oeh

1:44 replaca: hah!

1:44 Lajla: Though, in the name os science, I must try this at least 400 times to test if it is reproducible.

1:44 replaca, be my control group.

1:44 Gogogo

1:44 ,((fn [] "1"))

1:44 clojurebot: Lajla: It's greek to me.

1:46 slyrus: ok, as I was saying... defprotocol + type-hinted defns is probably what I was looking for

1:48 Lajla: ,,

1:48 clojurebot: Lajla: Huh?

1:48 Lajla: ,

1:48 clojurebot: Lajla: Excuse me?

1:48 Lajla: ,

1:48 ,

1:48 clojurebot: Lajla: Huh?

1:48 Lajla: AHA

1:48 I have you now.

1:49 Your mind is as an open book to me.

1:51 mmarczyk: slyrus: I wonder how much is the type hint buying you

1:52 slyrus: peace-of-mind :)

1:52 mmarczyk: slyrus: I mean, if you've got a protocol extended to, say, IPersistentMap

1:52 then a type hint on a function which is to operate on such maps with the protocol functions

1:52 is just... wrong

1:53 I mean, IPersistentMap instances are not of type user.Foo, even if you extended user/Foo to IPersistentMap

1:53 nothing will break with the hint afaict

1:53 slyrus: hrm... I see.

1:53 mmarczyk: but it's just not clear to me if there's any gain

1:54 slyrus: I think I'm doing something a bit different. take a look at: (defn neighbors [^EdgeSet v node] (map #(first (neighbors % node)) (vals (edges v node))))

1:54 mmarczyk: now if you had a method called foo

1:54 and called it as (.foo ... ), not (foo ... )

1:54 then there would be a difference

1:55 but you can't use (.foo ...) with extend*

1:55 slyrus: yes, v is likely to be an IPersistentMap, but I'm calling (edges v node) on it. these are methods of the NodeSet protocol, not IPersistentMap.

1:56 and the idea is that this would work on another implementation of NodeSet, one that didn't use IPersistentMap. Am I missing something obvious here?

1:56 mmarczyk: well, type hints are for avoiding reflection

1:57 slyrus: oh, I thought there might be some type checking going on.

1:57 ok, maybe this should just be an unhinted defn.

1:57 mmarczyk: as I said above, the ^EdgeSet type hint is actually misleading the compiler

1:57 Lajla: mmarczyk, accordingly Sigmund freud your hooking up of that bot to ignore me is the manifestation of a subconscious desire of yours to ban me, hit me and tell me that I'm insane and should have a talk with Signund Freud.

1:57 slyrus: my puny brain is still wired for CLOS' defgeneric and defmethod.

1:58 mmarczyk: because type hints have to do with Java types and reflection

1:58 * slyrus treats java like he treats CLASSPATH. if he ignores it long enough, it will go away :)

1:58 mmarczyk: :-)

1:59 try

1:59 slyrus: i don't suppose defmulti helps here?

1:59 tomoj: clojure is leaky though :(

1:59 mmarczyk: (defprotocol PFoo (foo [this]))

1:59 (defrecord RFoo [] PFoo (foo [this] :foo))

1:59 (defn bar [^PFoo x] (.foo x))

1:59 (defn baz [x] (.foo x))

1:59 oh

2:00 only you need

2:00 (set! *warn-on-reflection* true)

2:00 before all that

2:00 so now (bar "asdf") and (baz "asdf") give different error messages

2:01 slyrus: Unable to resolve classname: PFoo

2:01 mmarczyk: actually it's probably going to be user.PFoo

2:01 slyrus: I see...

2:02 mmarczyk: you'd need to (import user.PFoo) to leave off the package

2:02 slyrus: yechh...

2:02 mmarczyk: then baz compiles with a reflection warning

2:02 and (bar "asdf") attempts a cast of String to PFoo (and fails)

2:02 whereas (baz "asdf") uses reflection to determine if (.foo "adsf") makes sense

2:02 and still fails, but differently ;-)

2:03 now

2:03 (defn bar* [^user.PFoo x] (foo x))

2:03 (defn baz* [x] (foo x))

2:03 and there's no difference between (bar* "asdf") and (baz* "asdf")

2:04 (that I know of)

2:04 slyrus: about defmulti... why'd you want to use it?

2:05 if you want to write a function dealing with EdgeSet instances, just document it as such and call EdgeSet methods

2:05 Kaali: What does the function* naming convention mean?

2:05 slyrus: sure, but the idea is that if i have a function like neighbors then somebody else might come along with a different graph implementation and write an appropriate neighbors function.

2:06 mmarczyk: Kaali: no single established meaning, here it was meant as "a variant of"

2:06 Kaali: mmarczyk: Okay, thanks

2:07 mmarczyk: slyrus: ah, then sure, either a protocol or a multimethod will do

2:13 a multimethod might be more flexible...

2:43 slyrus: Ok, here's an issue. I've got a protocol, I extend-protocol a primitive type (IPersistentMap) and I want to have a function/method that works on that. Then I have a different defrecord, I want the same-named function/method to work on that. In this case it's the neighbors function. How can I do that?

2:47 Chousuke: slyrus: just implement the protocol directly in the record definition

2:48 slyrus: it should be preferred over the more generic implementation

5:30 esj: Fresh MEAP !

5:31 Raynes: esj: I beat you to it.

5:31 :D

6:10 Bahman: Hi all!

6:13 lypanov: i start to wonder if the words i don't know of in the

6:13 ... clojure books are real words, or typos

6:23 tomoj: like what?

6:52 zmyrgel: could somebody explain briefly whats the difference between defn and defn-

6:52 the non-public def is mystery to me

6:53 hiredman: what's mysterious about it?

6:54 zmyrgel: so with defn- I make non-public functions which I can't access from ... somewhere or what?

6:54 hiredman: can't access from outside of the namespace where they are def'ed

6:55 zmyrgel: ah

7:52 candeller: hi, why does the split function return an empty string at the beginning (I want to split on every character) (split "abcde" #"") #=> ("" "a" "b" "c" "d" "e"), isnt that a bug?

7:53 (seq str) is ok, but (seq (.split str #"")) isnt

7:54 (seq (.split #"" str))*

8:02 rubydiamond: guys.. getting this error Exception in thread "main" java.io.FileNotFoundException: Could not locate ring/adapter/jetty__init.class or ring/adapter/jetty.clj on classpath: (run.clj:0)

8:03 after running clj script/run.clj

8:03 am I missing something

8:03 I have followed http://mmcgrana.github.com/2010/07/develop-deploy-clojure-web-applications.html

8:04 Raynes: That means that jetty is not on your classpath.

8:04 rubydiamond: Raynes: but that tutorial does not mention about classpath

8:05 Raynes: also I have 18 jars in lib folder..

8:05 Raynes: That is because Leiningen should handle the classpath for you.

8:05 rubydiamond: does it mean .. I have to manully add those classpaths

8:05 Raynes: but I am directly running clj without leign

8:05 lein*

8:06 Raynes: rubydiamond: Your clj script should be adding lib/* to the classpath. You should be able to do this: java -cp "lib/*:src" clojure.main script/run.clj

8:07 er, java -cp "lib/*:script" I guess. Whatever needs to be added to the classpath. :p

8:07 Ah yeah, it's "lib/*:src/"

8:08 Wasn't sure where the tutorial was putting that stuff.

8:08 rubydiamond: hmm

8:13 Raynes: Exception in thread "main" java.lang.Exception: Unable to resolve symbol: a in this context (core.clj:17)

8:14 Raynes: That sounds like a bug in the tutorial.

8:14 rubydiamond: hmm.

8:15 Raynes: if you could please try this tutorial..

9:04 Raynes: chouser: ping

9:56 lozh: Can anyone see a way to simplify rgb-to-key-colour in http://clojure.pastebin.com/ppuZgdLV get the feeling I'm missing something

9:58 raek: ooh, enlive uses tagsoup...

10:01 lozh: sort-by comes to my mind

10:02 and use #(nth % 0) as the keyfn

10:02 lozh: thankyou

10:02 raek: hrm, is sort lazy, btw?

10:03 also, when the function you pass to map is getting big, consider using for

10:03 Raynes: -> (type (sort [1 2 3]))

10:03 sexpbot: => clojure.lang.ArraySeq

10:06 lozh: min-key looks like it should be useful, but I can't figure out how to apply it to a collection

10:07 ,(min-key (fn [x] (-5 x)) 1 2 3)

10:07 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

10:07 lozh: ,(min-key (fn [x] (- 5 x)) 1 2 3)

10:07 clojurebot: 3

10:08 lozh: but I'd like that to be '(1 2 3) as the last argument

10:09 rhudson: ,(apply min-key #(- 5 %) [1 2 3])

10:09 clojurebot: 3

10:10 lozh: cool, thanks

10:10 raek: lozh: the rgb-distance-squared doesn't return anything

10:10 lozh: it does now, sorry, I missed the end off

10:11 http://clojure.pastebin.com/GABaaeGB

10:13 http://clojure.pastebin.com/BMdZsJwW using that min-key trick, very nice, thanks

10:15 Raynes: lozh: You know, gist.github.com and paste.pocoo.org have Clojure-specific highlighting.

10:15 lozh: I didn't, I was wondering about that, thanks again

10:16 Raynes: lozh: There are several more that do as well. hpaste.org (I think), ideone (this one can also run your code, but last time I checked, highlighting was a little broken), and probably more.

10:17 * Raynes is out of tea. :(

10:19 raek: lozh: http://clojure.pastebin.com/idHfFnvE

10:19 oh

10:20 lozh: That's nice too

10:20 raek: the min-key is nicer...

10:20 just my 2 öre

10:20 lozh: It's all a good way to learn the standard libraries though

10:20 raek: yeah

10:20 rhudson: You can shorten the rgb-distance-squared, if you like, to something like (defn dx2 [c1 c2] (->> (map - c1 c2) (map #(* % %) (reduce +))

10:21 oops, should be (map #(* % %))

10:21 lozh: neat

10:22 mfex: lozh: (-> (sort-by (fn [[k v]] [(rgb-distance-squared rgb-color k) v]) colour-map) first val)

10:23 raek: that reminds me of the coordinates-as-maps addition: (merge-with + {:x 1, :y 2} {:x 3, :y 4})

10:24 that even works for adding two and three-dimensional vectors (asuming z=0 if not given)

10:25 lozh: thanks mfex, amazing how many ways it can be done

10:27 rhudson: -> and ->> are two of the coolest most useful macros in Clojure. I've wondered if they have precedent in older Lispy langs.

10:27 sexpbot: java.lang.Exception: Can't take value of a macro: #'clojure.core/and

10:28 rhudson: sexpbot I wasn't talking to you

10:31 raek: tutorial.scrape1> (hn-headlines)

10:31 ("Developing and Deploying a Simple Clojure Web Application" ...)

10:32 what are the odds?

10:32 dnolen_: raek: :)

10:34 mfex: lozh: this is a bit better than my first suggestion (-> (sort-by #(rgb-distance-squared rgb-color (key %)) colour-map) first val)

10:35 raek: what package is 'cljcp' a part of?

10:36 * raek just realizes that is described on the page he's reading

10:37 lozh: mfex I went for (colour-map (apply min-key (partial rgb-distance-squared rgb-colour) (keys colour-map)) in the end, thanks :)

10:38 raek: dnolen_: I think your clj script fills the gap between leiningen project management and launching scripts from the command line pretty well

10:39 Raynes: rhudson: sexpbot apologizes. -> is the new code-evaluation prefix. It's the only thing I could think of that's easy to remember and type that nobody will type in a channel and set it off accidentally. Guess I failed on the latter though. But that has only happened just this once so far. ;)

10:39 mfex: lozh: I was hoping to find something called "best" or something that combines sort-by and first, to no avail so far

10:39 dnolen_: raek: my clj script?

10:39 rhudson: Raynes, no problem; I realized that's what was going on.

10:40 raek: oh... wrong person

10:40 was reading your enlive tutorial in the other tab

10:40 lozh: I know min-key does at most one comparison per value in the key-colours map, not sure if sort-by will be the same

10:40 * dnolen_ is impressed with how fast bake launches a repl. loves the fact that it doesn't trigger the windowing environment a la cljr.

10:45 mfex: min-key is the "best" function I was looking for

10:45 patrkris: what is the easiest way to get a 'submap' B from a map A, specifying in a seq which keys to include from A?

10:46 lozh: heh :)

10:48 mfex: lozh then you can just do (val (apply min-key ...)) no need for the (colours-map ... (keys colours-map))

10:50 rhudson: patrkris: look at clojure.set/project

10:50 lozh: patrkris: select-keys (http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/select-keys)

10:50 rhudson: ah, that looks better

10:50 lozh: mfex: cool, thanks for that

10:51 patrkris: lozh: ah, marvelous - thanks

10:51 i knew there had to be a function to do that

10:53 raek: I get this when using enlive: (fetch-url "http://clojure.org/contributing") => ({:tag :html, :attrs nil, :content ({:tag :body, :attrs nil, :content nil})})

10:53 anyone know why?

10:54 the fetch-url call becomes (html/html-resource (java.net.URL. "http://clojure.org/contributing"))

10:57 it works for other sites, but the contributing site seems to be empty for enlive

10:58 maybe this is a tagsoup issue, or due to badly configured content negotiation

11:07 Bahman: Hi all!

11:12 raek: hi

11:23 lozh: is there an easy way to get for to create a map?

11:25 jkkramer: ,(into {} (for [i (range 5)] [i (* i i)]))

11:25 clojurebot: {0 0, 1 1, 2 4, 3 9, 4 16}

11:25 lozh: cool, thanks

11:36 Kaali: Hi everyone, I made a small web form validation library as a practice project on Clojure. http://github.com/Kaali/pour -- I wanted to use assert-args included in Clojure, but it's a private fn. Was it okay for me to copy it to a file with the copyright from Clojure's core.clj included and also Rich Hickey's copyright included in the README?

11:37 Chousuke: it's under the EPL, right?

11:37 then it's fine.

11:38 Kaali: Yeah it's under EPL. I figured it would be fine, but it's always good to make sure.

11:51 raek: Kaali: nice library

11:52 ah, it does conversion/normalization too!

12:10 Kaali: raek: Thanks, it's first piece of Clojure I have written (except for some SICP excercices). I guess it needs some cleanup and code review. And more validations/conversions.

12:11 edbond: how to return first non-nil from seq or nil?

12:11 raek: (first (filter identity the-seq))

12:12 or (first (remove nil? the-seq))

12:12 the latter treats false distinct from nil

12:14 Kaali: will the requirements of a field always come in [validator-fn error-text] pairs?

12:15 Kaali: Yes

12:16 I had no idea how to approach multi-lingual support, so I though that the explicit error-text is a close enough solution. That's why the validators don't output messages at all.

12:17 raek: sounds resonable to me

12:17 translation is often done as some enlgish-to-other-language mapping, I think

12:17 Kaali: But I guess the inner vectors could be removed from the syntax, as they provide no real value vs. just partitioning the outer vector.

12:18 raek: clojure forms often leave out the "inner vectors": (cond a b c d e f) (let [a b c d e f])

12:19 Kaali: I actually tried to remove them, but partition converted them to a list, which somehow broke it; but that's just me being a Clojure newbie.

12:19 raek: (*if* your goal is to mimic clojure syntax as closely as possible, then :password [required "Password is required" (minimum-length 5) "Password should be at least 5 chars long"] could be considered)

12:19 ah

12:20 Kaali: Yeah, that's what I was trying to do, but gave up for now.

12:20 raek: just don't get me wrong. I it's really great that you've made this lib

12:20 Kaali: Comments are always welcome, no problem at all.

12:20 raek: there shouln't be any problem to use partition in this case

12:22 Kaali: Yeah, I should try it again. I guess the problems I had, had something to do with macros. I might be a bit more wiser now...

12:22 * raek looks into the code

12:22 raek: http://gist.github.com/446760 <-- example of a macro that uses partition

12:23 Kaali: Sorry for the lack of comments or documentation, and also the lack of tests. Those are on my TODO list.

12:24 raek: how is "pour" pronounced?

12:24 Kaali: http://www.merriam-webster.com/dictionary/pour

12:24 raek: like the english word=

12:24 Kaali: Yup

12:25 It's really an anagram of a finnish name, but matched with english.

12:33 raek: Kaali: instead of (map (fn [item] ...) coll), try (for [item coll] ...)

12:33 jli: are there many people here who are more used to strongly-typed functional languages? common lisp was my first functional language, but I've been doing OCaml and Haskell for the past couple of years, and I'm just learning Clojure now

12:35 Kaali: raek: Yeah, it seems to be a cleaner version of what I do with map all the time.

12:35 dnolen_: Kaali: pour looks sweet. Nice name too.

12:36 Kaali: dnolen_: Thanks

12:39 raek: Kaali: do you want me to look into this no-inner-vectors thing?

12:40 I would want that syntax myself

12:40 and if it aslo were your original intension...

12:40 Kaali: raek: I'm trying to solve it right now, but go ahead.

12:40 rhudson: jli: I wouldn't say more used to, but Haskell was my first FP lang, and I'd looked into OCaml (and Scala) before falling in love with Clojure

12:41 jli: rhudson: hm, okay. how much did you like Haskell?

12:42 rhudson: I liked lots of things about it, never really liked its story about state & side-effects

12:42 jli: yeah, I know what you mean

12:43 I think I appreciate it, but don't really want to be forced to use it

12:44 Kaali: raek: I'll go off for a while, seems like my friends car which he lend to me, might be stolen. Fun.

12:44 rhudson: I understand why it is the way it is, and I think it's a tremendous intellectual achievement

12:44 raek: Kaali: this could be useful to have in the library (defn pred-to-validator [pred] (fn [x] (when (pred x) x)))

12:45 Kaali: raek: Yeah, I though about that too. Thanks for the note, it means that it should be added.

12:45 jli: rhudson: yeah, exactly. I think it's just too intellectually challenging to write in :)

12:46 rhudson: jli, that was my feeling. I'm so impressed with Clojure's story about state -- to my mind it's just a rigorous, but a lot easier to reason about

12:46 [just a => just as]

12:47 i.e. a lot easier to write code in!

12:48 jli: yeah, I haven't done anything with it yet

12:49 Kaali: raek: Back again, false alarm about the car.

12:50 rhudson: I think you might really enjoy it. Clojure is such a gem of language design, very clean, very usable, very powerful

12:50 Kaali: raek: If you wish, you can fork the project and push changes to me, I'll gladly merge them.

12:51 jli: rhudson: yeah, I'm liking it so far. I'm just afraid that I'm too used to strong typing now. we'll see

12:51 raek: so nil always means "validation failed"?

12:51 Kaali: Yes

12:53 I thought about using exceptions, as those wouldn't block any return values. But it might make the validator interface a bit more complex.

12:53 raek: one can use a special sentinel value, such as a let'ed (Object.) or perhaps ::invalid

12:54 * raek tries to figure out if he would need nil as a valid value

12:54 Kaali: At first I used :error, but I thought it could clash if someone wanted to convert to a keyword.

12:55 rhudson: jli, I gave up on Scala because I spent more time getting the type decls right than the actual program logic. "Yes Mr Compiler, I know what I'm doing."

12:55 raek: using namespace qualified keywords works as long noone tries to use the keywords of your namespace

12:56 :pour.core/error

12:57 namespaced keywords are made for avoiding clashes

12:57 jli: rhudson: yeah, you have to sort of think in a "typed" way, but I feel like once you get used to it, you get a lot of power from it in terms of correctness checking

12:57 Kaali: raek: Nice. Then the pred-to-validator fn would be more important than now. Well, it's a great abstraction either way.

12:58 raek: (alias 'p 'pour.core) ::p/error, can be used from other namespaces

12:58 Kaali: Would that bind the validators too much to pour?

12:59 Or is that a moot point?

12:59 raek: well, that is a valid point

13:00 another solution would be to return a 2-vector containing the result and whether it was valid

13:00 => [123 true]

13:00 => [nil false]

13:01 (output from a number validator)

13:01 Kaali: That would also complicate the validator interface a bit.

13:02 raek: the nil is error is very simple

13:02 and simple is good

13:02 Kaali: Yeah, I guess it should be left as is for now, and hope for the best that nobody wants to use nil as a valid value.

13:02 raek: then the *user* of the lib could be responsible for choosing his own nil-sentinel-value

13:02 that makes more sense

13:03 Kaali: Yeah, a user-based workaround for a rare problem.

13:03 rhudson: jli, it seems to be partly a matter of temperament and taste. It's always a little embarrassing to find something in initial testing that a type system would have caught. But my experience is that very very few lingering bugs in dynlang code I've written are things that a stronger type system would have pointed out.

13:04 raek: or, the validator could take a error-value parameter

13:04 that it returns if it didn't validate

13:04 well, no reason to change the lib yet

13:04 jli: rhudson: I think the advantage of strong typing is much stronger when you have a huge code base. the compiler/type system does its error checking over the whole world every time you compile. it's kind of scary to me that you can have obvious bugs in dynamic code that you don't know about just because it's down a code path that is rarely used

13:05 Kaali: raek: If the library gets users, I guess the feedback will say if this problem needs a solution.

13:05 raek: exactly

13:07 the required validator is not invoked if the map doesn't containt the key

13:07 maybe you should iterate over the keys of the validators, instead of the keys of the map

13:08 Kaali: Ah, that's true.

13:09 Could you explain the suggestion?

13:11 rhudson: jli, I won't really argue that point, except to say that I've seen people get a false sense of security on big code bases because it all compiles. :)

13:11 I do have a sense that Clojure 1.2's protocols and datatypes will help in large code bases. "Types when you need them."

13:13 Kaali: It's true that required validator is more like not-empty validator right now. My first hunch would be to fetch the fields and give a default value of nil for the missing fields. This would force the validator evaluation, but this would require some way to short-circuit the validators for optional but nil values.

13:13 jli: rhudson: yeah, it can absolutely deceive you, like with polymorphic functions in OCaml like compare and equal. Haskell does this better, with its typeclasses, but there are certainly still lots of bugs that aren't catchable with type systems

13:15 raek: the input-map might be {:foo ...} and the validator map {:foo ...., :bar ...}

13:17 (for [[k validator] validators :let [input (get input-map k)]] (...))

13:18 currently it works something like this

13:18 (for [[k innput] input-map :let [validator (get validators k)]] (...))

13:18 where (...) would be "run validator for value"

13:21 Kaali: raek: Could you show that as you would use it with defform as an user?

13:23 raek: (defform foo :a [[required "a is required"]]) (foo {}) => {:errors {}, :values {}}

13:24 it should be {:errors {:a "a is required"}, :values {}}, right?

13:24 foo does not do validation for :a, since it's not in the map it gets passed

13:25 Kaali: I understood the problem, but not the solution yet. BTW. I really love your feedback.

13:26 I fixed the inner vector syntax and will push the change soon.

13:26 raek: the solution would be to map over the validators, rather than the params

13:27 Kaali: Pushed.

13:27 Ah, I'll try that. Thanks.

13:28 raek: food. bbl.

13:30 Kaali: I joined #pour, maybe we could move dev talk there

13:36 dysinger: test

13:37 irssi!!11 seems emacs rcirc is the only thing working for me right now.

13:39 I'm sure everybody knows that we are hiring at Sonian. We currently considering #8, #9 & #10 on our full time work-at-home clojure team. It's all backend/bus work, rest apis, r&d, etc. Fun stuff.

13:40 If you like contact me offline on irc, skype (tim.dysinger) or jobs@sonian.net

13:42 KirinDave: dysinger: Speaking of that, sorry I didn't get in touch earlier.

13:43 dysinger: np :) I'm saving you a spot

13:43 KirinDave: dysinger: With this wedding coming up I've been super busy with minutiae.

13:54 raek: ...now, how do I change Github's interface back to English?

13:57 oh, links at the footer of the page...

13:57 "Forkar hårt och länge"...

14:09 TakeV: Is there a way to call Clojure files as scripts in Java?

14:13 dysinger: clojure.main is java

14:13 grab the source and figure it out :)

14:15 qbg: I believe there are some methods that let you do that in clojure.lang.RT

14:15 rhudson: TakeV: One way is an implementation of javax.script interfaces ScriptEngine{,Factory}. (also known as "JSR-223". ScriptEngine provides facilities to bind variables on the Java side and retrieve the results. I've seen a couple of implementations around github etc.; dunno if they're current

14:17 qbg: loadResourceScript in clojure.lang.RT looks useful

14:23 akhudek: is there anything like swap!, but that does not use apply?

14:24 i.e. just does (f old-atom-value)?

14:24 qbg: What is wrong with swap!?

14:25 akhudek: I have a record in there

14:25 and by using apply, it forces me to destructure the record, no?

14:26 qbg: No

14:26 ,(doc swap!)

14:26 clojurebot: "([atom f] [atom f x] [atom f x y] [atom f x y & args]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in."

14:26 akhudek: right, so if you do (apply (fn [x] x) {:a 1 :b 1})

14:26 you get a wrong number of args error

14:26 qbg: (swap! atom f) does (f current-atom-value)

14:27 ,(apply (fn [x] x) {:a 1 :b 1} [])

14:27 clojurebot: {:a 1, :b 1}

14:27 raek: (swap! atom f a b c) does (f current-atom-value a b c)

14:28 (apply f a b c args) is like (apply f (concat [a b c] args))

14:28 qbg: ,(let [a (atom 0)] (swap! a inc) @a)

14:28 clojurebot: 1

14:28 qbg: ,(apply inc 1)

14:28 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

14:28 qbg: ^ Proof that it will not destructure the atom's contents

14:30 raek: akhudek: the last arg of apply is a sequence of the arguments to pass to the function

14:30 (apply (fn [x] x) [{:a 1 :b 1}])

14:30 then the map is the first argument, and gets bound to x

14:32 akhudek: hmm, ok let me look at this further, maybe I've done something odd

14:39 yes, the problem was that I and blind to typos

14:39 excellent

14:40 am blind even

14:40 rhudson: case in point :)

14:49 mcav: ,(map :out [(clojure.java.shell/sh "echo" "\u0169")

14:49 (clojure.java.shell/sh "echo" "\u0169" :in-enc "UTF-8" :out-enc "UTF-8")])

14:49 clojurebot: EOF while reading

14:49 mcav: (map :out [(clojure.java.shell/sh "echo" "\u0169") (clojure.java.shell/sh "echo" "\u0169" :in-enc "UTF-8" :out-enc "UTF-8")])

14:49 ,(map :out [(clojure.java.shell/sh "echo" "\u0169") (clojure.java.shell/sh "echo" "\u0169" :in-enc "UTF-8" :out-enc "UTF-8")])

14:49 clojurebot: java.security.AccessControlException: access denied (java.io.FilePermission <<ALL FILES>> execute)

14:51 mcav: I might be mistaken, but I don't think clojure.java.shell/sh defaults to UTF-8, though the docs say it does

14:52 akhudek: it did not as of a few weeks ago

14:53 mcav: looks like there were commits on July 7th or so, changing the docs to say it does, but I don't think that encoding change was actually made

14:54 akhudek: change line 96 to: (with-open [osw (OutputStreamWriter. (.getOutputStream proc) "UTF-8")]

14:56 I think only the coverting of the shells *output* defaults to UTF

14:58 mcav: it's line 122 in the master branch

14:58 http://github.com/clojure/clojure/blob/master/src/clj/clojure/java/shell.clj

14:58 in-enc is nil by default

15:09 jli: is there a standard sum function, like #(reduce + %) ?

15:09 zooG: grr i'm trying to install the Enclojure plugin on Netbeans, its telling me i need all these updates to the Ant, the Search API, etc. But there's no updates for them.

15:09 akhudek: jli: (apply + [1 2 3 4])

15:09 jli: zooG: I saw that too, when I installed netbeans through debian. it's because the debian package was really old - worked when I installed from the netbeans site

15:10 akhudek: right, but I'm asking if sum already exists. I guess not.

15:10 I don't want to say "+"

15:11 akhudek: oh, I don't think so, no

15:11 jli: okay, thanks

15:11 I guess the apply is better than reduce though.

15:12 zooG: jli is it compatible with 6.9 yet?

15:13 or do i have to find the 6.8 on the siet?

15:13 *site

15:13 akhudek: it works with 6.9

15:13 jli: I thought it worked with 6.9 just fine

15:15 zooG: ok cool

15:24 qed: Hello all

15:25 jli: I'd like to write (fn [x] [x (* x 2)]), a function that takes a number and returns a pair of the number with its double

15:26 when I do #([% (* % 2)]), I get java.lang.IllegalArgumentException: Wrong number of args (0) passed to: PersistentVector

15:26 mefesto: jli: try #(vector % (* % 2))

15:27 jli: hm, #(vec [% (* % 2]) seems to work

15:27 mefesto: that too. can you explain why?

15:27 lpetit: jli:

15:27 ,(macroexpand-1 '#([]))

15:27 clojurebot: (fn* [] ([]))

15:28 lpetit: jli: see, the vector is placed in call position

15:28 jli: huh. not sure I understand what's going on there

15:28 lpetit: ,(macroexpand-1 '#(+ 1 2))

15:28 clojurebot: (fn* [] (+ 1 2))

15:29 lpetit: jli: what you place in the first position inside will be what gets called by the function

15:29 jli: oh, I guess I don't understand the #() macro then

15:30 yeah, okay. I sort of understand I think

15:30 mefesto: jli: the resulting code was ([])

15:31 jli: so it's attempting to call that vector as a function, but when you do that a vector needs a parameter indicating the index

15:31 ,([1 2] 0)

15:31 clojurebot: 1

15:31 jli: I see. I guess the problem is that [1 2 3] is a literal vector, but ([1 2 3]) is a function call, because vectors are functions of indices, right?

15:31 okay. I think I got it.

15:31 mefesto: yeah

15:32 jli: cool, thanks mefesto

15:34 Lajla: ,

15:34 clojurebot: Lajla: Excuse me?

15:37 lpetit: hi emacs paredit.el users. I've a question for you

15:38 qed: My reply will be slow I'm on a phone. Shoot.

15:38 lpetit: Is there so emacs user here willing to help a poor eclipse dev ? :)

15:39 everybody has already switched to enclojure ? :)

15:39 qed: With?

15:39 Never!

15:39 lpetit: Given the following text in the buffer (no more no less), and the cursor represented by the pipe

15:40 "[foo (bar [baz {bleh |blah}))]"

15:40 qed: Yessir

15:40 lpetit: If you hit the closing square bracket key : ] , what do you get ?

15:40 (assuming that paredit is installed, and paredit close square bracket is enabled)

15:40 ?

15:41 qed: Erm you're not allowed to be unbalanced

15:41 It would already be there

15:42 But if for some reason you were unbalanced it would just yield a single ]

15:42 raek: paredit-mode won't activate since they're unbalanced

15:42 qed: raek: it's possible to delete a bracket though

15:43 raek: I see

15:43 qed: You can't open anything new, but you can fix it

15:43 lpetit: qed: the question is already ^^^ what behavior ? inserts the ] ? jumps somewhere ? does nothing ?

15:43 raek: paredit will close with the "right" parent, no matter which one you try to write

15:45 lpetit: qed: I guessed this one. Now please, assume paredit.el is smarter than today, and that unbalanced things are not a problem. Which behaviour would you like in this precise case ? I have 2 interesting ideas:

15:45 qed: 1. jump to the end of the string, just after the closing square bracket

15:46 qed: I sort of like my paredit stupid tbqh

15:46 lpetit: qed: 1. would then become "[foo (bar [baz {bleh blah}))]|"

15:47 qed: What's w?

15:47 2*

15:47 lpetit: qed: 2. localise the first enclosing ([ <whatever but not ]>) pair, and insert ] just before the wrong <whatever but not ]> bracket

15:48 qed: 2. would then become "[foo (bar [baz {bleh blah}]|))]"

15:48 qed: I'd pick 1, but not being allowed to be unbalanced is why paredit is great I think.

15:49 I think you should only be able to fix a balance issue in general

15:49 But not allowing that to happen in the first place is central

15:51 lpetit: qed: sure, not arguing against that

15:51 qed: lpetit: do you see what I mean?

15:51 lpetit: qed: maybe not :/

15:52 qed: Okay then without a doubt I choose #1

15:52 Why would you not already have a closing bracket in your example?

15:52 What scenario would allow that?

15:53 lpetit: qed: degraded mode

15:53 qed: Elaborate please?

15:54 lpetit: paredit is black / white. It does not have to remain black/white forever. At least not my paredit.clj :p

15:55 qed: When I use an editor that matches pairs but let's you be unbalanced I'm annoyed.

15:55 Fwiw

15:56 mmarczyk: same here

15:56 qed: I'm not saying I wouldn't use your version and give it a fair shake, but black/white is sort of the point for me

15:56 lpetit: I'm currently enhancing my clojure grammar so that even not-well balanced things get you some behaviour. E.g. if you have "([)]" it's analysed as two nested "weird" (chimera) forms. You can stil use the form selection commands on it, it parses correctly so you still have correct auto-indentation ...

15:57 qed: But why? That's not valid clojure.

15:57 lpetit: I would rather think that every people gets used to the behavior his favorite tool gives him.

15:57 mmarczyk: that sounds technically interesting

15:58 lpetit: Some people not always have valid clojure code "every time".

15:58 mmarczyk: but I'm not clear on the meaning of "correct auto-indentation" where incorrect code is concerned

15:58 qed: Indeed

15:58 rhudson: fwiw, La Clojure lets you insert the ], but it then immediately red-marks all the unbalanced ) ] }

15:58 lpetit: Imagine a user that knows *nothing* about paredit. And does not want to activate it yet. I can disable the paredit commands that make paredit "weirdos" at first: open-round for example.

15:59 mmarczyk: some people use the black/white paredit and get at least the bracketing correct every time :-)

15:59 lpetit: So the person starts a new file, hits "(" => my new extended grammar parses this as a ["(" <eof>] form. And when the user hits <Enter>, he gets the correct auto-indentation behavior

15:59 qed: lpetit: If they don't like paredit, fuck em. lol

16:00 lpetit: qed: no, it's generally the contrary: it's paredit which f..ks them ! And they don't know how to get rid of it ! :)

16:00 mmarczyk: lpetit: that's what Vim does for me and I've written thousands upon thousands of lines of Scheme like that... sounds perfectly alright, but it's nothing to do with paredit, I think...?

16:00 lpetit: leaving them with a wrong impression of not controlling things anymore

16:01 qed: Paredit for me generally amounts to 2 commands

16:01 I'm no super user

16:01 mmarczyk: ah, I didn't really want to argue for paredit to be necessarily on by default, if that's what the conversation is about

16:01 rhudson: What does paredit do if you paste in something that's unbalanced?

16:01 qed: Freaks out

16:02 mmarczyk: rhudson: it throws a temper tantrum and expects you to fix it asap ;-)

16:02 rhudson: sounds ... unhelpful

16:02 qed: I disable the mode and fix it

16:02 Yeah you got me there

16:02 But usually it's just me pasting something from a non paredit user

16:02 Lol

16:03 mmarczyk: you can insert ([{""}]) wherever you want with C-q

16:03 when fixing a typo / paste error / etc.

16:04 qed: Yeah I know I'm lame in that respect but I haven't internalized bat one yet

16:04 I almost never need it

16:04 lpetit: hmmm, the fact is I'm partly focusing on this because I've implemented all paredit commands on top of the hypothesis that I have a parse tree. For example if at the end of the buffer there's a problem which makes the parser return no parse tree, it's currently impossible to have auto-indentation even between the first and second line

16:04 maybe this is a non problem in emacs

16:05 mmarczyk: well, if you want to sort of mark just part of a buffer unbalanced

16:05 and still auto-indent below it

16:05 then it's an interesting approach

16:06 I'd still want, at the very least, to have some sort of warning -- red curly underline or whatever -- to tell me I probably ought to fix my brackets

16:06 hiredman: hmm

16:07 qed: Same here

16:07 mmarczyk: but this sounds like it's about acting reasonably when paredit is disabled...

16:07 lpetit: yeah sure, it's part of the extension. I've a special parstree node for this: currently it's named :chimera :)

16:07 hiredman: I am sure someone must have mentioned paredit already

16:07 qed: lpetit: You might consider the response you get from #emacs?

16:07 lpetit: hiredman: jumping in the middle of the chat ? :-)

16:07 mmarczyk: hiredman: this is in fact a "paredit in ccw" conversation :-)

16:08 lpetit: hiredman: was joking . welcome ! :)

16:09 hiredman: does paredit in ccw let you enter unbalanced expressions?

16:09 lpetit: well, I was wrong in asking the question to users of paredit, since the problem almost never happens to them !

16:09 hiredman: copy/paste lets you easily enter unbalanced expressions in any editor I know of, ccw and emacs certainly being no exception

16:10 and yes, ccw has 2 "modes" for paredit, one mode that provides the commands which do not "get in the way" of new users

16:10 hiredman: well, thats why you copy and paste using C-k and C-y

16:10 and don't use a mouse

16:10 mmarczyk: lpetit: incidentally, if you enter a closing bracket in the middle of a bracketed expression, paredit will move the cursor past the closing bracket of this expression

16:10 lpetit: and bracket type mismatch doesn't matter here

16:11 lpetit: I know all that, that's what I've implementing in paredit.clj

16:11 mmarczyk: oh, alright :-)

16:11 lpetit: Nevermind

16:21 slyrus: paredit.clj?

16:21 oh, this is for eclipse?

16:26 lpetit: slyrus: among other candidate IDEs. paredit.clj is totally "headless" and "framework agnostic".

16:27 mmarczyk: lpetit: I like your multimethod-based design

16:28 lpetit: mmarczyk: Oh, you've looked the state of the code

16:28 * lpetit vanishes in the dark

16:29 mmarczyk: :-)

16:41 lpetit: for example with the new mode, "paredit expand left" works like this : "(foo bar|]" => Expand left command => "(foo |bar|]"

16:56 tomoj: why would you care what it does with "(foo bar]" ?

17:03 lpetit: why wouldn't you want it to be able to recognize bar and select it ? What if bar were a more complex expression, and you don't care for this malformed ] yet. Same if ] is the end of the line.

17:04 From the recent conversation in the ml post I started, there seems to be a lot of people who do not want to be restricted to working with always good looking code.

17:07 tomoj: but if you're using paredit mode, why do you have a malformed expression?

17:07 but yes, that is a good thing

17:08 paredit.clj?

17:08 never heard of it

17:09 it's a plugin?

17:09 oh you could use it from anywhere

17:10 I wonder how you would make an emacs implementation of that efficient

17:10 and whether it would it be OK to send the entire top-level form at point for every paredit command

17:20 lpetit: tomoj: I'm talking about it here and there, but not yet sufficiently "proud of it" to talk loudly about it

17:23 rhall: hi, anyone around?

17:23 Hi rhudson

17:24 it's really quiet in here

17:24 rhudson: hi rhall

17:24 rhall: I'm trying to figure out debug-repl... have you ever used it?

17:25 rhudson: no, afraid not

17:25 LauJensen: rhall: debug-repl, is that what the poor kids without swank.core/break are using?

17:26 rhall: don't know, but being one of those poor kids you mention., I don't even *know* about swank.core :)

17:26 checking the goog now

17:26 izzit better?

17:27 hiredman: LauJensen: pretty sure those are the same thing

17:27 pabloh: can u do something similar to ruby's argument splating in clojure?

17:27 LauJensen: hiredman: They rely on the same tricks, yea, made by different people

17:27 rhall: check my latest blogpost, in the screencast near the end I show it off

17:28 rhall: ok, looks like debug-repl has been incorporated in swank.clojure

17:28 hiredman: I've never found either to be more useful then just logging/printing

17:30 rhall: hiredman: so far I've had mixed results with logging... still working on it

17:30 laujensen: where do you blog? I'm not finding it quickly

17:31 LauJensen: rhall: http://bestinclass.dk/index.clj/2010/07/trail-blazing-innovators.html

17:31 thats the latest post, back up to /blog.html for the rest

17:31 slyrus: is there an equivalent to the clhs: <cl identifier> supported by the bots in this channel? e.g.. clojure-api: extend-protocol

17:32 rhall: laujensen: thx... reading now

17:32 tomoj: (doc extend-protocol)

17:32 clojurebot: "([p & specs]); Useful when you want to provide several implementations of the same protocol all at once. Takes a single protocol and the implementation of that protocol for one or more types. Expands into calls to extend-type and extend-class: (extend-protocol Protocol ::AType (foo [x] ...) (bar [x y] ...) ::BType (foo [x] ...) (bar [x y] ...) AClass (foo [x] ...) (bar [x y] ...) nil (foo [x] ...) (bar [x y] ...)) expands

17:32 LauJensen: rhall: np

17:32 slyrus: tomoj: well, ok. I was hoping for a link to the web page, but that's nice-ish. thanks.

17:33 tomoj: don't you have a repl?

17:33 maybe it should link to clojuredoc.org

17:33 raek: pabloh: apply

17:33 tomoj: clojuredocs.org I mean

17:34 raek: ,(apply concat 1 2 3 [4 5 6])

17:34 clojurebot: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

17:34 pabloh: raek: is not partial apply waht i'm tring to do

17:34 raek: ,(apply list 1 2 3 [4 5 6])

17:34 clojurebot: (1 2 3 4 5 6)

17:35 slyrus: tomoj: I was thinking the api docs referenced from clojure.org, but sure.

17:35 rhudson: So far the thing I like best about clojuredocs is the Clojure core quick ref. It's great to see the functions grouped together by topic.

17:35 raek: what does argument splatting do?

17:35 tomoj: real examples of use are always nice too

17:35 pabloh: raek: at ruby, if u have foo(a,b) u can do foo(*[a,b]) and have the same effect

17:35 tomoj: especially for things like ns I bet

17:36 raek: (foo a b) and (apply foo [a b]) is somewhat similar, but not what you are looking for?

17:37 they have the same effect and in the latter case you get the args as a collection

17:37 pabloh: raek: humm, i think u're corrent

17:37 correct*ç

17:38 raek: all arguments between the function and the arg-list are unsplatted

17:38 like in the list example

17:39 krunaldo: (create-ns 'test) (ns 'test) leads to java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:2)

17:39 What am I missing?

17:39 ah

17:39 'test should be test :)

17:40 raek: ns creates the namespace if it doesn't exist already

17:40 it is a macro, unlike the other ns functions

17:41 krunaldo: yeah, I wasn't supposed to give it a symbol :)

17:42 I guess it macros it into a symbol somewhere down the road

17:42 hiredman: it is a symbol

17:43 test is a symbol, 'test is a quoted symbol

17:43 'test is expanded by the reader to (quote test)

17:43 which is the list mentioned in the exception

17:43 raek: macros gets their args unevaluated

17:44 krunaldo: Ah, cool!

17:44 I coded some common lisp way back in 2004-2005 never really got the hang of macros back then :)

17:44 as in how to use them not how extremely useful and cool they are

17:45 pabloh: raek: what does apply do at that context?

17:46 raek: it return an anonymous function?

17:46 raek: no, it invokes the function

17:47 applies it

17:47 pabloh: its like, call this function with the paramters on this vector?

17:47 raek: yes

17:47 (apply f args) = call f with args

17:48 pabloh: ok, does it takes only 2 parameters?

17:48 raek: (apply f a b c args) = (apply f (concat [a b c] args)) ; a convenience extra

17:48 it can take more

17:48 that is a convenience feature

17:49 they can always be rewritten into the 2-parameter form

17:49 pabloh: ok i got

17:49 it

17:49 raek, the last argument *can* be a vector ?

17:49 * slyrus keeps forgetting that defun is spelled defn in this lispish

17:50 raek: the last element must be sequable

17:50 rhudson: "Clojurians have more fn"

17:50 pabloh: raek: ok

17:50 raek: that is, you should be able to call seq on it and get a sequence

17:51 ,(seq [1 2 3])

17:51 clojurebot: (1 2 3)

17:51 raek: ,(seq 1)

17:51 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

17:51 pabloh: ok

17:51 raek: so you can't do (apply f 1)

17:53 pabloh: raek: so is only a convience way, for the sake of clojure's conventions?

17:53 raek: the arity of apply

17:53 raek: yes

17:53 exactly

17:53 pabloh: ok, i got it, thx a lot!

18:00 rhall: anyone got any thoughts on why swank.core/break shows "No Locals"? I've searched through clojure-log and found that I need to upgrade to 1.2.0 and clojure mast and contrib... did that... still "No Locals"

18:01 neither slime-connect (using lein swank) nor swank-cloure-project show local

18:08 tomoj: I think you have to get the right frame

18:08 what does your attempt look like

18:09 rhall: I get the usual slime debug backtrace...

18:09 0: user$eval__2351.invoke(NO_SOURCE_FILE:1)

18:09 I hit enter or "t" on that and it explands but says [No Locals]

18:10 I'm using LauJensens screencast example

18:10 the backtrace looks pretty similar

18:10 except his has locals :)

18:33 tomoj: weird

18:33 rhall: what swank-clojure version?

18:36 rhall: 1.2.1

18:36 tomoj: maybe try 1.3.0-SNAPSHOT

18:37 rhall: ok, thx.. trying now

18:40 no better, but I get this message when I start "slime-connect" -> Versions differ: 20100404 (slime) vs. nil (swank). Continue? (y or n)

18:40 wonder what that means

18:40 slyrus: mmarczyk: there's a new shortcut that cleans things up a bit and adds some functions for paritioning/connected-components

18:40 and I finally bit the bullet and decided that molecules _aren't_ graphs, but rather contain a graph. made that code a bit simpler.

18:41 tomoj: hmm

18:41 rhall: what version of slime?

18:42 20100404 from ELPA?

18:43 rhall: yes, exactly

18:43 tomoj: dunno what to say.. I have the same

18:43 rhall: ah... maybe this is the problem

18:44 elpa has swank-clojure 1.1.0 installed slime adapter for clojure

18:44 but I have 1.3.0-SNAPSHOT in lein

18:44 wonder which one is winning

18:44 tomoj: swank-clojure from ELPA is sort of deprecated

18:44 I don't use any emacs swank-clojure package

18:44 mmarczyk: slyrus: greats, thanks! will look at all that soonish :-)

18:44 tomoj: rhall: lib look like this? https://gist.github.com/ca7eee970e9c0400d4f4

18:45 rhall: I'm guessing the elpa one is active:

18:45 swank-clojure-deps is a variable defined in `swank-clojure.el'.

18:45 Its value is

18:45 ("http://repo.technomancy.us/swank-clojure-1.1.0.jar" "http://build.clojure.org/snapshots/org/clojure/clojure/1.1.0-master-SNAPSHOT/clojure-1.1.0-master-20091202.150145-1.jar" "http://build.clojure.org/snapshots/org/clojure/clojure-contrib/1.1.0-master-SNAPSHOT/clojure-contrib-1.1.0-master-20091212.205045-1.jar&quot;)


18:45 let me remove it

18:45 tomoj: wonder how you can unload it without restarting emacs

18:46 `M-x unload-feature swank-clojure` maybe

18:46 technomancy: swank-clojure.el is just about launching swank servers; it shouldn't affect swank's break feature at all

18:47 tomoj: shucks

18:47 rhall: good question... not sure I can... I'll restart... back in a sec (I'm using erc)

18:47 tomoj: oh well :(

18:49 mmarczyk: technomancy: http://github.com/technomancy/leiningen/commit/c8ce3cd014c8ab3732af4fc90ee3ee9260f3abed commit message seems to explain the intent behind the funky stuff in uberjar to a certain extent... more importantly, it made me check lein's own standalone jar and, surely enough, it does contain a non-empty components.xml

18:50 rhall: tomoj: same issue... strange

18:50 tomoj: technomancy pointed out that swank-clojure.el doesn't affect swank.core/break

18:50 maybe check your (System/getProperty "java.class.path")

18:50 for the right swank-clojure jar

18:51 good luck :(

18:53 qed: Evening all

18:55 rhall: hi qed

18:55 qed: Lo

18:58 nickik: Why does it not scho :pre and :post when you call meta on something?

18:59 qed: Because they aren't part of the meta fields iirc

18:59 They are conditions not meta

18:59 nickik: how can i print them?

19:00 qed: Use a let binding and return them as a map along with your result?

19:01 nickik: how do you mean that?

19:03 mmarczyk: a function with :pre and :post gets transformed to sth like (fn [& args] (assert pre1) ... (assert preM) (let [res (apply-the-actual-body-to args)] (assert post1) ... (assert postN) res))

19:04 so you can't print them

19:06 nickik: I just looked it up on clojure.org the map is metadata of the arg list

19:11 mmarczyk: oh, really? that's cool, thanks

19:13 nickik: The condition map may also be provided as metadata of the arglist.

19:13 i didnt say it right

19:16 mmarczyk: just checked (defn foo [...] {:pre ... :post ...} ...) ~> (-> #'foo meta :arglists first meta) and, surely enough, there's a symbolic representation of :pre and :post right there

19:16 awesome :-)

19:20 nickik: nice

19:20 why do you have to right #' ?

19:21 mmarczyk: the magic happens in clojure.core/sigs

19:22 well, there's a bug -- or at least I think it's a bug -- which prevents defn from transferring useful metadata to the function itself

19:23 I mean, the correct metadata is attached to the Var, but the function itself gets outdated metadata

19:23 I made a ticket for that ages ago on Assembla... could look for it

19:23 nickik: I have to try to add them like this (defn testtest (with-meta [n] {:pre (pos? n)}) (* n n))

19:23 mmarczyk: no, not at all

19:24 (defn testtest [n] {:pre [(post? n)] :post [(even? %)]} (* n n))

19:24 I mean, (pos? n)

19:25 in fact, you can't use with-meta, you'd have to use reader metadata: ^{...} [n]

19:26 nickik: intressting stuff

19:28 I'm trying some diffrent stuff in trammel so I need all infos on that pre post stuff

19:34 could i have a map with conditions and assign that somehow to a function?

19:42 bokeh: I've been pulling my hair last trying to import a Javax Sound nested class

19:42 mmarczyk: nickik: well, you could wrap your function in another function with the conditions in place

19:42 bokeh: Could someone please explain why this works: (import '(javax.sound.sampled.DataLine$DataLine.info))

19:43 mmarczyk: bokeh: does it really?

19:44 you don't need the quote (although it doesn't hurt anything)

19:44 but more importantly

19:44 bokeh: but not this: (ns (:import '(javax.sound.sampled.DataLine$DataLine.info))

19:44 ) or this: (ns hello (:gen-class) (javax.sound.sampled DataLine$DataLine.Info))

19:44 I know, I normally never use quote...

19:44 mmarczyk: well you need to get your capitalisation right in any case

19:45 I don't know if it's info or Info, so don't know which to choose, but presumably it should matter...

19:45 bokeh: I'm wondering if the .Info of the nested class name doesn't fool Clojure somehow

19:45 sorry, typing from memory here, it's .Info

19:46 mmarczyk: (import java.util.Map$Entry) works for me

19:47 now I can just say Map$Entry

19:47 dunno if you can shorten this further

19:47 bokeh: yeah, simple stuff works just fine, but try this: (import javax.sound.sampled.DataLine$DataLine.Info)

19:48 an official java nested class...

19:49 mmarczyk: ClassNotFoundException for me

19:49 I mean, without the import around it

19:50 where do you get it from?

19:50 bokeh: now delete the $DataLine.Info and the container class works fine

19:50 what do you mean?

19:50 it's a javax package

19:51 I'm wondering if it's a Clojure bug where the .Info throws off the reading of the class name...

19:53 dnolen_: lancepantz: what about a "bake eval", would make integration with TextMate easy

19:53 mmarczyk: bokeh: ah, shouldn't it be javax.sound.sampled.DataLine$Info ?

19:54 bokeh: God, I want to marry you mmarczyk :) You've found it!

19:55 mmarczyk: bokeh: I will carefully consider your proposal

19:55 ;-)

19:55 bokeh: The doc in Java calls the class DataLine.Info nested in DataLine... I'm a Java newbie, that was enough to fool me ... Thanks again man!

19:56 mmarczyk: np :-)

19:57 pabloh: what's the difference beetwen let and binding?

19:59 qbg: let is lexical, binding is dynamic

20:00 Also, the bindings bound by binding are mutable

20:01 nickik: if you let something its only inside your (let ...) with binding its also outside the (binding ...)

20:01 pabloh: qbg mmm, so if u make use of biding with the foo symbol, and call a function that asumes the existence of a foo symbol, it will use the definition given by binding?

20:01 nickik: i hope thats right

20:02 qbg: pabloh: As long as it has not been shadowed

20:02 pabloh: ...that asumes the existence of a global foo symbol...

20:03 qbg: shadowed by something like 'let', u mean?

20:03 qbg: Correct

20:04 pabloh: ok, i've been told, that dynamic scoping is evil :P

20:04 qbg: ,(let [a (fn [] +)] (binding [+ 5] (a)))

20:04 clojurebot: 5

20:04 pabloh: qbg: are there some correct use cases for this?

20:08 hiredman: binding is also threadlocal

20:09 nickik: we set some global variabls with binding

20:09 thread local

20:10 qbg: You shouldn't need to use binding very much

20:10 pabloh: o

20:10 ok

20:12 qbg: Functions that use dynamically bound variables are not referentially pure, and so are not functions in the mathematical sense

20:14 pabloh: qbg: is that the same case as using set! ?

20:14 regarding referential purity?

20:15 nickik: yes

21:14 daaku: is there a way to reference the key and value using %1 %2 in a #(..) when reducing a map?

21:16 ah, i see. i need fn

21:16 hate it when i answer my own question in 2 minutes

21:21 rhall: off the wall question... anyone know how to search for a unicode character inside a file using emacs?

21:22 I'm getting this error: An invalid XML character (Unicode: 0xdbc0) was found in the comment.



21:22 using clojure.xml

21:22 and I just can't see it

21:25 daaku: rhall: xmllint?

21:25 donno if it checks for unicode errors

21:25 rhall: thx... checking

21:26 looks like it just does dtd validation more...

21:27 I can't see why "parse" cares what's inside the comments anyway

23:16 joubert: hello

23:16 does anybody here use clojure-couchdb from the-kenny?

23:16 (http://github.com/the-kenny/clojure-couchdb)

Logging service provided by n01se.net