#clojure log - Jun 30 2010

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

0:43 technomancy: anyone know when the final reviewer notes for the latest Joy of Clojure draft is due?

1:35 scottj: Is there an abstraction for handling the case when you want branching behavior, but one branch is to do nothing (including not return nil)? Something like (defmacro bar [a] `(defn foo ,(when (even? a) a) [] ...)) when "when" can't return nil? You can write it roughly (defmacro bar [a] `(defn foo ,(let [tail []] (if (even? a) (cons a tail) tail)))) but I think it's kind of ugly as I want the branching to be cnfined to what's different, not inclu

1:46 tomoj: scottj: every expression returns something..

2:00 scottj: tomoj: yeah, I thought maybe there might be a macro with a clever name that would abstract that away :)

2:49 jowag: what are the guidelines for using bang (!) in the fn name? I read somewhere that one should use it when it is not safe to use fn in the transaction, is that it?

3:04 Bahman: Hi all!

3:28 zmila: jowag - seems, the ! sign is for fns with mutations

3:29 Chousuke: io stuff usually isn't marked with a bang

3:29 I think it's for functions which *could* be functional but aren't.

3:29 eg. the operations on transients.

3:40 jowag: Yep, the io is what got me perplexed, why fns like slurp does not have a bang notation

3:41 Chousuke: you can mark io functions with the io! macro so they will throw an error if used in transactions

3:42 jowag: yes I use it, but I was uncertain about the fn naming guidelines

3:42 Chousuke: they don't really exist :)

3:42 anything goes as long as you're consistent.

3:43 jowag: I see :)

3:46 I think I'll go with something like "use ! notation for fn with side effects except io stuff, in that case just use io! macro inside those fns"

4:02 cais2002: hi guys, is http://clojure.org/lazy the latest doc on laziness?

4:04 esj: Morning Good People

4:04 LauJensen: Good morning all

4:04 Bahman: Morning esj and LauJensen!

4:05 LauJensen: cais2002: Typically the stuff on clojure.org relates to the latest stable release, which feels like ages ago

4:05 cais2002: good afernoon guys

4:05 LauJensen: cais2002: Streams didnt get into Clojure, Chunks did

4:05 cais2002: am I supposed to get latest copy from github?

4:06 LauJensen: or via clojars, a snapshot

4:09 cais2002: great, let me try it out, thanks

4:13 esj: Lau, cgrand: How did the clojure training go?

4:26 cgrand: esj: on the phone with Lau right now :-)

4:26 esj: planning round 2 I hope :)

4:54 LauJensen: esj: Thats right :)

4:55 bobo_: same place? or too early to say perhaps

4:56 LauJensen: Yes, we havent zeroed in on a venue, so it might be close (ie Cologne), but it might be as far away as Berlin- All we know for certain is that its in Germany, early September. We are working rapidly on settling the last details

4:56 (although, picking a quality venue is always tricky. The one in Brussels was outstanding)

5:00 bobo_: :-)

5:01 if only i could find any arguments to tell my employer to send me

5:02 LauJensen: I can give him a call if you want :)

5:02 bobo_: :-)

5:03 there just isnt much clojure stuff for a consultant to take.

5:04 lpetit: bobo_: your employer may sometimes take some risks to be ahead of the concurrence.

5:04 bobo_: and sending you for a 3-days course isn't such a great risk :)

5:04 bobo_: true

5:04 well its money :-)

5:05 LauJensen: There might not be anything specifically labeled "Clojure", but knowing Clojure alone allows you to build better software, even if bound to another language. Secondly, even though it doesnt wear the Clojure label, many applications will benefit greatly from being implemented in Clojure. You'll learn about functional programming, concurrency etc, which are common themes nowadays

5:05 lpetit: concurrence = competition

5:05 bobo_: yeh true

5:05 i can atleast give it a try :-)

5:06 LauJensen: bobo_: In return for a 25% administration fee, as well as a 10% greeting fee and finally a 15% drinks/dinner fee, I'm prepared to offer a 45% discount

5:06 bobo_: early september is great timing atleast

5:06 lol

5:07 LauJensen: yea we hope most people are back from holidays

5:09 bobo_: is the page for the last round gone? cant seem to find it

5:09 LauJensen: http://conj-labs.eu is still there, but registration is closed

5:11 I see the pictures under course/venue are actually still from Bruseels, but I'll update that once we find THE place :)

5:32 esj: LauJensen: after Brussels though, it can only be downhill..... at least in terms of beer !

5:35 cgrand: esj: I recommend Moeder Lambic, they server great beers, http://www.moederlambic.eu/cellier/index.php/en/history/15-histoire/16-histoire :-) (fr, no english translation)

5:37 npoektop: hi! i need to do (apply some-macro first-ard '(rest-of-args)). I found apply-macro, but docs say "This is evil. Don't ever use it." Why?

5:39 cgrand: npoektop: because macros being functions is an impl detail

5:40 Chousuke: npoektop: if you need to do that, you're probably doing something weird

5:40 npoektop: is there a way to splice arglist to a macro?

5:40 cgrand: npoektop: usually you would prefer something like (macroexpand-1 `(some-macro ~first-arg ~@'(rest-of-args)))

5:41 but like Chousuke sais if you need to manually macroexpand or "call" a macro you are probably doing something wrong

5:41 Chousuke: npoektop: from another macro you can generate your call to the other macro any way you want.

5:42 if you're trying to do it from a function then you're probably misusing macros

5:42 what are you trying to do? maybe there's a better way.

5:43 raek: macros are expanded at compile time

5:43 Chousuke: also if you're just trying to generate code based on the contents of a data structure then you don't need a macro at all

5:43 raek: their input is unevaluated code

5:44 Chousuke: functions can return clojure code too

5:44 raek: applying a macro doesn't make much sense, since then the arguments will already be evaluated

5:44 clojurebot: code-review is <rhickey> yikes

5:47 Chousuke: ,((fn [vec-of-fn-names] `(do ~@(for [fn-name vec-of-fn-names] (list fn-name :somearg)))) '[foo bar zonk]); like this

5:47 clojurebot: (do (foo :somearg) (bar :somearg) (zonk :somearg))

5:47 Chousuke: and that you can pass to eval if you really need to, but eval too needs to be treated with suspicion :)

