#clojure log - Nov 23 2010

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

0:00 Licenser: compojure is the closest to that I think but I'm not sure

0:01 I use rack there but it does not make much just translates the requests into a hashmap and retranslates a result hashmap to a html response

0:02 trybeingarun: actually the way things work in my company is weird. If i get a few devs interested in clojure and we showcase some decent project then it becomes management's responsibility to bring new projects in that technology to the devs

0:02 dnolen: amalloy: I agree w/ the great way it present the basics.

0:03 Licenser: heh that is cool

0:03 I'm kind of lucky that I'm not a dev so I have realtively much freedome what to use if I have the chance to code once in a while

0:04 trybeingarun: yep. The downside is that each dev will have his own preference and it would be difficult to convince people :)

0:04 dnolen: trybeingarun: I've heard only good things to HTDP. But it's not nearly as broad in scope as SICP from the looks of it, much more "obviously" practical

0:04 Licenser: heh

0:05 well talking about work, I got to run, time to work :) take care people and don't get eaten by the flying spagetti monster!

0:05 trybeingarun: dnolen: at least the book doesn't seem threatening from its looks (unlike SCIP)

0:05 c ya l8r!

0:06 dnolen: trybeingarun: good point. Can't say much bad about a book authored by Felleisen and Krishnamurthi either.

0:08 trybeingarun: still that's introductory text to programming in general as well - seems like a lack of things in the middle ... Land of Lisp ? :)

0:08 trybeingarun: but there are not many reviews in Amazon

0:10 am new to lisp/clojure. I have that book (Land of Lisp). Have to read it some time

0:10 From the looks of it LoL seems to be a very funny/entertaining book

0:11 I'll find out some time whether it really packs the punch

0:11 tomoj: the music video was hilarious but also terrible

0:12 trybeingarun: tomoj: which video?

0:14 tomoj: I'll find it

0:14 dnolen: trybeingarun: did you already look at Joy of Clojure ?

0:14 tomoj: http://www.youtube.com/watch?v=HM1Zb3xmvMc

0:14 trybeingarun: nope. So far I have gone through only 2 texts on clojure, programming clojure and practical clojure

0:15 Programming clojure is my favorite among these two

0:15 I also went through "The little schemer" which is very good imho

0:16 dnolen: trybeingarun: Little Schemer rocks

0:16 the ultimate first programming book IMO. You don't even need a computer.

0:25 trybeingarun: tomoj: too good. Really funny :)

0:34 LauJensen: Morning!