5:51 npoektop: i have this code: (defmodel ~collname (doall (map (fn [x#] (-> x# :name keyword)) conf#))). I'm trying to splice (doall (map...)) here.

5:52 Chousuke: hm

5:52 is that within a syntax-quote?

5:53 npoektop: I guess so: `(do ... (defmodel...))

5:53 Chousuke: show the whole macro please

5:53 ~@(map (fn [x] ...)) ought to work though (no need for gensyms there since it's not part of the generated code)

5:53 clojurebot: maps are *AWESOME*

5:54 Chousuke: though I'm not sure about the conf#

5:54 npoektop: http://pastebin.com/UKSLSMhi

5:54 Chousuke: you can't splice in things that are part of the generated code, the stuff needs to be available when the macro is called

5:55 don't put closing parens on their own lines please ;(

5:56 npoektop: it's not my code. i do not like it too)

5:57 Chousuke: hm

5:59 do away with the let and just do (defmodel ~collname ~@(map (fn [x] (-> x :name keyword)) (process-columns collname-str columns))))

5:59 cais2002: guys, where can I find the definition of "reduce" ?

5:59 Chousuke: ~def reduce

6:00 npoektop: it looks like the macro has the usual confusion about syntax-quote, the macro parameters, unquoting and how it all actually works :)

6:01 a macro is a function of type anything -> clojure code

6:02 it just so happens that the result is also evaluated by the compiler

6:03 cais2002: Chousuke: don't get it. but clojurebot does its job.. interesting

6:03 Chousuke: cais2002: that definition of reduce is rather more complicated than it needs to be, for performance reasons

6:06 an easy def of reduce is (defn red [f init coll] (if-not (seq coll) init (recur (f init (first coll)) (rest coll))))... it always requires the init value though.

6:08 cais2002: why is it not found on http://richhickey.github.com/clojure/api-index.html

6:09 or am I looking at the wrong place for api reference?

6:10 npoektop: That assert is unneseccary here, right? (defmacro defmodel [modelname & attributes] (assert (seq? attributes)) ... )

6:17 Chousuke: npoektop: right.

6:18 npoektop: thank you

6:22 * Lajla on Chousuke:n päällä nyt.

6:23 Lajla: ja menee alas ja Chousuke:n päähän

6:23 Nyt lajla on Chousuke:n päässä

6:29 Chousuke: :P

6:44 Lajla: Chousuke, on hyvää sun päässä

6:45 Sun aivot on nätti ja hyvä.

6:45 Chousuke: Lajla: you should keep nonsense on -casual :P

7:17 npoektop: i have a macro with a construction inside: '(do ... (defmodel ...)). defmodel is a macro. How to skip (defmodel ...) when i do not need it?

7:18 '(do ... (if condition (defmodel ...))) does not work.

7:18 jartur: Hi all.

7:18 Does anybody know if mmcgrana happens to be here sometimes?

7:19 lpetit: npoektop: you want some conditional code to execute in the macro, while constructing the code structure to be returned by the macro

7:20 npoektop: so you need to escape from the "code template" : `(do ... ~@(when condition `(defmodel ...)))

7:20 npoektop: lpetit, thank you

7:20 i'll try it

7:20 lpetit: ,`(do a (if true (defmodel)) b)

7:20 clojurebot: (do sandbox/a (if true (sandbox/defmodel)) sandbox/b)

7:20 lpetit: ,`(do a ~(if true `(defmodel)) b)

7:20 clojurebot: (do sandbox/a (sandbox/defmodel) sandbox/b)

7:21 lpetit: ,`(do a ~(if false `(defmodel)) b)

7:21 clojurebot: (do sandbox/a nil sandbox/b)

7:21 lpetit: ,`(do a ~@(if false `(defmodel)) b)

7:21 clojurebot: (do sandbox/a sandbox/b)

7:21 npoektop: cool

7:21 lpetit: ,`(do a ~@(if true `(defmodel)) b)

7:21 cais2002: hi, for this one, why do we need the additional identify call: (.instanceMember Classname args*) ==>

7:21 clojurebot: (do sandbox/a sandbox/defmodel sandbox/b)

7:21 cais2002: (. (identity Classname) instanceMember args*)

7:21 lpetit: ,`(do a ~@(if true `((defmodel))) b)

7:21 clojurebot: (do sandbox/a (sandbox/defmodel) sandbox/b)

7:22 lpetit: npoektop: there we are, if you want to avoid inserting a nil instead of defmodel when the condition is false, this form works:

7:22 ,`(do a ~@(if true `((defmodel))) b)

7:22 clojurebot: (do sandbox/a (sandbox/defmodel) sandbox/b)

7:22 lpetit: ,`(do a ~@(if false `((defmodel))) b)

7:22 clojurebot: (do sandbox/a sandbox/b)

7:22 lpetit: npoektop: but if you don't care, then the following form is easier to understand:

7:22 ,`(do a ~(if true `(defmodel)) b)

7:22 clojurebot: (do sandbox/a (sandbox/defmodel) sandbox/b)

7:23 lpetit: ,`(do a ~(if false `(defmodel)) b)

7:23 clojurebot: (do sandbox/a nil sandbox/b)

7:24 npoektop: lpetit, thank you very much! )

7:25 lpetit: npoektop: np

7:31 thetafp: (+ 1 2)

7:31 clojurebot: 3

7:31 jartur: so no mmcgrana here, aye?

7:34 cais2002: (reduce + 1 (2 3))

7:35 (reduce + 1 '(2 3))

7:35 (+ 1 2)

7:35 clojurebot: 3

7:38 Chousuke: that + thing is a special feature :P

7:38 you need to use ,(foo) if you want to eval clojure code

7:38 (+ 5 6

7:38 (+ 5 6)

7:38 clojurebot: *suffusion of yellow*

7:38 Chousuke: like that :P

7:39 cais2002: ,(+ 5 7)

7:39 clojurebot: 12

7:39 cais2002: ,(reduce + 1 '(2 3))

7:39 clojurebot: 6

7:39 cais2002: ,(infinite loop)

7:39 clojurebot: java.lang.Exception: Unable to resolve symbol: infinite in this context

7:40 Chousuke: infinite loops will last 10 seconds

7:46 cais2002: ok, that's what I thought would have happened

7:47 why does this not work? (macroexpand '((memfn charAt i) "ab" 1))

8:27 jowag: ,(/ 1 0)

8:27 clojurebot: java.lang.ArithmeticException: Divide by zero

9:01 bartj: er, is it possible to issue bash commands from the REPL ?

9:02 LauJensen: bartj: using shell-out from contrib, yes

9:02 in Emacs there's also M-!

9:07 ,(use 'clojure.contrib.shell)

9:07 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/shell__init.class or clojure/contrib/shell.clj on classpath:

9:08 LauJensen: well thats no fun

9:08 chouser: ,(require 'clojure.java.shell)

9:08 clojurebot: nil

9:09 LauJensen: same thing?

9:09 chouser: doubt it'll do you much good though.

9:09 ,(clojure.java.shell/sh "echo" "hello")

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

9:10 LauJensen: chouser: Is it the old contrib shell thats been moved?

9:10 bartj: and then do a "(echo hello)" ?

9:10 chouser: LauJensen: yes

9:11 LauJensen: chouser: Is there a list anywhere on which parts of contrib moved where?

9:11 bartj: No, that is the actual shell call

9:11 chouser: bartj: no, use the sh function from that namespace as I showed. The command to run and each of its args should be a separate arg to sh

9:11 hm, sh isn't really a good name

9:11 LauJensen: bartj: http://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/shell.clj#L138

9:12 chouser: should be shell/run or shell/launch or something.

9:13 bartj: gee, I don't see any output

9:13 ;(ls)

9:16 chouser: (sh "ls")

9:18 bartj: chouser: yay! thanks!

9:28 Licenser: cooookies

9:35 bartj: Licenser: for everyone ?

9:36 Licenser: of cause

9:39 LauJensen: Licenser: Just doesnt feel right without Raynes here to share the fun

9:40 Licenser: yea :(

9:40 but well we can leave him some crumbs

9:41 LauJensen: Licenser: Hows your Clojure driven game coming along?

9:42 Licenser: LauJensen: not good, the team kind of backstabed me and left me alone with it - very frustrating experience

9:42 LauJensen: Oh

9:45 Licenser__: So now i can keep chatting :)

9:46 LauJensen: Licenser__: There was this game some years ago called Freelancer, and later something that smelled like a Version 2 came out from another company, with another name, they were similar though. I would love to build an MMORPG like that in Clojure. It'll have to wait until I can clear a year out of the schedule though

9:48 Licenser__: LauJensen: That would Be cool it sounds a bit like eve online so

9:48 LauJensen: Never played Eve online, but from what I've heard they would be completely different

9:48 bartj: LauJensen: this is the one - http://en.wikipedia.org/wiki/Freelancer_(video_game)

9:48 ?

9:49 LauJensen: http://www.gamespot.com/pc/sim/freelancer/index.html?tag=result%3Btitle%3B0

9:49 Licenser__: Never played it either but it sounded a bit like freelancer online :P so oddly enough you could look at the epic engine while not build with this kind of stuff in mind it could very well function l

9:50 At least partially since it. Is turn based but speed should not be an issue it was made for battles witness a few thousand participants

10:05 TakeV: Why am I getting this error when I try to use the compile function? "java.io.FileNotFoundException: Could not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath: (NO_SOURCE_FILE:0)"

10:15 chouser: TakeV: most likely because your clj file is not on the classpath in the appropriate place

10:16 TakeV: chouser: I'm not using a clj file, just the REPL. I need a file?

10:16 chouser: (doc compile)

10:16 clojurebot: "([lib]); Compiles the namespace named by the symbol lib into a set of classfiles. The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath."

10:17 chouser: yes, compile takes a lib name and finds the appropriate .clj file on disk, then writes out the appropriate .class file to go with it.

10:18 if you're not trying to get a .class file, you don't need 'compile'

10:19 TakeV: Yeah, trying to do ahead of time compilation.

10:19 And I need to do (set! *compile-path* "/path/to/clj/file")?

10:20 chouser: no

10:22 pjstadig: you need "path/to/clj/file" to be in your classpath

10:23 chouser: AOT compilation can be a bit tricky to set up. I think there are good tutorials, though.

10:24 TakeV: chouser: Yeah, I'm reading them but they are not working. :\

10:25 chouser: those would be the bad tutorials. :-)

10:25 LauJensen: haha

10:25 TakeV: http://clojure.org/compilation -- This one?

10:25 LauJensen: thats true. But on a new lein project just as an example. Start a repl, (set! *compile-path* "/classes") and compile, thats it

11:20 mtopolnik: what would be the idiomatic way to make a memoized defn?

11:20 currently I have this:

11:20 (defn- myfun [arg] ...)

11:21 and then (def #^{:private true} myfun (memoize myfun))

11:23 Chousuke: mtopolnik: that's pretty much it

11:23 mtopolnik: there's a defn-memoize or something in contrib to make that a bit neater though

11:24 mtopolnik: yes, i'm looking for just such a thing

11:24 but it also needs to be private

11:24 Chousuke: that's not a problem

11:24 mtopolnik: of course, there isn't much work in defining it myself

11:24 AWizzArd: ,(doc defn-memo)

11:24 clojurebot: "clojure.contrib.def/defn-memo;[[fn-name & defn-stuff]]; Just like defn, but memoizes the function using clojure.core/memoize"

11:24 Chousuke: just add the metadata.

11:24 AWizzArd: I just defn-memo, easy to use.

11:24 mtopolnik: yeah, that'll do it

11:25 AWizzArd: mtopolnik: but of course, it is potentially able to introduce a "memory leak" into your app.

11:25 mtopolnik: sure, like any memoize

11:25 but i've got that under control

11:25 AWizzArd: k

11:25 mtopolnik: i'm memoizing all the setter-functions for my java beans

11:25 there won't be too many of those

11:26 in the hundreds tops

11:26 i guess a lambda doesn't use too much memory

11:27 AWizzArd: not much

11:27 Chousuke: mtopolnik: the problem isn't the number of the functions, it's the number of different arguments they get called with

11:28 mtopolnik: i wanted to say, my memoized function is a constructor for setter funtions

11:28 so it will get called with only a couple hundred different arguments (property names)

11:29 also, chouser warned me that it might make an even worse impact on memory (PermGen, specifically) if I don't memoize the lambdas but keep making new ones

11:30 hiredman: ,(doc resolve)

11:30 clojurebot: "([sym]); same as (ns-resolve *ns* symbol)"

11:30 hiredman: ,(ns-resolve (create-ns 'clojure.core) 'a)

11:30 clojurebot: nil

12:08 Fossi: ja

12:30 polypus: ~ping

12:30 clojurebot: PONG!

12:46 cais2002: ~pong

12:46 clojurebot: Qinfengxiang!

12:52 _fogus_: ,Q

12:52 clojurebot: java.lang.Exception: Unable to resolve symbol: Q in this context

12:57 polypus: are the hashcodes for datastructures generated at creation time or only when they are first needed by some equivalence test?

12:58 qbg: It seems to be usually by need

13:02 polypus: also, if i have a sorted set of some complex datastructure, and i am sorting on say the :id keys of those structures, which are integers, then hash codes do not need to be, and are not, calculated for the entire structure, but only for the keys, correct?

13:33 LauJensen: technomancy, hugod: M-. works great for the clj fns, but are there any way to dig into the java source as well ?

13:34 scottj: M-. works on any language if you use ctags

13:34 LauJensen: scottj: How do you get it to take you to one of the java files of Clojure.core?

13:35 hugod: LauJensen: specifically for core?

13:36 scottj: LauJensen, read emacs docs on ctags/etags

13:36 LauJensen: No not really, but its usually those functions I want to look up

13:36 @ hugod

13:37 technomancy: LauJensen: I don't think there's a good solution for that; seeing signatures via slime-inspector is the best I have managed.

13:37 scottj: short version: create TAGS file from source, load it, search it

13:37 technomancy: but if you really need it, yeah... ctags it is.

13:37 hugod: LauJensen scottj's suggestion seems the easiest - bind to a different key

13:37 LauJensen: Its odd that it takes a lot of work, since Eclipse does it out of the box, I didnt expect it to require any effort

13:38 technomancy: LauJensen: well, slime isn't really designed to work with Java =)

13:38 LauJensen: true

13:38 Alright, I'll look up ctags

13:38 thats scottj, hugod & technomancy :)

13:38 scottj: btw ctags is really useful for Clojure code as well since you don't have to have it loaded into slime (compilable, dependencies, etc) to browse/search it by tags

13:39 hugod: LauJensen: I use find . -name '*.java' | xargs etags --language=java

13:39 technomancy: scottj: right, but you have to build and constantly refresh the tags table

13:39 seems like more work

13:39 LauJensen: hugod: oh ok, and just run that on the git repo?

13:39 hugod: LauJensen: at the root

13:40 of the repo

13:40 LauJensen: yea

13:40 scottj: technomancy: one command

13:43 LauJensen: technomancy: one love

13:50 shoover: scottj: do you run that in a file save hook or anything for constant updates?

13:55 LauJensen: hugod: Your shellcall works fine, so its seems odd to me that this doesnt: find . -name '*.java' -type f -exec etags.emacs --language=java '{}' \;

13:56 It simply returns a file thats about 1/4 of that of your call, yet a superficial inspection of the files found, looks similar for both calls

14:00 hugod: LauJensen: xargs is presumably calling etags once with all the files as arguments

14:01 LauJensen: I see etags has a -a argument

14:03 LauJensen: aha

14:03 hugod: Is there anyway I can move the TAGS file to ~/.emacs.d and reference it from my .emacs, or how do you integrate?

14:04 hugod: LauJensen: first time you call find-tag it asks for the TAG file

14:05 LauJensen: I use it across several projects, so don't load any tag file by default

14:06 LauJensen: ok, cool, thanks

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

14:20 bobo_: hm, is there any "ok i installed the emacs-starter-kit now what" blog or similar? :-)

14:20 LauJensen: bobo_: To launch a repl, or to start coding?

14:20 bobo_: no more, this is what it can do

14:20 LauJensen: ah - Sorry I dont know that kit very well

14:21 bhenry: bobo_ http://www.assembla.com/wiki/show/clojure/Getting_Started_with_Emacs

14:21 if you haven't gotten the elpa stuff from esk yet

14:23 rhickey: Clojure now at: http://github.com/clojure

14:25 LauJensen: rhickey: fancy :)

14:34 polypus: most efficient way to remove N items from end of vector, getting vector back?

14:35 is it best to just pop multiple times?

14:36 hoeck: polypus: maybe that, or use subvec

14:37 polypus: hoeck: thanks, forgot about that one

14:37 hoeck: docs say its O(1)

14:37 polypus: that's what i need

14:44 technomancy: subvec won't allow elements in the original vector to get GC'd though, so watch out

14:47 polypus: technomancy: thanks for the heads up.

15:08 rhickey: pjstadig: fixed that problem from the other day: http://github.com/clojure/clojure/commit/0f4b6495347dc7d9601cc0907d5d08dd861bb3aa

15:13 LauJensen: rhickey: Its interesting to review the impact graph for Clojure. You're just slaving away on your lonesome all the way to 21 June 2009, when you dropped the stu bomb :)

15:17 pjstadig: rhickey: thanks...though I think that was actually a separate issue than I eventually realized was my problem

15:17 i think my problem ended up being that keywords are not GC'ed

15:18 polypus: forgive my ignorance, but what's the stu bomb?

15:18 Raynes: polypus: Stuart Halloway, I imagine.

15:18 polypus: but what's the bomb?

15:18 LauJensen: polypus: Yea Stuart, and the bomb was the 11500 lines he commited that day

15:18 Raynes: Tons of commits from Stu.

15:18 danlarkin: see kevin downey's patch to clojure-dev for more details on the keyword interning problem

15:19 polypus: ahh

15:19 danlarkin: unfortunately it's complicated :(

15:20 rhickey: pjstadig: yeah, keywords are not yet held by weak refs, they'll need a similar treatment in order to be tolerant of ongoing generation

15:23 danlarkin: I moved build.clojure.org to point to the new clojure github fyi

15:34 rhickey: danlarkin: cool

15:35 polypus: is into! planned for transients. what about peek on transient vectors?

15:54 wolfjb: where can I read more about clojure.test? I've just started learning clojure and have started my first project with lein, but running lein test gives an error 'Unable to resolve symbol in this context'

15:55 lancepantz: wolfjb: that's just an exception in either your source or your test

15:56 Raynes: wolfjb: http://java.ociweb.com/mark/clojure/article.html#Testing

15:56 wolfjb: Raynes: thanks

15:58 lancepantz: in myproject.core I have (defn add2 [x] (+ x 2)) and in myproject.core-test I have (deftest test-add2 (is (= (add2 2) 4))) but the unresolved symbol is add2

15:59 lancepantz: wolfjb: you have to use myproject.core-test in your test

15:59 raek: (ns myproject.core-test (:use myproject.core))

15:59 wolfjb: thanks

16:00 * wolfjb is a n00b! yikes!

16:00 lancepantz: wolfjb: no prob, ask away

16:00 wolfjb: thanks!

16:50 replaca: rhickey: are you here?

16:50 rhickey: replaca: yes

16:50 replaca: the clojure org is now the official repo?

16:51 i see that you're pushing stuff there

16:51 rhickey: replaca: in the process, do you want me to change the hook?

16:51 replaca: yeah, the hook should be wherever you're pushing to

16:51 rhickey: replaca: I thought Stu was getting in touch with you to coordinate

16:52 dsop: hmm how to call the overwritten super class method in a gen-class?

16:52 replaca: also, I wanted to know where to push contrib changes and autodoc pages

16:52 rhickey: no, I hadn't heard from him yet

16:52 rhickey: yes, please to clojure now

16:52 replaca: ok. we'll have to update links on clojure.org

16:53 to point at the "new" autodoc

16:53 I'll get it building to there tonight (assuming github pages work with organizations)

16:54 rhickey: replaca: ok, hooks are on in the clojure repos

16:55 replaca: let me know if you need any settings tweaked, I think you should have the privileges you need

17:02 chouser: so is the official git repo moving? was there an announcement I missed?

17:03 lpetit: what what ? :)

17:04 replaca: chouser: that seems to be it. Github has finally added an "organizations" feature that let's us put the repo in a place separate from the person "richhickey" while still letting him be BDFL

17:05 rhickey: chouser: yes, we are in the process of moving, will 'announce' when everything is in place. We're pushing to clojure from now on

17:06 chouser: ah, I see it. http://github.com/clojure/clojure but not quite ready yet?

17:07 rhickey: chouser: close, needs docs, downloads etc. hooks in place to assembla, all privileges in place

17:07 chouser: huh, didn't know I was a member. I wonder where I can see a list of the organizations I'm a member of.

17:07 rhickey: excellent. sounds good.

17:14 dsop: does someone know how to add an init function to defservice?

17:14 that is called during servlet initialization?

17:19 Raynes: It's a shame that all of those 956 watchers will have to watch the new repo.

17:19 Organizations are confusing.

17:19 :p

17:43 wolfjb: is there a mocking mechanism (like JMock or Mockito or similar) for clojure?

17:44 bhenry: chouser click "switch context" in the top(ish) right of the github home page to see all your orgs.

17:47 wolfjb: okay, found test-expect, but no doc?

17:47 Chousuke: Raynes: at least switching the url of a remote in git is trivial :P

17:47 Raynes: no need to reclone a repository

17:50 replaca: Chousuke: do I edit the file to do that or is there a git command?

17:50 Chousuke: git remote set-url remotename new-url

17:50 remotename should be origin in this case :)

17:50 replaca: Chousuke: thanks!

17:51 Chousuke: git's concept of remotes is excellent

17:51 replaca: Chousuke: yeah, git always seems to have a way to do what I want, it's just hard to figure out and keep track of :)

17:52 Chousuke: the original server is just given a default name, other than that, it's just like any other remote :P

17:52 technomancy: can also edit .git/config

17:52 Chousuke: I have two remotes in my local git repo

17:52 one for rhickey's repository, and one for my own clone

17:52 on github

17:53 haven't updated it in a while though :P

17:57 yacin: can you cast nil to something in clojure like you can cast null to an object in java?

17:57 like

17:57 DeusExPikachu: is this statement correct? "it is impossible to extend an object returned by reify"

17:57 yacin: (FastVector) null

17:58 i ask because in weka, to make a string attribute, you do:

17:58 new Attribute("att3", (FastVector) null)

17:59 DeusExPikachu: or better yet this statement "it is impossible to extend an object returned by reify to new protocols/interfaces"

17:59 yacin: i tried (cast FastVector nil)

17:59 but it doesn't seem to work properly

18:00 qbg: yacin: Is there another 2 argument constructor for Attribute?

18:01 Chousuke: DeusExPikachu: the class of a reified thing is anonymous so... yes?

18:01 DeusExPikachu: Chousuke: how does one extend the object then?

18:01 as in the syntax required to do so

18:01 Chousuke: DeusExPikachu: though you could extend an interface that the reified object implements, thus "extending" the reified object too.

18:01 DeusExPikachu: you don't really extend protocols to objects. you do it to classes

18:02 yacin: qbg: there are a couple

18:02 qbg: Are you using 1.2?

18:02 yacin: nah, unfortunately not

18:02 qbg: 1.1?

18:02 yacin: yes

18:02 DeusExPikachu: Chousuke: like basically I know I can extend a type with extend-type, but dont' know how to do with something returned by reify as reify returns an object as you said

18:03 qbg: Try (Attribute. "att3" #^FastVector nil); that might work

18:03 Chousuke: DeusExPikachu: yeah, you can't

18:03 DeusExPikachu: you'd need to know the class of the reified object, but you don't

18:03 qbg: Actually not, because you can't put metadata on nil..

18:03 DeusExPikachu: ok, so that's an important distinction between reify and defrecord then

18:04 Chousuke: DeusExPikachu: but as I said, if the reified object implements an extended-to interface or the protocol directly, then of course it works.

18:04 DeusExPikachu: Chousuke: hmm I'm not seeing the example in my head

18:05 Chousuke: DeusExPikachu: reified objects implement interfaces

18:05 DeusExPikachu: and protocols can be extended to interfaces

18:05 DeusExPikachu: 1) reify interface 2) extend protocol to interface 3) protocol methods work with aforementioned reified object