0:35 joshua__: In case anyone was wondering putting (setq default-frame-alist `((width . 80) (height . 30))) into my .emacs fixed the problem. Good morning LauJensen, thanks for the advice on Enlive.

0:35 LauJensen: np :)

0:36 joshua__: Such a clever approach to templating, it might actually be getting me a job too. I was talking to someone about it and they might be having me do some scraping for them. They're not really technical so they don't know how to do it themselves.

0:51 ossareh: joshua__: snatch that money, homie! (/me goes back to proper english)

0:53 LauJensen: joshua__: Yea, I remember telling Christophe (the author) that if he didn't make a load of money on Enlive, that I would :)

3:16 samx: With multimethods, what happens if you define instances of the method in multiple different source files / namespaces.. And then, when using them in two other namespaces, in one usage you only require one of the namespaces defining the instances, while in the other you require both the namespace.. Will the two namespaces I'm using them from have different sets of instance methods, or the same set of instance methods ? Is defining the instance

3:16 methods in more than one file just a really "bad thing" to do?

3:19 raek: you can have implementations in multiple namespaces

3:20 however, make sure that you don't redefine the method for a certain dispatch value

3:22 you have to make sure that the namespaces with the implementations use the same namespace with the defmulti

3:24 samx: right.. not quite what I was asking though.. that is, lets say namespace NS1 defines the multimethod MM, and instances MMA and MMB.. NS2 defines instance MMC.. In NS3, I require NS1, but not NS2.. I'm assuming I'd only see instances MMA and MMB then.. In NS4, I require NS1 and NS2. I'd assume the method would then have MMA, MMB and MMC.. But would me doing thing in NS4 also affect the multimethod usages in NS3 to contain MMC ?

3:25 raek: yes

3:27 samx: cool.. thanks

3:28 raek: (assuming that NS2 calls (defmethod MM ...) where MM is the var that NS1 defines)

3:28 i.e. (ns NS2 (:use [NS1 :only (MM)])) (defmethod MM MMC ...)

3:28 samx: yeah, that's what i meant with the 'instances'

5:32 jonaskoelker: Hi all. I have an object I want to thread through a bunch of function calls; I can best describe the sequence of function calls by some nested loops of [apply f to object, i, j, ...]. I try to write this in terms of reduce but my code is a mess...

5:32 What's a poor lisp/clojure newbie to do?

5:46 trybeingarun: jonaskoelker: I dont get what you are trying to do.. what are i, j ...?

5:46 btw I too am a newbie. Can't guarantee I will be able to answer your question

5:48 jonaskoelker: I'm basically trying to translate some python (with braces indicating indentation/nesting): foo = some_object(); for i in ...: { massage(foo, i); for j in ...: massage(foo, i, j) } return foo

5:49 shachaf: jonaskoelker: For a nested loop like that (a cartesian product) a list comprehension of some sort might make more sense.

5:49 * shachaf has no idea if Clojure has those, actually.

5:49 shachaf: I only saw a reference to it somewhere once. Ignore that.

5:49 jonaskoelker: shachaf: I'm trying to compute the final version of foo, not the list of (i, j) pairs...

5:50 shachaf: jonaskoelker: Can you give a little more context?

5:51 mrBliss: maybe this is what you look for: http://clojuredocs.org/clojure_core/clojure.core/for

6:04 jonaskoelker: mrBliss: no, not exactly: I don't want a bunch of lists; I want the result of composing f length-of-the-lists times with itself, applied to my object foo

6:05 mrBliss: `for' would be what I wanted if I could make an assigment to a global variable inside the loop

6:06 something like this: http://pastebin.com/YdxyyDZX

6:34 vedang: I'm seeing some weird behavior in slime-who-calls..

6:34 it works in some cases and throws an error in other cases..

6:36 this error to be precise:

6:36 Debugger entered--Lisp error: (wrong-type-argument char-or-string-p nil)

6:38 Could someone please shed some light on this, is this behavior expected/documented? Am I missing anything? I'm using the latest versions of technomancy's clojure-mode and swank-clojure from github..

7:00 islon: can I easily serialize a record (read-string (pr-str myrecord))?

7:06 AWizzArd: islon: no

7:06 What happened when you tried this?

7:07 islon: java.lang.Exception: No dispatch macro for: :

7:07 any sugestions?

7:14 raek: jonaskoelker: maybe something like (nth (iterate f foo) n)

7:14 jonaskoelker: raek: not exactly (I think); the parameters to f vary from call to call

7:14 raek: i see.

7:14 jonaskoelker: anyways, I have my problem solved with a macro defining a new kind of loop

7:15 raek: jonaskoelker: also, ` ("syntax-quote") has a gensym feature built into it. just write seq# and ret#

7:15 `(let [x# 1] (inc x))

7:16 ,`(let [x# 1] (inc x))

7:16 clojurebot: (clojure.core/let [x__394__auto__ 1] (clojure.core/inc sandbox/x))

7:16 raek: (the last one should be a x# too, of course...)

7:16 jonaskoelker: neat :)

7:17 raek: ,((resolve (symbol "eval")) '(ns-unmap 'sandbox 'x))

7:17 clojurebot: nil

7:17 raek: maybe you could use reduce in some way

7:18 * raek reads what jonaskoelker has said previously

7:19 jonaskoelker: :) // yeah, reduce seems obvious but it makes a mess in my code and makes my head explode

7:19 raek: can you give an example of some input data you have and the desured output data?

7:20 or what you are trying to accomplish in a wider sense

7:35 AWizzArd: ~seen rhickey

7:35 clojurebot: rhickey was last seen joining #clojure, 1450 minutes ago

8:14 raek: ,(read-string "010")

8:14 clojurebot: 8

8:19 jweiss_: is there an easier way to get the name of a var, #'user/myfn to "myfn", other than using str and then chopping up the string?

8:20 MayDaniel: ,(str (name (:meta (var reduce))))

8:20 clojurebot: java.lang.NullPointerException

8:20 MayDaniel: jwiss_: ^

8:22 jweiss_: that didn't work for me :)

8:23 ,(str (:name (:meta (var reduce))))

8:23 clojurebot: ""

8:23 jweiss_: ,(str (:name (meta (var reduce))))

8:23 clojurebot: "reduce"

8:23 jweiss_: there we go :)

8:33 if my macro is going to generate a defn with metadata, can it just spit out the reader macro ^ ? or do i have to use with-meta somehow

8:34 actually my macro is creating a gen-class call and pulling the metadata from the fn and adding it as annotations on the method in the gen-class

8:34 but same concept

9:37 neotyk: Good afternoon!

9:38 Innar: Hello hello

9:38 jaley: hi guys. am I right in thinking that conj'ing vectors won't reorder them?

9:39 chouser: conj'ing an item onto a vector "adds" it to the right-hand end, disturbing nothing else.

9:39 neotyk: what would reorder vector?

9:39 jaley: chouser: cool. but that's not true of a list, right?

9:39 chouser: conj'ing on a list "adds" to the left-hand end, disturbing nothing else

9:40 jaley: chouser: ahhh makes sense. so, I'd like to add to the right using butlast, which seems to return a list when you pass it a vector, thus i'm getting the opposite of what i want :s is there an alternative?

9:41 chouser: use 'pop' to take things off the right end of a vector

9:41 ,(pop [1 2 3 4 5])

9:41 clojurebot: [1 2 3 4]

9:41 jaley: chouser: perfect. thanks!

9:41 chouser: ,(-> [1 2 3 4 5] pop (conj 42))

9:41 clojurebot: [1 2 3 4 42]

9:41 jaley: chouser: cheers, that's exactly what i wanted

9:43 neotyk: are you guys able to work with clj-sys packages?

10:08 trybeingarun: hello guys!

10:13 islon: does anyone know how can I serialize and deserialize records?

10:16 trybeingarun: to write it to a file: (spit filename (pr-str object)))

10:16 Read from file: (read-string (slurp filename)))

10:16 islon: it doesn't work with records

10:16 trybeingarun: This is where I got it from. http://thinkrelevance.com/blog/2008/09/16/pcl-clojure-chapter-3.html

10:17 AWizzArd: islon: you can do this by overwriting the print method for your specific record.

10:18 Chousuke: print/read is not a very good method of serialisation.

10:18 islon: specialy with records

10:18 Chousuke: with anything, really

10:18 it only works if you have reasonably simple data.

10:18 islon: indeed

10:19 i think i'll have to use basic java object serialization

10:21 AWizzArd: When you have (defrecord Foo [x y]) then you could (defmethod print-dup Foo [f, ^java.io.Writer w] (.write w (format "(Foo. %d %d)" (:x f) (:y f))))

10:21 Now (binding [*print-dup* true] (print (Foo. 10 20 ))) prints it in a way in which it can be read back.

10:21 jweiss_: in a syntax quote form, can i avoid a symbol being namespace qualified (just output the symbol without ns) ?

10:21 islon: this is a kind of externalization

10:22 MayDaniel: jweiss_: ~'foo

10:22 chouser: jweiss_: yes, but usually the desire to do so is misplaced.

10:23 AWizzArd: ,`(~'x)

10:23 clojurebot: (x)

10:23 AWizzArd: It can be useful if you expand into a defn for example and want to offer the caller a sane preview in Emacs.

10:24 jweiss_: chouser: my overall goal for this macro is to let me put java annotations in metadata on my defn, not in the gen-class call. so the macro will put them there for me. :methods [[mymethod [] void]] <- mymethod shouldn't have a namespace, right?

10:24 AWizzArd: He wants to see that the function takes [x y] so you can expand into [~'x ~'y]

10:25 chouser: jweiss_: did you know that you can replace the body of a gen-class method at run time?

10:26 this is part of why the the entire spec of the class is given in the gen-class form, rather than picking up type hints etc. from the functions or vars and applying them to the class

10:27 jweiss_: chouser: hm, i see usefulness there, but also still want to be able to specify java annotations in the defn :)

10:28 chouser: heh, ok.

10:29 jweiss_: chouser: is there an example somewhere of replacing the body of a gen-class method at runtime?

10:29 chouser: you can just re-run the (defn foo- ...), or change the .clj file that has those and re-load it

10:29 jweiss_: ah i see

10:30 chouser: and then all your existing instances of gen-class classes will behave the new way

10:31 jweiss_: chouser: ok, so my macro is not going to prevent me from doing that, it'll just make the java annotations fixed, which is ok with me

10:31 they're fixed anyway, right?

10:31 chouser: right

10:33 islon: how can I force clojure to evaluate a ratio? (/ 30 4) => 15/2

10:34 jarpiain: &(quot 30 4)

10:34 sexpbot: ⟹ 7

10:34 islon: thanks

10:34 jarpiain: &(double (/ 30 4))

10:34 sexpbot: ⟹ 7.5

10:34 trybeingarun: I was doing it like (int (/ 30 4))

10:34 islon: that's what I want

10:35 trybeingarun: *double* whatever :P

10:42 hugod: anyone else having issues with maven 3 trying to resolve clojure, and picking up org.clojure:clojure:jar:1.3.0-testbuild1-SNAPSHOT?

10:48 seems to happen with any dependency that transitively depends on an old snaphot, like autodoc or a version range, like moustache

10:53 stuartsierra: If you have Sonatype OSS snapshots as a repo it gets pulled in.

10:55 hugod: the failure I get is Failed to read artifact descriptor for org.clojure:clojure:jar:1.3.0-testbuild1-SNAPSHOT: Failure to find org.clojure:pom.baseline:pom:0.0.1 in http://oss.sonatype.org/content/repositories/snapshots

10:56 stuartsierra: hugod: I don't think this is specific to Maven 3

10:58 hugod: stuartsierra: I haven't tested with maven 2

10:59 stuartsierra: Solution for now is excluding those transitive dependencies.

10:59 testbuild1 isn't for general use

11:00 hugod: I realise that - just annoying that it keeps getting picked up

11:00 stuartsierra: I'll ask Chas if we can delete it from Sonatype's repo

11:01 hugod: stuartsierra: thanks - though I don't want to get in the way of you testing new builds

11:04 stuartsierra: Yeah, we needed to do that, just regret that it ended up affecting actual builds.

11:07 hugod: the vagaries of maven...

11:24 alpheus: I'm using clojure.contrib.shell-out/sh to create PNG using dot. If I have dot write to a file everything's fine. But if I store the output of shell-out/sh in a var the data seems to be corrupted. Any ideas?

11:38 dnolen: does it seem weird to anybody that satisfies? returns true even though the entire Protocol has not been implemented?

11:39 islon: clojure is easily satisfiable ;)

11:40 KirinDave: dnolen: I must have missed the first part?

11:41 dnolen: KirinDave: no that's the whole shebang there. If you extend a Protocol or reify you get a record/object that returns true for (satisfies? Protocol x), regardless of how much of the Protocol you actually implemented.

11:42 KirinDave: Ahh, I misread.

11:47 chouser: oh no, naked :use!

11:47 * chouser weeps

12:02 amalloy: chouser: (use 'misfeatures)

12:17 jweiss_: hm. i'm making a macro that expands into a call to gen-class, with the annotations for the methods put in place by the macro. I can't figure out whether i should have the macro produce a symbol with the metadata already on it, or just return a literal form (with-meta mysym {:annotx :valx}) ?

12:17 i tried the former but it doesn't seem to work. (and if anyone knows how to inspect class files for annotations, that'd help me a bunch. javap apparently doesn't do it)

12:19 raek: jweiss_: do you have a paste of you code?

12:19 jweiss_: raek: let me make a gist

12:20 rata_: hi

12:21 jweiss_: raek: https://gist.github.com/712134

12:21 djpowell: alpheus: if the output of the command is binary, then you probably want to call it as (sh :outenc :bytes "command")

12:21 jweiss_: raek: the macro is the important part, the fn's above are just for building the annotation metadata i want to add

12:22 djpowell: alpheus: otherwise you are going to get your PNG mushed into a string using some random character encoding. If you are storing binaries in strings in Java, then you are probably doing something wrong

12:22 s/outenc/out-enc

12:23 raek: jweiss_: btw, when writing map + anon fn, consider 'for'

12:23 jweiss_: raek: ok

12:24 rata_: is this a good construct to send a fn several times to an agent? (reduce #(send % f) agent (range n))

12:25 raek: rata_: (dotimes [_ n] (send agent f))

12:25 djpowell: alpheus: hmm, actually (sh "command" :out-enc :bytes)

12:26 raek: jweiss_: I can't see anything suspicious with it yet

12:26 jweiss_: raek: the issue is that it generates the classes ok, with the right methods, etc. but they don't appear to have any annotations

12:27 so i'm wondering if it's better to remove the unquote from (with-meta ... )

12:27 rata_: raek: so what send returns is just the same as the original agent?

12:27 * raek reads up on the annotations syntax for gen-class

12:28 raek: rata_: yes

12:28 rata_: thanks =)

12:32 jweiss_: raek: removing the unquote (and unquoting the forms inside with-meta instead) seems to generate ok looking code, but gen-class doesn't produce anything with it

12:33 maybe because it insists on actual symbols for a method, not a form that evaluates to one

12:33 raek: jweiss_: is an annotation attached by putting {AnnotationClass some-value} metadata on the mehtod name symbol?

12:33 jweiss_: raek: yup

12:34 raek: jweiss_: which one of the unquotes?

12:34 jweiss_: raek: line 15, right before with-meta

12:34 let me update the gist with the variation i just tried

12:35 done

12:36 it produces this: (clojure.core/gen-class :name test_clj.sample_tests :methods [[(clojure.core/with-meta config5 {org.testng.annotations.BeforeMethod {:groups []}}) [] void] etc

12:37 raek: what is config5 here?

12:38 jweiss_: raek: one of the fn's in the namespace i pass in. ie, (defn config5 [] etc etc)

12:38 raek: the nested `s is confusing me... :)

12:38 jweiss_: there's a nested `?

12:38 raek: that will take the value of config5, and attach the metadata to that

12:38 you first generate code in the let

12:39 and then insert it into another `-form

12:39 jweiss_: oh right

12:39 raek: well, maybe not nested...

12:39 jweiss_: yeah i see what you mean

12:39 raek: you could generate a quote around config5

12:40 jweiss_: ok, let me try that

12:41 raek: (clojure.core/gen-class :name test_clj.sample_tests :methods [[(clojure.core/with-meta (quote config5) {org.testng.annotations.BeforeMethod {:groups []}}) [] void] etc

12:41 that doesn't produce any classes either

12:44 rata_: what does it mean in the documentation of await that it "Will block on failed agents"? if there's a failed agent it will never return?

12:45 raek: jweiss_: what did the original version you gisted produce?

12:45 jweiss_: raek: (clojure.core/gen-class :name test_clj.sample_tests :methods [[config5 [] test-clj.meta/void] etc

12:46 i'm wondering whether config5 still has metadata on it

12:46 in that case

12:46 raek: do you have *print-meta* on?

12:46 jweiss_: raek: er, no, didn't know about that

12:48 raek: also, I think the void return type is handled incorrectly

12:48 it should be void instead of test-clj.meta/void

12:49 hrm, but you're already doing ~'void...

12:49 anyway, I have to go now. good luck!

12:49 jweiss_: raek: thanks for your help!

13:11 dnolen: interesting reify is one of the cases where you not care that much about "this". *also* a pretty amazing way to make some datatype become something else ...

13:12 chouser: right, reify almost always has everything you need in lexical context, so rarely need 'this'

13:22 raek: jweiss_: just realized something. check the class of the generated org.testng.annotations.BeforeMethod. is it a symbol or is it a _class_?

13:23 jweiss_: raek: i'm doing (.getAnnotations (.getMethod test_clj.sample_tests "config5" nil)) and it actually has the annotations

13:24 so either the version picked up by the repl is not the same as the class files on disk... or something i don't know what :)

13:24 i don't know how to check the files on disk

13:25 oh i think i know what's going on

13:26 * jweiss_ tries a test or two

13:27 dnolen: wow, 1.2.0 protocols+reify has some serious awesomeness consequences that I had not yet considered.

13:28 jweiss_: raek: yeah i think i got it, so far the expansion of the macro call works (if i paste the expansion in place of the call). so i think it works

13:29 or sorta, the macro itself still doesn't work :)

13:29 but i must be 99% of the way there

13:56 there's something weird going on - my macro takes a namespace as an argument. when i call (macroexpand-1'(mymac my.namespace)) it expands correctly. executing the expansion works. but (mymac my.namespace) doesn't work. is there some kind of quoting gotcha here?

14:07 dnolen: chouser: any thoughts about the nature of satisfies? that I brought up earlier?

14:09 chouser: dnolen: "meh" ...how's that for a thought?

14:10 dnolen: w/ current behavior it means that consumers must always provide all methods, as library designers can't check via satisfies?. I suppose consumers merge provided default impl fn map for things they don't intend to customize ?

14:10 chouser: as in you don't see it being much of an issue?

14:10 chouser: I haven't found a situation where using 'satisfies?' felt right.

14:11 dnolen: chouser: I agree, but then why is it there?

14:11 jweiss_: can i not refer to the current namespace with *ns* inside a macro?

14:12 i want to call a macro to do things with the ns-publics of the namespace i make the call from

14:14 kotarak: dnolen: why is map? there? or seq?? or integer?? or instance?? Because people want it.

14:15 dnolen: kotarak: have you looked at the Rx Observable protocol at all?

14:15 Observer I mean

14:15 kotarak: dnolen: no. :) Just saw your question why satifsfies? is there.

14:16 I missed the previous discussion. (if any)

14:16 dnolen: here's the gist of the problem, people want to observer something. They reify the Observer protocol to do so.

14:16 Observer protocol is (on-next [this v] ...) (on-error [this exc]) (on-complete [this ...])

14:17 chouser: dnolen: I think it may not be "correct" to extend a protocol without extending all methods.

14:17 stuartsierra: dnolen: I did a version of that in Clojure

14:17 dnolen: problem is, an Observer may only care about errors

14:17 stuartsierra: I know I was there at your talk.

14:17 stuartsierra: ah. :)

14:17 names, nicknames, faces, … all a big blur to me

14:18 dnolen: because of the nature of Protocols, reified instances of Observer must always provide everything, regardless of whether they only care about some specific methods of the Protocol.

14:18 kotarak: dnolen: then the observer should probably only have on-event and the actual observer filter out stuff, they don't want. Or the tell the Observee, that they only want certain events.

14:20 I had the case that I had instances which implemented only part of the protocol, other instance only other parts. And suddenly ... CLABANGO. I should have actually two different protocols because they were actually different things. And I was conflating stuff.

14:22 Oeh. btw. Can I put metadata on a Protocol? In particular {:added "<some-version>"}.

14:22 mduerksen: jweiss: i'm quite new to clojure, so i may be wrong, but AFAIK, you have to capture the ns at the time the macro is defined. like this: (defmacro some-macro [] (let [current-ns (ns-name *ns*)] ...

14:23 jweiss: and then, inside the macro, you can do (create-ns '~current-ns). but it could be that i made this too complicated

14:23 stuartsierra: kotarak: yes, protocols are Vars

14:24 jweiss_: mduerksen: maybe that's what i'm confused about. what is the purpose of ns-name, what are you supposed to pass to it?

14:24 seems like it takes a symbol and returns the same symbol.

14:25 stuartsierra: jweiss_: it takes a Namespace object

14:25 mduerksen: jweiss: ns-name takes a *real* namespace and return its name

14:25 as symbol

14:25 kotarak: hmmm... "Deprecating the Observer Pattern"

14:25 jweiss_: so, what does ns-publics take? seems to take symbols as well

14:26 stuartsierra: Most of the ns functions accept symbols and will call "the-ns" on them

14:26 dnolen: kotarak: exactly!

14:26 jweiss_: stuartsierra: mduerksen: thanks, that helps clear things up a bit

14:26 dnolen: he's critiquing complexing Observer/Observable interface points.

14:27 it should be absolutely minimal

14:27 that what Reactive Extensions are about

14:27 mduerksen: stuartsierra: thx for the-ns, everytime i'm here, i learn new useful functions :)

14:27 dnolen: a minimal Protocol means you can convert reliably convert all kinds of streams in to all kinds of events and all kinds of events into all kinds of streams

14:27 kotarak: dnolen: ah. Ok. I'm not up to date with this new stuff. I only know Clojure.

14:28 dnolen: subscribe, unsubscribe, on-event, on-error, on-complete is it basically.

14:29 stuartsierra: unsubscribe might be redundant

14:29 dnolen: Observers don't tell Observables to filter. an Observer *can* be a filter, for yet another Observer

14:30 kotarak: dnolen: seqs are everywhere

14:31 dnolen: kotarak: :)

14:32 kotarak: dnolen: well, that's it basically. A seq. Maybe in a different form than usual, so what?

14:33 dnolen: kotarak: converting side effects into streams, right? (map-events + side-effect-src1 side-effect-src2 side-effect-src3 ...)

14:34 kotarak: stuartsierra gave a great preso, are the slides somewhere? also https://github.com/stuartsierra/cljque

14:35 stuartsierra: slides at http://stuartsierra.com/download/2010-11-17-clojure-async.pdf

14:37 jweiss_: gen-class is killing me. it only does stuff at compile time, so i can't see what's going on. is there a way to at least get the macro expansion when the compiler hits it?

14:41 chouser: gen-class is pain

14:41 you could try faking it out by setting *compile-files* yourself

14:41 I've never done that though -- not sure what happens.

14:42 jweiss_: chouser: sneaky, what's the worst that could happen

14:42 * jweiss_ tries

14:42 rlb: It'd be nice if http://clojure.org/libraries had links to the docs (or code) for things like clojure.contrib.command-line.

14:46 mduerksen: jweiss_: I just prn'ted all parameters of the macro before the actual macro code started. Not elegant, but helped me figure out the *ns* issue.

14:56 fogus`: Is there a technical or philosophical reason why a macro that "returns" a function can't be apply'd?

14:56 amalloy: fogus`: because the list of parameters isn't known at compile time?

14:56 kotarak: rlb: http://clojure.github.com/clojure-contrib

14:57 member:rlb: http://clojure.github.com/clojure-contrib

14:57 amalloy: &(apply (or nil +) [1 2 3]) ; should work, if that's what you mean, fogus`

14:57 sexpbot: ⟹ 6

14:58 fogus`: amalloy: Why would that matter?

14:58 amalloy: fogus`: i must not understand what you're asking. can you give an example form that you wish would work but doesn't?

14:59 kotarak: fogus`: I'm not sure I understand „"returns"“

14:59 fogus`: let me put together an example

14:59 rlb: kotarak: thanks -- perhaps http://clojure.org/libraries should just have links there.

15:00 technomancy: the libraries page needs to be deprecated IMO

15:00 pjstadig: oinc

15:00 kotarak: technomancy: +1

15:00 Thorn: hello

15:01 technomancy: the idea that one manually-curated page could list all interesting Clojure libraries implies Clojure being a very immature ecosystem.

15:01 kotarak: technomancy: it was back then

15:01 technomancy: kotarak: oh, certainly.

15:04 fogus`: ammaloy, kotarak: Hmmm, nevermind. I was looking at the problem from the wrong perspective. What I wanted (I think) would/will be solved by letmacro

15:07 Thorn: if I do (map print some-seq) is memory wasted on a list of nils?

15:08 kotarak: Thorn: you want (doseq [x some-seq] (print x))

15:09 amalloy: Thorn: no, but because map is lazy you might not see your prints

15:09 kotarak: Thorn: map is not supposed to be used like this.

15:09 amalloy: kotarak: or (dorun (map print some-seq))

15:09 kotarak: amalloy: dorun is sooooooo ugly.

15:12 rlb: technomancy: the libraries page is also what google seems to finds first, i.e. for "clojure command-line"

15:12 s/finds/find

15:12 sexpbot: <rlb> technomancy: the libraries page is also what google seems to find first, i.e. for "clojure command-line"

15:13 Thorn: what if I want to apply a function to each element in a collection and don't care agbout return values, like .forEach() in javascript? is there an appropriate builtin for that?

15:13 kotarak: Thorn: doseq

15:14 Thorn: replace print in above example with your function

15:15 Thorn: I want syntax like (foreach fun seq)

15:15 should I do that myself?

15:17 chouser: (def foreach (comp dorun map))

15:17 if you must

15:17 Thorn: that's cool thanks

15:17 * kotarak prefers side-effects being ugly and widely visible in code.

15:17 chouser: yeah

15:19 dnolen: Thorn: doseq would probably be more idiomatic (doseq [x coll] (f x)) and going through a lazy seq.

15:19 and not involve going through a lazy seq I mean.

15:34 Thorn: why is '() not nil? ?

15:35 Chousuke: Thorn: because it's the empty list, and nil is null

15:35 nil is supposed to represent "nothing", and an empty list is not nothing :)

15:37 Thorn: well given that there are no cons cells that's probably a good idea

15:38 hiredman: () is also the empty seq, and making the distinction has ramifications for lazy seqs

15:40 raek: Thorn: well, there's still 'cons'. apart from that it can only have an ISeq object in its cdr slot, it's like whate you're used to in other lisps

15:40 jave: I'm trying to make a hello world portlet with clojure, but I'm getting file not found errors for clojure/core.clj on init

15:43 Thorn: clojure probably wins the "language with the largest amount of finer points" award

15:44 hiredman: unless you consider all the other languages

15:45 raek: jave: maybe it could be related to this: http://groups.google.com/group/clojure/browse_thread/thread/bb450997c5edf4ba/bb6ed7185c80c13a

15:46 Thorn: those will compete for the "unnecessary complicated" award (except scheme)

15:47 dnolen: anybody ever played with Quartz Scheduler?

15:48 jave: raek: hmm yes

15:49 raek: I found out that cron4j did what I needed (run a task at a specific time every weekday), so I never looked into Quartz

15:51 mduerksen: dnolen: quartz.net for work, but I did not do very sophisticated things with it

15:55 puredanger: anyone out there a guru on the implementation of clojure.zipper ? I have some questions around the signaling of enumeration end and how that doesn't play well with the loc state

15:59 hiredman: puredanger: there is a zipper/end?

16:00 puredanger: hiredman: yes

16:02 hiredman: puredanger: perhaps if you cared to share the problem you are having

16:02 puredanger: hiredman: well it requires some intimate knowledge of clojure.zipper but I'm happy to share my question

16:03 hiredman: in #java their bot has a factoid about "just ask your question, it is more efficent then all known implementations of the ask to ask protocol"

16:03 puredanger: zippers wrap nodes in "locs" which is a vector of the form [node { /loc-data /}]

16:04 hiredman: point taken

16:04 hiredman: and if you zip/next off the end you get a nil loc

16:04 puredanger: hiredman: actually no

16:04 if you zip to the end, you get a loc = [node :end]

16:04 hiredman: off the end

16:05 not "to the end"

16:05 but I could be wrong, it's something like 6 or 8 months since I have done anything with zippers

16:05 puredanger: the point being that the :end loc actually destroys the other data that was in the map in (loc 1)

16:06 and at that point, any operations on that last loc will mostly not work as you expect them to

16:06 for instance, if your tree is actually a single node, and you call next on it, you get back this state

16:07 hiredman: the various zip ops don't work on it?

16:08 puredanger: I'm not sure how to then get back to a state where that loc is the original loc, ready to next again without actually calling node, then recreating the zipper (which seems antithetical to the notion of zippers as (conceptually) a mutable tree)

16:08 hiredman: they do, but they work differently

16:09 hiredman: I see

16:09 puredanger: hiredman: I'm actually running into differences in code over the top of zipper so I'm trying to come up with a cogent example

16:09 hiredman: zip/prev doesn't work?

16:10 anyway, I don't have an answer, and unfortunately I need to pay attention to something else at the moment :(

16:11 puredanger: hiredman: thx

16:22 because the end node is also the last node in a DFS through the tree, it must be the root and thus has no left or right siblings - this actually covers many of the potentially broken paths. down is a function that will fail in this scenario though:

16:22 ; (def v (vector-zip [1 2]))

16:22 ; (-> v next next next down node) --> throws NPE

16:23 (the node call at the end is immaterial - the down is the point where the function expects a map at (loc 1) but finds only :end

16:23 here next next next will traverse from 1 to 2 to [1 2], then down should go back to 1.

16:24 what I'm wondering is if that is just outside the realm of what the zipper is supposed to do

16:24 hiredman: erm

16:24 right, hmmm

16:25 * Lajla hugs hiredman

16:28 puredanger: ; (-> v next next next prev) --> returns nil, which is also somewhat confusing to me

16:29 hiredman: may also be a result of the :end thing

16:33 puredanger: hiredman: oh, it definitely is

16:34 anything that relies on destructuring the map passed in the loc will fail as that map is destroyed

16:34 hiredman: are you on clojure-dev?

16:34 puredanger: hiredman: y

16:35 hiredman: good thought

16:37 my thinking now as I read more of the Huet paper is that getting to the end of the zipper should not return you to the same place as the beginning - you are "down the zipper" and the changes you've made are embodied in the zipper behind you. but you should be able to get back to the start by unzipping and other operations should understand when you get into this state.

17:06 phaer: How can i make a function parameter optional? eg. (defn connect-to-database [database user password host?] (...)). With host optional?

17:07 chouser: (defn foo [database user password & [host]] ...) is one way

17:08 raek: that will make the function take any number of arguments, right?

17:08 chouser: yep

17:08 Raynes: (defn foo ([database user password] ...some code that will call foo with a sane default for host...) ([database user password host] ..))

17:08 That's another option using arities.

17:09 raek: phaer: (defn connect-to-database ([database user password] (connect-to-database database user password nil)) ([database user password host] ...))

17:09 the longer variant

17:09 Raynes: raek: I beat you too it.

17:09 to*

17:09 raek: ...as Raynes already demonstated

17:09 Raynes: :p

17:09 raek: Raynes: and now again...

17:09 kotarak: (defn foo [database user password & {:keys [host]}] ...) (foo db u p :host host)

17:10 * raek lifts his hat

17:10 kotarak: Just for the case files

17:10 phaer: I'd like to make port optional too, so i guess your first variant will do the job. thanks.

17:11 Raynes: phaer: kotarak's version might be better for this.

17:11 (defn foo [database user password & {:keys [port host]}]) ... (foo db u :port 8080 :host localhost))

17:11 Minus the last paren.

17:18 alpheus: Please help me adjust my expectations about binding: http://alpheus.me/binding-question.clj

17:20 chouser: alpheus: because map returns a lazy seq, so f is not called until the REPL is trying to print the seq, well after the thread has left the scope of 'binding'

17:21 dnolen: anybody here messing with fogus's unifier?

17:21 alpheus: Ah, got it.

17:22 raek: alpheus: you can use bound-fn to make f remember the bindings

17:23 or maybe bound-fn* would be a better fit in this case

17:23 kotarak: or rolling something similar for seq: bound-seq http://bit.ly/anYaZq

17:23 raek: how does things look for a reactive framework for clojure?

17:25 I've seen ztellman's work on channels, and overheard that dnolen and stuartsierra were discussing something related

17:26 stuartsierra: Don't hold your breath.

17:26 alpheus: I've got a with-config macro that establishes some bindings then evaluates body. The body could be inside a bound-fn, but I'm wondering if this sounds like bad style?

17:26 raek: I'm reading "Deprecating the Observer Pattern" now, and I would like to hear about what similar things people are hacking on now

17:27 dnolen: raek: I would look at stuartsierra's work on cljque on github to get some ideas, stuff to play w/. Microsofts Rx definitely is working off the ideas presented in that paper.

17:49 alpheus: Back to my question about binding: would I still need to use bound-fn in 1.3?

17:51 mabes: alpheus: IIRC, with 1.3 dynamic vars must be explicit.. one key benefit of this is that bound-fn and variants are no longer needed

18:16 KirinDave: Ha

18:16 I clicked the "run in console mode" on fogus's homepage.

18:16 Forever will that mistake dominate my destiny.

18:18 bhenry: KirinDave: wow that is really cool.

18:19 mabes: KirinDave: hah, yeah, I did that once too.. I had to reset my cookies for the site.. once the novelty runs out it is somewhat annoying IMO...

18:19 Raynes: Oh wow, that is fantastic.

18:19 stain_: xkcd did something like that as well

18:19 mabes: it is a wordpress theme I believe

18:22 KirinDave: Yes, it is.

18:23 And it's very cool for about 35 seconds

18:23 Then you start trying to figure out how to undo it

18:26 Does anyone have a link offhand to how to tell lein to pull from a local maven repo?

18:29 amalloy: KirinDave: it should do that first by default, no?

18:29 KirinDave: amalloy: I mean a new one of my own architecting.

18:38 mabes: KirinDave: you just need to specify the repo in the project.clj like so: :repositories {"leadtune-repo" "http://c0026236.cdn1.cloudfiles.rackspacecloud.com/repo"}

18:38 technomancy: KirinDave: there was a thread about this last week on the lein list; puredanger had a good example.

18:38 KirinDave: Ahh, cool. Thanks, mabes

18:39 technomancy: I'm trying to get sbt and lein to nicely put banksimple stuff in private repos, etc.

18:39 technomancy: So it's becoming relevant to my interests.

18:39 technomancy: you sir are on an edge which is cutting. unexplored territory there. =)

18:40 KirinDave: The sharp end of the stick

18:40 technomancy: I've got some serious razorburn out here as it is.

18:40 I think I'm going to have to make a lein command to fool maven into doing the deploy properly.

18:40 mabes: a simple approach would be to "lein install" and then sync over the appropriate dir from the ~/.m2 folder

18:45 jave: I'm trying to inherit a java class from clojure, using genclass

18:46 aparently the class I get cannot be cast to an interface of the class I'm inheriting

18:51 KirinDave: jave: A gist demonstrating the problem is the fastest way to get an answer

18:51 jave: A lot can go wrong with gen-class, I feel your pain. Maybe I can help.

18:51 jave: Thanks.

18:51 ive just noticed I havent rtfm:ed properly. so ill do that and come back

18:57 rtfm didnt help

18:57 https://gist.github.com/712809

18:58 I get: java.lang.ClassCastException: cljportlet.portlet cannot be cast to javax.portlet.Portlet

18:58 I suppose theres something wrong with the signature

18:59 I dont actually need the typehints, right?

19:01 KirinDave: You don't.

19:01 Derander: when I try to use clojure.xml/parse on a file with a "?" in its filename, everything from the ? to the end of the filename is thrown away and I get a filenotfound exception from java.io

19:01 is there something I need to do?

19:01 (slurp file-with-?-in-name) works fine

19:02 KirinDave: jave: So what's the specific error you get?

19:02 jave: Caused by: java.lang.ClassCastException: cljportlet.portlet cannot be cast to javax.portlet.Portlet

19:02 when deploying the portlet

19:04 joshua__: Question about enlive. Lets say I have a class like "book" that appears like ten times on a page and I want to go through each of these book classes and fill them in with book details. Sometimes there will be more books, sometimes there will be less, depending on how many books need to be filled in. How would I do that?

19:04 Derander: (clojure.xml/parse (File. file-with-?-in-name)) works, fixed.

19:05 _ato: Derander: I think SAXParser (which clojure.xml wraps) treats a passed in string as a url, not a file path, so a ? in it will be treated as the query string separator, I guess

19:05 KirinDave_: jave: When you do lein compile it says that as the reason the compile fails?

19:06 Derander: _ato: yeah, I have a feeling something like that was going on.

19:06 _ato: like I said, (xml/parse (File. <filename>)) fixed the issue

19:07 jave: KirinDave_: oh, I dont get a compile time error. I build the uberwar fine. the error happens uppon deployment to liferay

19:07 KirinDave: Instantiate one on the repl and say (supers (class (cljportlet.portlet.)))

19:07 joshua__: Anyone know?

19:09 jave: KirinDave: javax.portlet.Portlet is on the list of supers

19:18 Derander: https://gist.github.com/712835 <-- any idea why this does not seem to act multithreaded? When it finds a file to process it runs the process function, and when that returns it continues writing "Firing."

19:19 I would expect it to keep writing "Firing." while processing the file

19:19 the java processes' thread count does increase by 1 while it's processing and then decrease by 1 after it's done, though

19:24 jave: yay, my hello world portlet now works!

19:25 _ato: Derander: hit Ctrl+\ (or do kill -QUIT $pid) while it's processing the file and "Firing" is blocked. It'll give you a stack trace telling you what each thread is doing and also if they're holding or waiting on any locks

19:26 Derander: _ato: in the repl?

19:26 (I'm doing this in emacs w/ slime)

19:27 _mst: don't you also want (Thread. #(process file)) or something?

19:27 _ato: aah

19:27 Derander: _mst: probably

19:27 _ato: there we go

19:27 _mst: if you're not passing in a fn it'll get evaluated in the main thread

19:27 Derander: oh, thank you

19:27 I wasn't aware of that

19:28 _mst: no worries. I'm often doing the same thing so the symptoms were familiar :)

19:28 Derander: :P

19:29 amalloy: Derander: (future (process file) works as well as (.start (Thread. (fn [] (process file))))

19:29 Derander: alright

19:29 amalloy: since future is a macro, it can delay evaluation of its arguments; java.lang.Thread knows nothing about that, so the arguments have to be evaluated before being shipped off

19:29 Derander: that's cool.

19:30 I see the use case for futures now

19:30 amalloy: Derander: well, the main use case is that futures return a value

19:30 Derander: right

19:30 I just read the docs and finally got what they di

19:30 do

19:30 joshua__: I had a flash of insihgt.

19:31 My question is answered, I had a misguided understanding of how to use the templating system.

19:31 Derander: joshua__: join the club :-)

19:32 alright, seems like it works now.

19:32 beautiful

19:32 joshua__: Congrats.

20:22 Derander: Should lein compile tell me "All namespaces already :aot compiled" no matter what I do?

20:22 Trying to run this app standalone outside of the repl, failing miserable

20:22 I've put (:gen-class) in my main ns, defined a -main function there, and put :main in project.clj

20:27 oh, I'm a moron.

20:32 defn: what does one need to start working on a ring middleware?

20:35 nvm -- figured it out :D

20:35 working on ring-modernizr

20:36 https://github.com/marshally/rack-modernizr

20:36 like that

21:00 islon: how can i do a record implement an interface?

21:08 puredanger: islon: you can specify an arbitrary number of interface or protocol extensions at the end of defrecord

21:12 islon: puredanger: thanks!

21:13 puredanger: islon: like: (defrecord Foo [a b] Iterable (iterator [] nil))

21:13 will implement the java.lang.Iterable interface which has one method iterator()

21:14 islon: actually, I always forget the interface takes the instance as the first arg: (defrecord Foo [a b] Iterable (iterator [this] nil))

21:14 islon: (defrecord bla [a b] Serializable) -> Duplicate interface name in class file compile__stub/user/bla

21:14 puredanger: islon: all records should automatically be serializable

21:14 islon: that's what I thought

21:14 thanks anyway =)

21:30 alpheus`: Where's a good place for information about switching from 1.2 to 1.3?

21:55 ossareh: since moving to 1.3.0 I'm noticing these, I assume generated by included libraries (certainly see that some libs cause more than others), what are they? "Var *classpath* not marked :dynamic true, setting to :dynamic. You should fix this before next release!"

21:57 Raynes: ossareh: In 1.3, vars have to be explicitly dynamic. Meaning, for a var to be able to be rebound using binding, it has to have :dynamic true in it's metadata map.

21:57 alpheus`: (def ^:dynamic a) ;; for example

21:58 ossareh: that is such a good idea.

21:59 alpheus: so just the presence of the key is enough? Raynes' msg suggests it would be (def ^{:dynamic true} a) ?

21:59 Raynes: ^:dynamic = ^{:dynamic true}

21:59 alpheus`: I just cribbed that from the test src

21:59 ossareh: Raynes: ahh - I didn't know that.

21:59 Raynes: It's shorthand.

21:59 ossareh: thanks guys =

21:59 =)

22:00 * ossareh continues to <3 the concision in this community

22:09 Lajla: &(-> (+ 1 2) "I worship his shadow"))

22:09 sexpbot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

22:10 Lajla: Hmm

22:10 So strings do not work as functions like vectors?

22:10 &("I worship your shadow" 0)

22:10 sexpbot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

22:10 Lajla: =(

22:15 alpheus`: &((vec "abc") 0)

22:15 sexpbot: ⟹ \a

22:37 Lajla: &('(1 2 3 4) 0)

22:37 sexpbot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

22:37 Lajla: Hmm

22:37 oh well

22:38 Raynes: &([1 2 3 4] 0)

22:38 sexpbot: ⟹ 1

22:38 Lajla: I know

22:38 I am just dissapointed that strings and lists don't. =(

22:38 I guess.

22:39 Because this is probably the part I like most about clojure.

22:39 That vectors are basically functions with their indices as domain

22:48 Edw: Anyone home?

22:49 clojurebot: help

22:49 clojurebot: http://www.khanacademy.org/

22:52 Adamant: KHANNNNNNNNNNN

22:52 Edw: ,(reduce #(assoc %1 %2 %3) {} '(a b c d e) (range))

22:52 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (4) passed to: core$r

22:54 ossareh: I just had to roll back all of my 1.3 work - was fine working in isolation but the moment I started using other libraries that haven't been ported it started to fall apart

22:54 seems all to do with the equality changes

22:55 edw: what are you trying to do?

22:56 edw: ossareh: take a list and create a hash whose keys are the elements and values the indices. While typing into web chat.freebies.net on my iPad.

22:57 Webchat.freenode.net, that is.

22:58 Raynes: &(into {} (clojure.contrib.seq/indexed '('a 'b 'c 'd)))

22:58 sexpbot: java.lang.ClassNotFoundException: clojure.contrib.seq

22:58 Raynes: Nonetheless.

22:59 edw: Thanks. Wish I'd brought my laptop home.

23:00 Raynes: (let [l '(a b c d)] (zipmap (range (count l)) l)) ; also works

23:00 &(let [l '(a b c d)] (zipmap (range (count l)) l))

23:00 sexpbot: ⟹ {3 d, 2 c, 1 b, 0 a}

23:01 edw: ,(reduce (fn [c [k v]] assoc c k v) {} (map #(list %1 %2) '(a b c d e) (range)))

23:01 clojurebot: 4

23:02 edw: D'oh, forgot patens...

23:03 ,(reduce (fn [c [k v]] (assoc c k v)) {} (map #(list %1 %2) '(a b c d e) (range)))

23:04 clojurebot: {e 4, d 3, c 2, b 1, a 0}

23:04 edw: There we go...

23:13 .(doc zipmap)

23:13 , (doc zipmap)

23:13 ,(doc zipmap)

23:13 clojurebot: "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

23:13 "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

Logging service provided by n01se.net