18:06 DeusExPikachu: that last part, protocls can be extended to interfaces, does that mean the protocol takes on new methods from interface?

18:06 Chousuke: no, it means that you provide an implementation of the protocol for objects of the interface

18:07 yacin: qbg: yeah =\

18:07 Chousuke: DeusExPikachu: protocols *cover* different data types. thus extending means you extend the range of data types they work with

18:08 DeusExPikachu: it's a bit backwards from the usual "extending" in OO languages

18:08 DeusExPikachu: Chousuke: so extending a protocol to an interface implies that an interface is a datatype?

18:08 Chousuke: DeusExPikachu: not really

18:09 DeusExPikachu: btw, interface, thats java only right Chousuke?

18:09 Chousuke: yes.

18:10 qbg: yacin: Maybe try (let [#^FastVector x nil] (Attribute. "att3" x))?

18:10 DeusExPikachu: hmm I guess from within clojure, its not possible then

18:10 Chousuke: DeusExPikachu: you could have some protocol, say, MyFancyMapping with a method apply-to-all extended to the Collection interface.

18:10 DeusExPikachu: then all Collection classes would work with the protocol

18:11 yacin: qbg: awesome. works!

18:11 Chousuke: DeusExPikachu: extending can be done from Clojure

18:11 DeusExPikachu: oh so extending a protocol is like redefining the protocol as the union of the old protocol and the interface?

18:11 * qbg grumbles about libraries that require you to cast null...

18:12 DeusExPikachu: *union of the methods

18:12 Chousuke: DeusExPikachu: no, the protocol doesn't gain new methods

18:12 yacin: yeah, seems pretty ridiculous to me

18:12 Chousuke: DeusExPikachu: it just gains new kinds of objects that the existing methods work on

18:12 DeusExPikachu: ok, so then I can't define new methods for a reified object then

18:12 yacin: but i'm adding support for strings in clj-ml

18:13 Chousuke: DeusExPikachu: you can't define java methods but you can make them work with protocols

18:15 DeusExPikachu: so lets say (def foo (reify ...)), and later how would I allow some other protocol to work with foo if I don't have the type for foo, only foo itself?

18:17 Chousuke: DeusExPikachu: You should know the interfaces foo reifies as they're the only way to actually use the object.

18:17 DeusExPikachu: and through those you can make it work with a protocol

18:18 DeusExPikachu: the actuall class of the object is unknown and can't be used, but then again that shouldn't be a problem

18:18 DeusExPikachu: so lets say foo implements bar-protocol, then I extend bar-protocol to some other types, that doesn't add methods to foo though right?

18:18 Chousuke: extending protocols doesn't add methods. ever.

18:19 DeusExPikachu: right, but that was my original question

18:19 reiterated, is it possible to add methods to a object returned by reify

18:19 Chousuke: java methods?

18:19 no

18:20 DeusExPikachu: and the yes part is clojure methods?

18:20 Chousuke: but again, it's possible to make it work with new protocols even after it has been created, through extending the interfaces. but protocol functions aren't methods.

18:21 extending to the interfaces, even

18:21 need to be careful with the wording, it's confusing enough without me being sloppy :P

18:21 DeusExPikachu: Chousuke: np, just trying to get this figured out

18:22 Chousuke: it might be easier if you just forget about objects for a while and consider only types

18:22 DeusExPikachu: thats fine, reify returns an instance of a type

18:22 Chousuke: a protocol is a set of functions and a set of types that those functions work with

18:22 the set of types is extensible

18:22 that's all

18:22 DeusExPikachu: right

18:23 so how would you make a new protocol extend to foo?

18:23 and foo is : (def foo (reify ...))

18:23 Chousuke: well you'd have to know an interface that foo implements

18:24 DeusExPikachu: foo implements bar-protocol

18:24 Chousuke: well then there's no need to extend because it's already in the set :P

18:24 but let's say it implements only a java interface instead

18:24 DeusExPikachu: ... but I want to extend to new protocols

18:24 Chousuke: ah, hmm

18:25 well since direct protocol-implementing is done via an interface, I guess you can treat bar-protocol as if it were an interface ;P

18:26 I'm not sure about the syntax right now but it goes something like (extend-type the.package.bar-protocol some-other-protocol (othermethod ...))

18:26 DeusExPikachu: extend-type can accept a protocol as its arg? I thought it only accepts types

18:27 Chousuke: well that's taking advantage of the fact taht protocols are backed by an interface.

18:27 but hm, that won't work in the general case.

18:28 DeusExPikachu: ok well regardless, so you call extend-type on bar-protocol to extend to baz protocol I'm guessing?

18:28 Chousuke: yeah, that ought to work. though only for things that implenet bar-protocol directly.

18:28 implement

18:29 it's probably a bit fragile :/

18:29 DeusExPikachu: so foo implements bar, and now bar is extended to baz, so does that mean baz methods/fns whatever you call it works on foo?

18:30 Chousuke: yes.

18:30 DeusExPikachu: ok, thats a new to me

18:31 I didn't know you could extend bar to baz, you say its fragile though

18:31 Chousuke: but only if foo directly implements bar. if foo is extended to the bar protocol afterwards instead, it probably won't work.

18:31 DeusExPikachu: it takes advantage of an implementation detail

18:32 namely that when you generate a protocol, a matching interface is generated too

18:32 and it's automatically made part of the protocol

18:32 DeusExPikachu: btw, foo directly implements bar in this case though right? what I wouldn't be able to do if there was another protocol bee, and baz is later extended to bee, foo wouldn't get bee?

18:32 Chousuke: right.

18:32 DeusExPikachu: ok, think its clear now

18:32 great help

18:33 I think because it won't work in the general case, its better in my case to use defrecord instead of reify

18:33 I'm guessing reify has some performance advantages though compared to defrecord?

18:34 Chousuke: the mechanism of extension is the same in either case, but defrecord generates a named class so you don't need to extend a protocol to it "indirectly"

18:34 but no, no real performance advantages I think

18:34 reify is mostly meant for one-off implementations of java interfaces.

18:35 DeusExPikachu: oh really, what about memory consumption despite how little, defrecord does more stuff behind the scences than reify right?

18:35 Chousuke: well, yeah

18:35 lpetit: hi guys. As with every new tool, there will be protocol / type / record abuse. How would you recommend the use (and not abuse) of these new features to newcomers ?

18:35 DeusExPikachu: kk, thanks Chousuke

18:36 Chousuke: lpetit: that's a broad question :P

18:36 lpetit: Chousuke: oh really ? :-)

18:36 Chousuke: lpetit: I don't think anyone except rhickey has a clear idea what constitutes use and abuse of those things, yet.

18:36 dnolen: lpetit: I probably wouldn't recommend them to newcomers.

18:37 lpetit: Chousuke: I'm just preparing myself for the new lengthy "noob" questions :-p

18:37 dnolen: lpetit: maybe defrecord if someone really wants a struct

18:37 Chousuke: lpetit: I suppose warning against hierarchies would be a good start. ie. tell newbies not to try to derive or inherit things :P

18:38 qbg: Well, protocols are a subset of multimethods in a sense, so it would be related to that.

18:38 lpetit: dnolen: and if someone knows in advance that he will just need single dispatch type-based polymorphism

18:39 dnolen: lpetit: but I still wouldn't recommend. You can get that with multimethods, and it encourages newcomers to explore a much more generic style of programming.

18:40 maps + multimethods still the way to go at the beginning I think.

18:40 lpetit: dnolen, Chousuke: you wouldn't recommend them to newcomers, but when 1.2 will be out, you will (and newcomers will) see "protocols" "datatypes" written everywhere in twitter, facebook, blog posts, infoq, etc. . And they will think "I can do my OO stuff in clojure now, yeah !" :-)

18:41 Chousuke: lpetit: they'll be right and wrong at the same time? :D

18:41 lpetit: Chousuke: google group will not support the traffic jam concerning these explanations ! :)

18:42 s/concerning/related to/

18:42 sexpbot: Chousuke: google group will not support the traffic jam related to these explanations ! :)

18:42 qbg: Google groups will go into an infinite loop!

18:43 dnolen: lpetit: I don't think it hurts for newcomers to explore them, just as much as they'll explore macros - I think it's constructive to guide people to explore eslewhere.

18:44 lpetit: dnolen: you're right.

18:44 dnolen: I learned a lot by hearing people say early on to use maps over structs. eventually it sunk in.

18:45 Chousuke: part of that was that structs really weren't that much of an improvement over maps

18:46 records are entirely different however

20:41 defn: it is absolutely uncanny how much rich and phillip glass look alike

20:51 http://graphics.musicme.com/wp/fr/2351/Philip_Glass_018.jpg http://pragprog.com/magazines/2009-07/images/clojure/RichHickey.jpg

20:51 LuminousMonkey: Woah!

20:52 It is uncanny...

20:52 defn: heh...thought it was sort of interesting

20:53 LuminousMonkey: That means I should be listening to Koyaanisqatsi while programming Clojure? :)

20:53 defn: haha!

20:53 Naqoyqatsi might be better

20:54 LuminousMonkey: Only have Koyaanisqatsi, I should get some others.

20:54 defn: glass has a pretty massive collection of operas and the like

20:55 his most recent work is called the book of longing -- it's all solo cello

20:55 very awesome work though

20:55 recommended.

20:55 LuminousMonkey: Nice. I shall see what I can find. Thanks.

20:56 defn: actually i take that back

20:56 book of longing is all based on leonard cohen poetry

20:57 ah yes, here it is: songs and poems for solo cello - wendy sutter

22:36 yacin: can you modify metadata of variables created by let?

22:37 mikem: yacin: you can generate a new var which contains the metadata you need based on the one created with let

22:38 hiredman: variables?

22:38 let doesn't make vars

22:38 yacin: i realize i'm not being precise with my terminology

22:38 mikem: hiredman: actually, what is the correct term for the thing let creates?

22:38 yacin: but i think my intent is pretty clear

22:38 hiredman: let doesn't create anything

22:39 mikem: a binding, maybe?

22:39 hiredman: but a binding is not a thing

22:39 mikem: show me a reference to a binding

22:40 mikem: so if I have (let [x 1] (println x)) and I want to refer to the x passed to println, what would I call it?

22:40 hiredman: you don't

22:40 mikem: i mean, what would I call it in english, when trying to explain this code to someone for example :)

22:40 hiredman: let means replace the occurances of this thing with the value of evaluating this other thing

22:40 x is a name

22:41 or a local

22:44 yacin: well, i'm trying to make the weird java idiom of casting null easy in clojure

22:44 i can do it with: (let [#^classname x nil] x)

22:46 but i'd like something along the lines of (cast-null ClassName)

22:56 qbg: yacin: (defmacro cast-null [c] `(let [~(with-meta 'x {:tag c}) nil] ~'x))

22:58 yacin: qbg: righteous, thanks

23:03 mudge: hello

23:03 celar

23:03 clear

23:03 i guess this doesn't work like a bash prompt

23:03 i'm a newbie to clojure

23:03 i was wondering if someone could help me with a simple thing

23:03 yacin: sure

23:04 mudge: i want to implement a java interface, one of the java interface methods returns void, so what is the way in clojure to write a function the returns void?

23:04 should the clojure function return nil ?

23:05 qbg: How are you implementing the java interface?

23:06 mudge: using :gen-class and :implements inside ns

23:06 then writing functions that start with "-"

23:07 qbg: Chances are that it will either just work, or you might have to play with :methods

23:07 mudge: okay

23:07 maybe i'll make my functions return nil

23:07 its kind of like void

23:08 qbg: Given that the docstring for gen-class says about :methods "Do not repeat superclass/interface signatures here.", it should just work I think.

23:09 mudge: yea, qbg, makes sense, thanks

23:10 wow, gen-class has a long doc string

23:10 qbg, you gave me the idea to read the doc strings of these things

23:10 that's even better than an answer to my question

23:10 thanks

23:16 arohner: mudge: just out of curiosity, why did you pick gen-class over the alternatives?

23:19 mudge: arohner, I didn't pick gen-class, i picked :gen-class inside ns. are there alternatives to this?

23:19 qbg: proxy

23:20 mudge: ah, i don't really understand proxy, is it better then using gen-class ?

23:21 arohner: mudge: depends on your needs. gen-class is useful if you need to start from a command line, or in some other cases where java code you don't control calls your class

23:21 qbg: If you don't need a named class, gen-class is probably overkill

23:21 For implementing an interface, proxy is usually more than fine.

23:21 mudge: ah, i do need to compile my code to a class so it can be called by Java code

23:22 so i will need a my class with a name right?

23:22 arohner: mudge: can you go into more detail?

23:23 mudge: i'm intending on writing some clojure code that uses Java classes and interfaces and that then generates java classes so that another java program can use them

23:24 i'm writing a 3rd part module for a Java application

23:24 party*

23:24 3rd party*

23:24 arohner: ah, yeah, then gen-class is probably what you want

23:24 mudge: okay, cool

23:25 arohner: just making sure ;-). a lot of newbies aren't always aware of the options

23:25 mudge: thanks

23:25 qbg: There is a ton of stuff in Clojure, so it is easy to miss stuff

23:25 mudge: i bet

23:26 qbg: find-doc is your friend

23:43 arohner: WTH is c1337?

23:44 tomoj: would be nice if clojurebot could pull out the description from the pom, and if people wrote good descriptions

23:44 arohner: it looks like a hello world kind of project

23:46 hiredman: meh

23:51 itistoday: what's the difference between: (defmacro time2 [expr times] `(time (dotimes [_# ~times] ~@expr)))

23:51 and (defmacro time2 [expr times] (time `(dotimes [_# ~times] ~@expr)))

23:51 qbg: The second one doesn't do what you want

23:53 itistoday: what does the second one do and why?

23:53 qbg: The second one times, at macroexpansion time, how long it takes `(dotimes [_# ~times] ~@expr) to execute

23:53 Which is very fast, as it is just constructing a list

23:53 itistoday: gotcha...

23:53 ok thanks qbg, that's a good explanation!

23:56 qbg: Also, you want (defmacro time2 [expr times] `(time (dotimes [_# ~times] ~expr)))

23:56 itistoday: qbg: can you walk me through the steps? (or point me somewhere that lists them?)

23:56 qbg: itistoday: You mean how macros work?

23:56 itistoday: qbg: ok thanks, it worked

23:56 qbg: yeah

23:57 qbg: A macro is just a function that returns some code

23:57 itistoday: i'm trying to guess based on what you said at what time the list is constructed, and when things are evaluated

23:57 qbg: When the macro call is compiled, the compiler runs the macro with its arguments, unevaluated, and substitutes its return value in its place.

23:58 itistoday: let's take this as an example: (defmacro time2 [expr times] (time `(dotimes [_# ~times] ~expr)))

23:59 qbg: Okay

23:59 itistoday: so, when i define that, the macro is not compiled yet, right? or is it?

23:59 qbg: The macro is compiled to a function, and {:macro true} is placed on time2's var's metadata

Logging service provided by n01se.net