#clojure log - Oct 30 2009

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

0:02 arbscht: hm, rfirst and rrest were replaced with nfirst and nnext during the lazy merge

0:08 adityo: good morning folks

0:08 arbscht: hi

2:34 konr: Is there a particular http client I should use?

2:35 arbscht: what are your requirements?

2:36 konr: hmmm... support for cookies... nothing much more complicated than that

2:41 arbscht: you could probably build on c.c.http-agent. if you want automatic cookie management maybe apache's httpclient

3:07 Fossi: hi

3:12 konr: HI, Fossi

3:40 sfuentes: chouser: so your scala adventures are over?

3:45 hiredman: ~scala ((x: Int) => x + 1)(3)

3:45 clojurebot: Int = 4

3:57 hiredman: sfuentes: http://gist.github.com/199542

3:58 or something like it

4:03 sfuentes: hiredman: thanks for the sample :)

4:05 hiredman: it maybe help to note that resources are loaded via the classpath and the classpath has little to do with filesystem locality

4:12 sgtzx: anyone using Enclojure here?

4:13 I am trying to learn Clojure while using Enclojure in NetBeans, but it is acting very strangely.

4:14 for example if I have (let [frame (JFrame. "Celsius Converter" ... then later I do (doto frame (.<I apply tab completion here and it seems to not be able to infer that frame is JFrame>

4:48 Fossi: wouldn't it make sense to make all io methods and java calls to use an implicit io!?

4:49 konr: How do I send a file using http.client? I'm using (File. "/foo/bar.jpg"), yet apparently the field is being dropped

5:04 spuz: LauJensen: hey

5:04 LauJensen: Hey spuz

5:06 spuz: Just running your brain sim now :)

5:06 LauJensen: How's it going?

5:06 spuz: There's a few things I didn't quite understand in your description though..

5:07 for example, you mention pmap, but where do you actually use it?

5:07 also, how does it work?

5:08 LauJensen: Second line in "step" is "pmap (fn [window]"

5:08 ~def pmap

5:10 As you can see it splits the computation into bits which are passed to 'futures' running in their own threads

5:14 spuz: interestingly, it appears to be creating 2 more threads than there are available processors

5:17 yason: spuz: it's a common idiom: two processes per processor perform better in case the processes are less than 100% cpu-bound; otherwise it's just 50/50.

5:17 eevar2: I think processor count * 2 might have been a better choise

5:17 granted, you get more context switches, but

5:17 yason: spuz: doubling, that is. Not +2, although if you have a dual-core system then it's probably *2 and not +2 :)

5:21 spuz: well, if you see the code for pmap, it sets n to numprocessors + 2. I'm not exactly sure what it does with 'n' after that but I assume that's the number of threads that is created...

5:28 LauJensen: also, could you explain what the step function does? I'm not quite getting the third line. Could you maybe expand it with an example of the input and output that goes into each part of the function?

5:30 LauJensen: spuz: I doubt I could you more input than what you get from setting the board dimensions to 3x3, re-eval 'board' and then do it step by step, you'll see how it is mapping windows on windows

5:30 spuz: ok good idea

5:35 sgtzx: LauJensen: brain sim is cool

5:35 LauJensen: you mentioned there is a performance hit due to that it's a functional language, how much do you think it is?

5:36 LauJensen: sgtzx: Glad you think so :)

5:36 With the current model, which is simple to reason about, the performance hit is huge, the way we work the board, the way the board is allocation, the massive allocation that comes with 'partition' and the strain on the GC that puts... Its a huge hit

5:37 I'm considering doing a revised version with blazing performance, but I figured I'd wait a few days and see what the commentators come up with :)

5:37 sgtzx: LauJensen: I would love to see that

5:41 LauJensen: out of curiosity, what IDE do you use, or do you use emacs and slime for clj dev?

5:41 vy: I'd expect concat to behave same as lazy-cat and there would appear no lazy-cat? Aren't they functionally identical, except laziness?

5:42 LauJensen: sgtzx: Emacs

5:43 ,(class (concat 1 2))

5:43 clojurebot: clojure.lang.LazySeq

5:43 hiredman: ,(first (concat [1] (println :foo)))

5:43 clojurebot: 1

5:44 :foo

5:44 hiredman: ,(first (lazy-cat [1] (println :foo)))

5:44 clojurebot: 1

5:44 vy: So what's the difference between lazy-cat and concat?

5:44 hiredman: lazy-cat has an extra layer of laziness

5:44 vy: Ooops! lazy-cat is just a macro over concat!

5:45 [& colls] `(concat ~@(map #(list `lazy-seq %) colls))

5:45 hiredman: concat is a function, so it's arguments are evaluated

5:45 lazy-cat is a macro, so it controls the evaluation of its arguments

5:46 which it does by wrapping them in a call to lazy-seq

5:47 vy: I'd still expect "concat" to work as "lazy-cat". Anyway...

5:48 hiredman: well, if you read the docstrings, the difference is explained there

5:48 so I don't know why you would expect something other than what is documented

5:48 vy: Why would somebody prefer concat over lazy-cat?

5:49 hiredman: concat is a function

5:49 so you can apply it

5:49 etc

5:50 rsynnott: also, lazy-cat sounds like some form of lolcat

5:52 ambient: so does concat ;)

5:53 Fossi: repost (;-)): wouldn't it make sense to make all io methods and java calls to use an implicit io!?

5:55 jdz: Fossi: what is an implicit io?

5:56 hiredman: ,(doc io!)

5:56 clojurebot: "([& body]); If an io! block occurs in a transaction, throws an IllegalStateException, else runs body in an implicit do. If the first expression in body is a literal string, will use that as the exception message."

5:57 vy: I'm reading clojure cheat sheet... While there appears "frest", and "rrest" in the documentation, there are no such functions supplied by the core, AFAIK. Am I missing something?

5:57 hiredman: the cheat sheet is old

5:57 the are fnext and something else now

5:58 rnext?

5:58 ,rnext

5:58 clojurebot: java.lang.Exception: Unable to resolve symbol: rnext in this context

5:58 hiredman: ,nnext

5:58 clojurebot: #<core$nnext__3833 clojure.core$nnext__3833@1daa156>

5:59 vy: I love languages that are getting trimmed by time.

6:03 sgtzx: ,nnext

6:03 clojurebot: #<core$nnext__3833 clojure.core$nnext__3833@1daa156>

6:13 jdz: there still is not any function like CL's find, is there?

6:15 vy: jdz: (first (filter f coll)).

6:15 jdz: vy: right.

6:20 liwp: any slime experts here?

6:21 if I type e.g. "(fn" into the repl and hit tab, I get a completion suggestion buffer and point has been moved in front of 'n' which I find really annoying

6:22 Is there a way to stop point from moving or can I somehow overwrite the 'n' when I carry on typing?

6:30 jdz: i don't observe the behaviour you describe...

6:31 LauJensen: jdz: phew - I thought something had happend to you, since I hadn't received a flamemail for my last blog post yet :)

6:32 liwp: jdz: urgh, I'll need to look into my slime setup then...

6:34 vy: liwp: Same as jdz in here.

6:35 liwp: vy & jdz: what do you get then? the completion buffer, but the point stays at the end of the line?

6:35 i seem to recall that I didn't see this behaviour sometime in the past, but I can't be sure

6:36 vy: liwp: Yup.

6:37 liwp: thanks

6:38 vy: Could somebody tell me more about the "with-local-vars"? I couldn't get the difference between "with-local-vars" and "binding".

6:45 liwp: vy: looking at the source it seems to me that with-local-vars creates new vars for the bindings, whereas binding rebinds the existing vars

6:45 I don't know what practical difference that makes

6:46 I guess if you call code in the body that uses global vars then with-local-vars will not work, i.e. it's not rebinding those global vars

6:49 pixelman: I'be been thinking about this lazy stuff -- does can clojure somehow cache stuff that's explicitly lazy?

6:50 yason: pixelman: what do you mean, like (memoize) ?

6:50 pixelman: I'm using compojure, and I would like to cache the result of certain calls to (html [...

6:50 the app would be snappier

6:51 liwp: vy: and one major difference is that, as the doc string says, you have to use (var-get) and (var-set) to access the var in with-local-vars

6:51 pixelman: looking at memoize

6:51 vy: liwp: I see. Thanks. (Reading the sources...)

6:52 yason: pixelman: (memoize your-page-generation-fn) and store that somewhere

6:52 liwp: vy: with with-local-vars you can set the var value in the body with (var-set)

6:53 yason: liwp: what's the point in that, i.e. what can you do that you can't with binding?

6:53 pixelman: yason: pretty cool! will try that.

6:53 liwp: yason: dunno, I'm trying to figure it out ;)

6:54 yason: liwp: IIRC in Practical Clojure there was a paragraph that usually vars and symbols can be mingled together but for certain cases it's important to recognize the difference -- ain't figured that out yet :)

6:54 liwp: definitely one major difference is the fact that with-local-vars does not rebind vars globally (as the name suggests)

6:55 yason: liwp: hmmm, but (binding) isn't global either, right?

6:56 liwp: yason: if you call a function from the binding body that reads a var that you've rebound, you'll get the new value rather than the orig value

6:56 i.e. (def a 1) (defn foo [] a) (binding [a 2] (foo)) will return 2

6:58 ,(def a 1) (defn foo [] a) (binding [a 2] (foo))

6:58 clojurebot: DENIED

6:59 liwp: ,(do (def a 1) (defn foo [] a) (binding [a 2] (foo)))

6:59 clojurebot: DENIED

6:59 liwp: have it your way then

7:01 LauJensen: Does anybody know who's behind disclojure.org ?

7:02 yason: liwp: I know binding but an example of with-local-vars would be enlightening

7:04 liwp: ,(with-local-vars [bb 1] (var-get bb))

7:04 clojurebot: 1

7:04 liwp: are slightly useless example :)

7:05 the interesting bit is that you have to use var-get and var-set to access the var

7:05 LauJensen: nvm

7:29 pixelman: I'm looking for a logging framework, should I just use log4j or is there some wrapper or such for clojure?

7:30 lpetit: ataggart created one in clojure.contrib

7:30 LauJensen: pixelman: You can wrap log4j using 1 macro, and I recommend that approach :)

7:31 pixelman: tnx!

7:45 vy: LauJensen: Were you the one who was asking yesterday how to log to a file via c.c.logging?

7:48 LauJensen: No, but I remember the talk @ vy

7:51 vy: Then do you know the answer? I couldn't figure out it too.

7:51 LauJensen: To me the answer is using log4j , for you, it may be patching c.c.logging

7:52 vy: LauJensen: You mean directly using log4j without c.c.logging wrapper?

7:52 LauJensen: That's what I did

7:52 I'm not saying it's for you though, I just try to stay out of contrib as far as possible

7:58 pixelman: c.c logging worked fine when the loglevel was accepted by log4j but crashed when I tried a :notice. still pretty slick though. I just want to log some stuff. :)

7:58 Fossi: out of curiosity: why's that?

7:58 LauJensen: out of curiosity: why's that?

8:00 LauJensen: Fossi: A lot of the code in contrib are small helpers/wrappers/utilities which help you abstract your problem - I get the best feel for the problem when I write these myself and sometimes that helps me refactor the code - if I didn't have all the code in my POV all the time, I don't think I'd refactor like I do, and I don't think I'd have as good a feel for it... and oh.. then there's the SQL thing :)

8:01 Fossi: understandable. in case you still look for new topics, i'd love a more elaborate blog post on that ;)

8:02 pixelman: what is the SQL thing?

8:02 LauJensen: I'm always looking for new topics :)

8:02 Fossi: kinda just explained the reasoning for the method of operation in the last few

8:03 *to me

8:03 ok, maybe that wasn't even an understandable sentence

8:03 LauJensen: pixelman: Kotarak and myself have developed ClojureQL which is a nice way to interact with databases, in contrib there's also an SQL wrapper, which I politically view as competition :) (just kidding)

8:06 pixelman: LauJensen: interesting, gotta look up your project :) I'm using the stuff in common now and finding it pleasant to use, but it's nice to see other approaches.

8:07 LauJensen: clojureql is radically different, because it lets you stick with your normal syntax, (query table1 [item id cost] (< cost 500)) for instance

8:07 spuz: LauJensen: very interesting, is that then just parsed and converted into normal SQL?

8:08 LauJensen: In some ways it's a matter of taste, in other we really provide functionality that you won't normally get, like specific backends for Mysql and Derby that provide FULL JOIN functionality etc etc, but read all about it on Gitorious :)

8:08 ~clojureql

8:08 clojurebot: clojureql is http://gitorious.org/clojureql

8:09 LauJensen: Then that's saved as a syntax tree, which you can do stuff with, like (group-by foo (query table ...)) and when you ask to have it executed, it's transformed to a valid SQL string and run through JDBC's .nativeSQL, and then executed

8:10 pixelman: can I access data lazily from mysql?

8:11 LauJensen: Yep, (run *con* (query table [x y z])) gives you a lazy result-sequence, instead of LIMIT you can then do (take 50 ) on it, instead of OFFSET you can use (drop) but that's costly, we're still working on that. When you've fully realized the seq, the connection closes

8:11 (drop was costly, not limit)

8:12 pixelman: neat!

8:12 spuz: LauJensen: that's very nice

8:15 LauJensen: Glad you think so - My last blog post is already 8.th on Dzone.com, it's amazing the interesting functional programming/clojure is generating these days - wonder if Rich's JVM talk has something to do with it :)

8:15 snowwhite: Does clojure have classes?

8:15 Chousuke_: yes and no.

8:15 spuz: LauJensen: was that the one about OO and time?

8:16 snowwhite: Chousuke_, as in?

8:16 LauJensen: spuz: A functional Brians Brain simulator

8:16 Chousuke_: snowwhite: it has classes because the JVM has them; however, actually directly making classes yourself is not very idiomatic.

8:16 spuz: LauJensen: I mean the jvm talk, there was one called Are we there yet I think. Is that the one you mean?

8:16 Chousuke_: snowwhite: the ability to create classes is mainly used for interop with Java.

8:17 LauJensen: spuz: To my great disappointment I still haven't heard the talk(s) but I'm thinking the OO vs Time could be it

8:17 snowwhite: Chousuke_, Can you show an example by pasting some code somewhere?

8:18 Chousuke_: snowwhite: hm

8:19 snowwhite: Chousuke_, thanks

8:19 Chousuke_: I don't have a gen-class example at hand right now :/

8:19 snowwhite: Chousuke_, :(

8:19 LauJensen: ~sofiaba

8:19 clojurebot: sofiaba is http://wiki.github.com/Lau-of-DK/sofiaba

8:19 LauJensen: snowwhite: I was forced to use gen-class in that :)

8:21 spuz: heh, I'm not sure a full blown 3d game is the kind of example snowwhite was looking for :p

8:21 Chousuke_: snowwhite: behind the scenes there are of course classes generated everywhere but you can accomplish quite a lot with Clojure without writing a single named class :)

8:21 LauJensen: I didn't implement Duke Nukem, so it's not full blown :)

8:22 Chousuke_: snowwhite: for example, every clojure function is its own class.

8:22 snowwhite: but you don't need to care about that :)

8:22 snowwhite: Chousuke_, hmm, but a small example could clarify a bit more?

8:22 spuz: it's interesting to see the classes generated by clojure, I put a very simple example through a decompiler to see what the byte code was doing and there's a lot more going on behind the scenes than you might think

8:22 Chousuke_: ,(class (fn []))

8:23 clojurebot: sandbox$eval__5228$fn__5230

8:23 Chousuke_: but of course, that's not very interesting to you.

8:23 for interop, you can often use proxy too

8:24 spuz: snowwhite: have a look at this for more info on class generation: http://clojure.org/compilation

8:26 Chousuke_: snowwhite: for interop without gen-class, you can have code like (.addListener someswingthing (proxy [ActionListener] [] (actionPerformed [e] ...))) ... proxy generates a class implementing ActionListener, but you don't need to care about what exactly it is called :)

8:27 snowwhite: Chousuke_, cool

8:27 Chousuke_, :)

8:27 Chousuke_: I guess gen-class enters the picture when people in Javaland need to be able to use it directly (and not through an interface)

8:28 or if you're implementing a main method.

8:55 Drakeson: is completion broken with slime + swank-clojure ?

8:55 or is it just my setup that's broken?

8:56 cschreiner: Drakeson: at the repl?

8:56 works fine

8:56 in the buffer, not so

8:56 (for me)

8:56 Drakeson: it doesn't comlete even in the repl

8:57 I updated everything couple of hours ago

8:57 cschreiner: did you first M-c k the file?

8:58 Drakeson: what is M-c k ? it is unbound here.

8:58 cschreiner: ah, C-c k, sorry

8:58 I'm sure you did

8:59 Drakeson: that's unbound, too

8:59 cschreiner: did you start slime?

9:00 Drakeson: sure

9:00 liwp: try C-h k TAB

9:00 in the repl

9:00 that should say that tab is bound to slime-indent-and-complete-symbol

9:01 Drakeson: liwp: it is.

9:01 jdz: LauJensen: i have not seen your latest blog entry, sorry

9:01 liwp: then I'm out of ideas :)

9:02 Drakeson: and it doesn't mentione any before or after advice?

9:02 Drakeson: well, if I could be sure that it is my setup that is broken, not the upstream ...

9:03 pixelman: what to use to read in config files? wrap properties? or yaml

9:05 liwp: pixelman: Properties can be dumped into a clojure map so it's definitely an easy way to get something working fast

9:06 Drakeson: liwp: I am trying to edebug the completion functions ...

9:06 liwp: ,((into {} (System/getProperties)) "path.separator")

9:06 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission * read,write)

9:06 liwp: blah

9:06 pixelman: liwp: yep, that's nice

9:07 liwp: the downside is that the keys are strings rather than keywords

9:08 ambient: anyone have the problem that after running a swing app, slime disconnects and I have to restart/reload everything?

9:09 liwp: ambient: many swing apps bind the close button to System/exit which will then kill your JVM and the slime connection

9:09 it's very frustrating when running stuff via slime

9:10 LauJensen: liwp, can't you just override it ?

9:10 ambient: it's ok if i just comment out the EXIT_ON_CLOSE part?

9:11 i don't know how to lessen the amount balls i have to juggle in air while trying to code swing/clojure with emacs/slime/clojure-mode

9:11 liwp: ambient: I think so, I think the default behaviour is to close the window and that's exactly what you want

9:11 LauJensen: sure, it just annoys me when I try out someone's clojure/swing app and closing it kills my repl

9:12 LauJensen: ok :)

9:15 ambient: heh, searching for 15 minutes on how to indent clojure code in emacs and a simple mark region + press tab does it :D

9:15 my google-fu is seriously lacking

9:16 liwp: ambient: also M-x indent-region would work

9:16 Drakeson: press tab? use M-C-\ after marking region.

9:16 Fossi: Meta-Q

9:17 indents the current region

9:17 no selection needed

9:17 danlei: I most often use C-M-q at the start of a sexp

9:18 Fossi: yeah, sorry, meta-q is paredit-indent

9:19 liwp: Drakeson: thanks for that - I'll have to try to remember it in the future

9:20 M-C-q also sounds good although I usually don't have to re-indent clojure code

9:21 danlei: I nedd it all the time :)

9:21 *need

9:21 liwp: I'm not sure why I don't need it, maybe it's because of paredit or because my yank reindents the yanked code

9:22 danlei: hm, I use paredit too

9:22 liwp: maybe I just leave my code in a massive mess and don't notice it 8-I

9:22 Drakeson: I rarely need that (maybe I press TABs too often). I only do a few C-x h C-M-\ during the day.

9:22 danlei: :)

9:24 liwp: self-reindenting yank sounds nice

9:24 should make mine behave like that too

9:24 liwp: danlei: it's very good with e.g. C++ and friends when you move stuff out of blocks

9:25 danlei: sure is

9:25 liwp: I can't remember where I picked it up from, probably emacs wiki

9:25 Drakeson: ok, what does (slime-eval '(swank:completions "ma" "user")) produce?

9:26 it doesn't give me any completion, and results in: (nil "ma")

9:26 liwp: Drakeson: I get a whole list of stuff, e.g. macroexpansion-1

9:27 (("macroexpand" "macroexpand-1" "main-page" "make-array" "make-hierarchy" "map" "map-invert" "map-str" "map?" "mapcat" "match-method" "match-uri" ...) "ma")

9:27 Drakeson: liwp: thanks. now I know there is something wrong with either swank-clojure or my setup.

9:28 liwp: this is the main problem with emacs: things sometimes break and it's difficult to figure out what's broken simply because your emacs setup is unique in the world

9:28 danlei: liwp: something like (lambda () (yank) (save-excursion (exchange-point-and-mark) (indent-sexp))) should work for lisp code

9:29 pixelman: ,(map #( list (keyword (% 0)) (% 1) ) {"foo" "FOO" "bar" "BAR"})

9:29 clojurebot: ((:foo "FOO") (:bar "BAR"))

9:29 pixelman: how can I build a map instead?

9:29 liwp: danlei: isn't your mark going to be in the wrong place when you're yanking?

9:30 danlei: it's untested, but I think it should work

9:30 liwp: pixelman: with reduce

9:30 pixelman: liwp: ok!

9:30 liwp: pixelman: something like (reduce #(assoc %1 (first %2) (second %2)) {} ...)

9:31 danlei: the yank-indent hack that I use adviced the existing yank, I'll see if I can find the URL for it

9:32 danlei: liwp: thanks. my thingie works, btw

9:32 but it should do everything pasted, not only a sexp (although that's what I most often paste)

9:32 s/do/indent/

9:33 liwp: danlei: http://trey-jackson.blogspot.com/2008/03/emacs-tip-15-indent-yanked-code.html

9:33 danlei: liwp: thanks!

9:34 liwp: np

9:37 danlei: ah, now I see what you meant, should move to the beginning of the line, too :)

9:38 pixelman: ,(reduce #(assoc %1 (keyword (first %2)) (second %2)) {} {"foo" "FOO" "bar" "BAR"})

9:38 clojurebot: {:bar "BAR", :foo "FOO"}

9:38 danlei: (or just press tab before yanking)

9:39 pixelman: liwp: thanks for the pointer :)

9:41 Chousuke: ,(into {} (map (fn [[k v]] [(keyword k) v]) {"foo" :bar}))

9:41 clojurebot: {:foo :bar}

9:45 liwp: Chousuke: what's the best way to turn a java HashMap<String, String> into a clojure map with keyword keys?

9:46 i.e. we talked above about using Java Properties for config and I can turn that into a clojure map with into, but I'm left with String keys

9:47 I could use your above code to change the keys to keywords except that the items in a Properties object are not pairs

9:47 chouser: what's wrong with string keys?

9:47 liwp: chouser: you can't do (:foo my-map)

9:47 not a big deal, but still

9:47 Chousuke: liwp: you can do (my-map "foo") though :)

9:47 liwp: yeah, I know

9:48 and also, I guess some of the strings won't be legal keywords anyhow

9:48 rhickey: ah, finally! - http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

9:48 Chousuke: (let [m {"foo" "FOO" "bar" "BAR"}] (zipmap (map keyword (keys m) (vals m))))

9:48 ,(let [m {"foo" "FOO" "bar" "BAR"}] (zipmap (map keyword (keys m) (vals m))))

9:48 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$zipmap

9:48 Chousuke: hmm

9:48 ah, damn

9:48 ,(let [m {"foo" "FOO" "bar" "BAR"}] (zipmap (map keyword (keys m)) (vals m))))

9:48 clojurebot: {:bar "BAR", :foo "FOO"}

9:49 Chousuke: I'm too used to paredit taking care of the parentheses :(

9:49 chouser: "Presented by Rich Hickey on Oct 01, 2009" Oops.

9:49 liwp: Chousuke: that'll work, thanks

9:59 spuz: What's the best way to add two vectors? I could do something like (map + [1 2] [3 4]) => (4 6) but this returns a list rather than a vector

9:59 Chousuke: just call vec on that :)

10:00 spuz: ok :)

10:00 I wonder if there is a more efficient way but we'll see if it is a performance problem later :)

10:01 ambient: vectors are often just arrays so you could use an actual array

10:01 Chousuke: arrays are mutable though.

10:01 vector aren't.

10:01 spuz: I don't think there's any more efficient way, besides using mutable data structures.

10:01 and you probably don't want that. :P

10:01 spuz: ok

10:02 ambient: using the GPU for numeric work

10:02 or dedicated math libs

10:14 namor: What is the advantage of STM over a synchronized "swap!" function?

10:14 chouser: namor: coordinated accees/mutation of multiple references.

10:15 liwp: namor: you can change multiple things as an atomic transaction

10:15 namor: Ok, i get it. Thanks.

10:16 raek: if I want to write yaml/load instead of org.ho.yaml/load (org.ho.yaml is a java package) how do I do it?

10:16 liwp: raek: import org.ho.yaml

10:16 yaml is the java class?

10:17 raek: no, the package

10:17 liwp: what's the clas?

10:17 raek: oh whait

10:17 org.ho.yaml.Yaml is the class

10:17 load is a static method of that class

10:17 then there's no problem :)

10:17 liwp: ok

10:19 raek: user=> (Yaml/load *in*)

10:19 - a

10:19 - b

10:19 - c

10:19 #<ArrayList [a, b, c]>

10:19 yay!

10:20 liwp: cool

10:21 is that all you have to do? Is the yaml lib easy to use from clojure?

10:21 raek: I have no idea... :) this is my first experience with yaml in clojure

10:22 the java containers can be used with clojure's sequence library

10:23 so traversing the yaml data shouldn't be any problem

10:24 konr: does (:import (java.awt *)) work?

10:24 Chousuke: no.

10:24 konr: Chousuke: hmm, is there an alternative?

10:25 Chousuke: no.

10:25 :)

10:25 chouser: konr: you're not going to use *all* the awt classes. Just list the ones you use.

10:26 somnium: it seems some libraries use def and namespaces to emulate mutable objects, though this is religiously discouraged. is there a run time difference between this and doing, for example, (ns config) (def config-state (atom {})) and using swap?

10:27 Chousuke: somnium: people expect defs to be immutable, or at worst thread-locally bound. :P

10:27 if it's an atom, it's *explicit* that it can change.

10:28 somnium: compojure defines an explicit redef that preserves metadata, for example

10:29 chouser: ew. really?

10:29 somnium: I'm new enough to lisp that I don't have any 'religious beliefs' about def, but I want to adopt best practices. I was just wondering if they're absolutely equivalent but one breaks convention and one doesn't

10:29 yeah, in control.clj

10:30 Chousuke: in any case, using def anywhere except top-level is wrong.

10:30 somnium: I'm not sure how it's used, they

10:30 also an immigrate macro but that just takes all the vars from a list of namespaces and puts them into one for convenience

10:31 Makoryu: Would it be possible to print warnings for any non-top-level use of def?

10:32 chouser: oh, I see. I think compojure's just doing that during app setup. That's slightly less evil.

10:32 somnium: I asked about doing that but was told it was absolutely evil and to use atoms :)

10:33 is there a way to list all the classes in a java package?

10:33 chouser: somnium: no

10:33 somnium: you can look at all the .class files in a directory or in a jar

10:36 somnium: hmm, thinking of a dirty way to do import org.foo.* by using the classpath to find all the classnames

10:37 anyway, under the hood, is evil-redeffing and atom swapping equivalent?

10:38 chouser: not quite

10:38 def uses a lock on the var. atoms do atomic-set-and-check

10:39 somnium: ok, so no reason not to use atoms when configuring state before launching the main loop to be explicit?

10:41 chouser: sure.

10:42 another benefit of using atoms is that if you decide later it needs to be a ref (to coordinate with other refs) much of your code will be very similar

10:42 replace swap! with alter, wrap in a dosync, done.

10:42 if you were redefing vars, you'd have to go find where you need to add @, fix your def calls, etc.

10:44 ambient: how do i refactor this into a shorter form? (Color. (bit-xor x y) (bit-xor x y) (bit-xor x y))

10:44 liwp: ambient: (let [c (bit-xor x y)] (Color. c c c))

10:44 ambient: ah.. *slaps forehead*

10:45 liwp: heh

10:45 somnium: I'm thinking of the way rails plugins go in and alter whatever core classes they're changing, it should be simple to decorate atoms with a logger to go and see exactly what happens during config

10:45 chouser: you wanted something trickier, perhaps. (#(Color. % % %) (bit-xor x y))

10:45 liwp: chouser: slightly shorter as well I think ;)

10:45 ambient: that seems oddly readable :o

10:46 liwp: (apply Color. (replicate 3 (bit-xor x y))) ?

10:46 chouser: plus it generates a whole new class for you under the covers.

10:46 spuz: chouser: I missed ambient's question, what is x and y?

10:46 ambient: image coordinates

10:47 xor function gives a cool image for testing purposes

10:48 spuz: heh, an image of what though :)

10:48 Fossi: xor

10:48 liwp: and x and y

10:48 Fossi: it plots the function :)

10:49 ambient: it's kinda the simplest fractal that i know of

10:50 spuz: I have a question, how can I get the decimal representation of a Ratio?

10:50 chouser: ,(double 7/3)

10:50 clojurebot: 2.333333333333333

10:51 spuz: chouser: thanks

10:53 rhickey: That infoq talk is one of my favorites

10:54 chouser: I'm watching it now. Did you just watch it?

10:54 rhickey: yep

10:54 slight slide lag in a couple of places, but I love that they sync the slides like that

10:54 liwp: must be weird watching yourself give a talk

10:55 chouser: yeah, that's good practical tech.

10:55 liwp: rhickey: yeah, that's a really nice feature

10:56 Fossi: repost (again ;-)): wouldn't it make sense to make all io methods and java calls to use an implicit io!?

10:56 rhickey: Fossi: no, many are functional

10:56 also overhead

10:56 Chousuke: rhickey: I just finished it. They cut out the question part at the end though (or were there really no questions? :/)

10:57 rhickey: they don't usually include the q/a part

10:57 there were a few, Joe Armstrong was in the audience :)

10:59 Fossi: too bad :(

11:00 somnium: what's the url?

11:00 rys: Joe is the Erlang guy?

11:00 liwp: rys: yep

11:01 somnium: http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

11:01 rys: Watched a nice thing with him and SPJ recently, can't rememeber the site though. InfoQ?

11:01 liwp: rys: this: http://www.infoq.com/interviews/armstrong-peyton-jones-erlang-haskell

11:01 ?

11:01 I haven't watched it yet

11:01 rys: Yeah, that's the one

11:01 It's quite funny

11:01 Chousuke: the thing about needing to model time hadn't quite sunk in before I watched that presentation, but I think it's clear now. good stuff, anyway

11:02 rys: Joe's really animated and SPJ just sits there, dead still

11:03 liwp: SPJ gets animated when he's launching missiles

11:04 sproingie: naw he's just lazy :)

11:04 liwp: ;-)

11:27 spuz: rhickey: hey, just watching your qcon talk. You say you made a talk the previous day, what was that talk about?

11:27 rhickey: spuz: an introduction to Clojure

11:27 spuz: is that available somewhere?

11:27 rhickey: not yet

11:28 the one they put up is the important one, new compared to all others

11:28 spuz: ok

11:28 rhickey: the intro has a lot of overlap with other talks I've given

11:34 spuz: rhickey: what kind of feedback do you get from people after these talks? Do you think you're winning the battle of converting people away from OO?

11:34 liwp: rhickey: should into be changed take multiple from collections as args? e.g. (into [] [1] [2] [3])

11:35 mark volkman was asking about it on the group

11:35 and is this an appropriate impl: (apply into (into x y) zs)))

11:38 rhickey: spuz: I think that talk was one of the more popular at QCon. There's a whole other set of issues in converting people... I'm not trying to do that, just explaining the ideas behind Clojure

11:43 liwp: I'm not sure about multiple args, not that important. could use (reduce into dest [xs ys zs])

11:43 Drakeson: liwp: can I ask you when you last updated your swank-clojure ?

11:43 liwp: sure

11:44 Drakeson: not too long ago I don't think

11:44 rhickey: I was looking for low hanging fruit to contribute. Is there anything urgent in assembla that no one's looking at?

11:45 sproingie: speaking of converting people from oo, there a doc out there about functional ways to replace is-a relationships?

11:45 i have a few tricks but it all feels pretty ad-hoc

11:46 rhickey: ,(derive ::square ::rect)

11:46 clojurebot: nil

11:46 rhickey: ,(isa? ::square ::rect)

11:46 clojurebot: true

11:46 ambient: square and rect are a good example of a devious not is-a relationship iirc

11:47 rhickey: liwp: anything marked for next release without patches is fair game

11:47 ambient: (a bit off-topic)

11:47 sproingie: square and shape then

11:47 rhickey: ambient: only in the face of mutation

11:47 liwp: Drakeson: maybe I haven't updated after all... git log gives me c1e309dfe53cb45149258404c4db5b53fb5c81b7 from april 17th

11:47 sproingie: the square/rectangle problem is a classic trick question. it _has_ no "right" answer

11:47 chouser: what?

11:48 rhickey: in what way is a square not a rectangle?

11:48 sproingie: if the contract for shapes says they have optional constraints, then there's a right answer

11:48 one-arg constructor to square violates substitution principle

11:49 rhickey: sproingie: you don't have an object yet when you call the ctor

11:49 so no substitution

11:50 sproingie: constructors usually aren't polymorphic anyway, so there's some argument that substitutability doesn't apply

11:50 wonder what liskov would say to that

11:52 been teaching myself scala for this whole week. love the syntax sugar, but soooooo much syntax.

11:52 i'd probably be half-done with my project if i started it in clojure instead

11:53 Fossi: any language with a construct like +: 1 2 fails :D

11:53 poor mans macros

11:53 somnium: I couldn't stand the syntax, too similar-yet-different to ruby

11:53 Makoryu: Fossi: Eh? What language would that be?

11:54 sproingie: eh my day job is perl, so i'm used to crazy syntax all over

11:54 Fossi: Makoryu: you could define +: as a prefix + operation in scala

11:54 Makoryu: Fossi: Ah

11:55 Fossi: the last char in the name defines the binding

11:55 excellent idea...

11:55 sproingie: +: would define a right-associative infix operator

11:56 you can't really define new prefix operators, they're hardwired to +-!

11:56 oh and ~

11:56 Fossi: ah. well. same, same really

11:57 pretty mad

11:57 vy: chouser: Any progress on " http://www.assembla.com/spaces/clojure/tickets/149-pop-does-not-preserve-meta-data (Actually, I'm just wondering the patch.)

11:57 #149

11:57 pop does not preserve meta-data

11:57 Makoryu: I still think the APL family has the craziest syntax

11:57 sproingie: i thought it was kind of crazy that ending with : would make a method right-associative. sort of flies in the face of what you'd expect for an operator that looked smalltalkish

11:57 Fossi: and absolutely overengineered and artificial

11:58 Drakeson: liwp: thanks.

11:58 Makoryu: Every function, regardless of the name, is either prefix or infix

11:59 sproingie: J makes perl look like cobol

11:59 Makoryu: Yep

11:59 liwp: Drakeson: yeah, I don't think I've upgraded since my slime-macroexpand-all work just fine. It got broken when some stuff got moved from contrib to core

11:59 although it might have been fixed now in swank-clojure head

12:01 chouser: vy: had totally forgotten about it

12:02 liwp: how's that for low-hanging fruit?

12:03 somnium: I wonder how hard it would be to emulate ruby semantics with clojure, wrap hash-maps with method missing, convert instance vars to atoms. maybe use | as a delimiter instead of ; due to the reader.

12:03 liwp: chouser: I thought it would be relatively simple to implement

12:04 chouser: then I noticed that the current implementation special cases transients and I wasn't so sure anymore ;-)

12:04 chouser: ahhh. :-)

12:04 somnium: as an example for the conversion from OO battle. I'm assuming C-syntax to lisp and OO to functional are separate battles

12:06 liwp: chouser: if you don't mind calling (transient) and (persist!) separately for each collection then it's easy, but calling them only once for the into call requires some more thinking

12:09 how do i get git to tell me where my repo was cloned from?

12:16 weissj: liwp: look in .git/config

12:16 liwp: weissj: thanks. There's nothing like 'svn info'?

12:16 weissj: liwp: there might be a command to show you that as well, but i don't know what it it

12:16 is

12:17 liwp: ok, thanks

12:18 Chousuke: git remote show origin

12:20 liwp: Chousuke: thanks. I'm sure I've seen that before.

12:20 Chousuke: one of my favourite features of git is the ability to have multiple remotes

12:21 makes it easy to track multiple repositories :)

12:21 liwp: Chousuke: with clojure are you working with a direct clone of rich's github repository?

12:21 Chousuke: well, yes and no.

12:22 liwp: I had my own clone on github and I cloned my working copy from that, but I'm not sure if that's the right thing to do w.r.t. patches

12:22 Chousuke: I have rich's repo as origin but I have my own github fork as a remote called "public" :P

12:22 liwp: this is some sort of higher git magic that I haven't seen yet

12:23 Chousuke: it's not too difficult

12:23 liwp: so if you branch locally, do you push those branches then to your gh repo?

12:23 Chousuke: sometimes

12:23 some I keep local

12:23 liwp: that was my main reason for having my own clone on gh, that I could save my branches somewhere

12:24 Chousuke: if I make bugfixes and such I base them on origin/master but then for example my reader branch tracks public

12:24 liwp: makes sense

12:24 just yesterday I nuked my gh clone and now I'm thinking I should recreate it and do something similar to what you're doing

12:25 Chousuke: git help remote, then :)

12:25 liwp: yep, I'll need to do some reading

12:25 Chousuke: (well, actually it's just git remote add remotename url-here)

12:26 liwp: so you clone a working copy from rich's repo and then add another remote to it (for example)?

12:26 Chousuke: that's one way

12:26 the repos actually don't even have to be related :P

12:26 liwp: and is there some easy way to push branches back to the remote? I managed to make it work, but it didn't seem obvious to me

12:27 that makes sense, but is also slightly scary at the same time :)

12:27 Chousuke: git push remotename localbranch:remotebranch

12:27 you can also make a branch "track" a remote branch so that you can just "git push" and "git pull"

12:27 liwp: will that possibly give the branch a different name on the remote?

12:27 Chousuke: yeah

12:28 you can omit the :remotebranch if you don't need that

12:28 liwp: I think that's what I did last time (tracking), which is actually what I wanted

12:28 Chousuke: so most of the time just git push remote branch

12:28 many scary things are possible with git ;)

12:29 liwp: so a 'git push' after a 'git push remote branch' will not push the branch changes to the remote?

12:29 since the branch is not tracked?

12:30 Chousuke: correct. but you can always configure the defaults afterwards

12:30 liwp: that's nice

12:30 Chousuke: git config branch.<branchname>.remote and .merge or something IIRC.

12:31 liwp: so you would recommend keeping my own clone on gh? I tend to do stuff both at home and at work so being able to share the repo via gh is nice.

12:31 Chousuke: well, I won't recommend anything... but it's what I do. :P

12:31 liwp: I was just worried about patches in that scenario, but it seems that having rich's repo as another remote fixes that

12:31 :)

12:32 thanks, I'll think about it

12:32 gott go

12:32 s/gott/gotta/

12:33 Chousuke: even with just one remote patches will not be a problem... unless you let your clone get too old so that you end up fixing things that are already fixed :P

12:35 liwp: Chousuke: I thought that might be the case, but I wasn't sure

12:36 I thought maybe the diff wouldn't apply in some cases if there were subtle changes so it would be safer to produce patches against the main repo

12:36 anyhow, now I really gotta go :)

12:38 danlei: about remote brances: I find it more convenient to "push origin foo", "co master" "branch -f foo origin/foo" that way, everything tracking is setup correctly and one hasn't got to mess with git config ...

12:38 Chousuke: -f?

12:38 danlei: force, yes

12:39 Chousuke: ah, right.

12:39 well, that's one way

12:39 danlei: the other thing works as well, of course, but I find it more convenient like this

12:46 steiger: (contains? [[1 2] [3 4]] [1 2]) -> false . is it a bug?

12:48 Chousuke: no.

12:49 contains? doesn't test whether a value is in a collection

12:49 it tests whether said collection has a value for a certain key :)

12:49 Makoryu: , (contains? {:foo bar} :foo)

12:49 clojurebot: java.lang.Exception: Unable to resolve symbol: bar in this context

12:49 Makoryu: , (contains? {:foo 'bar} :foo)

12:49 clojurebot: true

12:50 Makoryu: , true

12:50 clojurebot: true

12:50 steiger: oh

12:50 I see

12:50 Makoryu: ^ Is that defined as (def true 'true)?

12:50 steiger: the docs are a little bit confusing

12:50 Chousuke: Makoryu: no

12:50 Makoryu: it's special to the reader

12:50 Makoryu: Right

12:50 Chousuke: ,(class true)

12:50 clojurebot: java.lang.Boolean

12:50 Chousuke: ,(class 'true)

12:50 clojurebot: java.lang.Boolean

12:50 steiger: Chousuke: is there a function that tests wether a VALUE is present in the given collection?

12:51 Makoryu: ,(class 'pizza)

12:51 Chousuke: hmm

12:51 clojurebot: clojure.lang.Symbol

12:51 Chousuke: steiger: I'm actually not sure about that.

12:51 hiredman: (.contains '(1 2 3) 2)

12:51 ,(.contains '(1 2 3) 2)

12:51 clojurebot: true

12:51 Chousuke: oh, right, the Collection method :)

12:51 hiredman: ,(.contains '(1 2 3) 3)

12:51 clojurebot: true

12:52 steiger: hm, java contains

12:52 thank you guys

12:58 ben_m: Anyone have some example code for using sdljava with Clojure?

13:31 scottj: I often have trouble recognizing when to use map, reduce, loop, for, or lazy seqs that iterate or something. Anyone know of a tutorial (not necessarily in clojure, other functional languages would be fine) that focuses on helping imperative programmers to recognize when to use these methods?

13:31 ben_m: I've got a class Foo and a method bar that returns void (java interop). I'd like to create an object of Foo and call the method on it but return the created object, not the return value of bar ... is that possible?

13:32 vy: ben_m: What's wrong with (do (.bar foo) foo)?

13:32 ben_m: uh

13:32 sproingie: scottj: find out what the sources of events in your program are. now picture them as an infinite stream of events.

13:33 ben_m: vy: Not familiar with do, so I don't know. I'll look it up

13:33 sproingie: scottj: basically anything you can visualize as a timeline of state changes or events or messages or whatever you can convert to a sequence

13:36 reduce is handy for consuming a stream whenever you need to keep the previous state handy. probably not as necessary with STM tho.

13:36 *a stream of states

13:38 ambient: i wonder if asynchronous events will map 1-1 into seqs

13:39 it's something i've still yet to wrap my head around in fp

13:42 scottj: sproingie: thanks, but I guess what I'm looking for is a tutorial that breaks down common ways of using for/while loops and shows how to do them in fp

13:42 sproingie: you can block on a read of the event queue. there are probably better high-level constructs for that tho

13:43 i'm not entirely sure what they are myself. i'm only halfway-FP myself :)

13:49 technomancy: scottj: reduce is for when you want one value from a sequence; map is to transform one sequence into another.

13:49 sproingie: scottj: you can always break down for/while into recursion, which we have loop/recur for

13:50 technomancy: scottj: for is just syntax-sugar for map

13:50 doseq is like for, but intended for side-effects

13:50 sproingie: technomancy: reduce is also good when you never need the value back, but you want to derive the next action from the previous one

13:50 you can get a pipeline by reducing apply over functions, for example

13:50 technomancy: sure

13:50 ambient: doseq doall and dorun still confuse me

13:51 technomancy: or when you need something more specific (map, set) than a seq from a sequence

13:51 sproingie: right, like for building a tree

13:52 cons an empty tree onto the list and reduce the insert func over it

13:52 technomancy: sproingie: reduce takes an optional initial value; no need to conj it to the list

13:53 sproingie: yah i haven't translated all my idioms to clojure yet :)

13:54 ben_m: Is there something like an infinite loop in clj? (gameloop in my case)

13:54 sproingie: more useful with the optional arg since you don't have to screw up a nice homogeneous collection that way

13:54 ben_m: a loop/recur with no base case

13:54 or a for or reduce over an infinite sequence

13:54 chouser: ben_m: (fn [] (recur)) or (while true ...)

13:54 ben_m: Ah, didn't know while exists. Thank you :)

13:55 sproingie: or just plain while, yah. havent memorized the API yet :)

13:55 ben_m: http://clojure.org/api

13:55 chouser: 'while' is very rarely used

13:55 ben_m: I think the best way would be to use loop, since i'm using let anyways

13:55 sproingie: actually that probably doesn't have control structures in it, since those are usually special forms

13:55 chouser: but it yells "imperative" which can be useful

13:55 sproingie: but that page has a link to those

13:56 technomancy: anyone want to fix up swank-clojure's eldoc to indicate macros differently?

13:56 or am I going to have to implement that myself? =)

13:57 sproingie: just don't infinitely loop by mapping over an infinite sequence. unless you like space leaks :)

13:57 chouser: map will just return a lazy seq and do nothing.

13:58 sproingie: something would have to consume that. which i guess can't be map.

13:59 chouser: right. would have to be something like (loop [xs (map ...)] (recur (next xs))) ... which wouldn't leak anything

13:59 Drakeson: what does (remove-ns 'swank.commands.completion) do at the begining of the file?

14:00 chouser: though it would churn memory needlessly.

14:00 (doc remove-ns)

14:00 clojurebot: "([sym]); Removes the namespace named by the symbol. Use with caution. Cannot be used to remove the clojure namespace."

14:01 Drakeson: it is being used before defining (na swank.commands.completion ...), and I don't understand the intent

14:03 (not to mention that swank completion is broken here, since the revision from around Sept 15)

14:04 technomancy: Drakeson: can you give an example of the breakage?

14:04 ben_m: Trying to do SDL programming with Clojure is pretty hard if you don't know Clojure that well and sdljava is pretty ... strange.

14:05 Drakeson: technomancy: I am looking at swank_c_p_c.clj, (a small file)

14:07 in the definition of `completions' there is a try..catch that aborts the completion in case of any error. I change it to actually see the error.

14:07 (well, I forget to say, the initial problem was that I was getting no completions)

14:08 the error message was this: "java.lang.IllegalStateException: Var swank.commands.completion/potential-completions is unbound."

14:08 sproingie: so when i hit C-c C-k in slime and it tells me there are errors, how do i make it actually show me the error?

14:08 technomancy: sproingie: they should be shown in the *inf-lisp* buffer

14:09 hoeck: ben_m: you can try processing, there is rosado's clj-processing, a thin clojure wrapper around it, using it with success for a small clojure space duel game

14:10 technomancy: clj-processing is awesome

14:10 ben_m: Oh, I've heard about processing.

14:10 I'll take a look at it, thank you :)

14:10 technomancy: might not be as performant as sdl

14:10 sproingie: shown and then some. massive traceback obscures the actual error

14:10 ben_m: sdljava is a pain to use ... I'm getting a link error now for some reason

14:11 ambient: i could be possible just to use java sound and io api, plus straight opengl

14:11 or jmonkeyengine

14:11 Drakeson: I just copied the functions from swank.commands.completion into swank_c_p_c.clj, and it works. I just don't understand the mechanism that is supposed to load the stuff in swank.commands.contrib/

14:13 ben_m: ambient: Can't use OpenGL at the moment because my video card broke :/

14:14 Else I'd probably use one of the available Java game libraries

14:15 Drakeson: is the line (remove-ns 'swank.commands.completion) at the begining of swank.commands.completion really necessary?

14:16 technomancy: Drakeson: my guess is that it's not necessary for regular usage, but it might be needed to hack on swank-clojure itself interactively

14:16 I'm not too familiar with the completion mechanism though; I find that "dumb" dabbrev is enough for me

14:17 Drakeson: when I remove it, it can successfully load swank.commands.contrib.swank-c-p-c.

14:18 it is not really a matter of completion. I just don't understand what that defslimefn swank-require in swank/commands/contrib.clj was supposed to work.

14:18 it might be missing something

14:18 deafmacro: Hi! I tried righting "member?" to get a hang of using loop/recur. I would appreciate it if someone could review it. Here's the link http://pastie.org/639697

14:20 Chousuke: the x loop parameter is redundant :)

14:20 otherwise that should be okay.

14:21 though, (some (partial = x) coll) does the job :P

14:21 ben_m: How do I fix an UnsatisfiedLinkError?

14:22 Do I miss something on the classpath, or .. ?

14:22 deafmacro: Chousuke: ah true :)

14:22 Drakeson: wow! I didn't know about java completion in swank ... that's neat.

14:23 technomancy: Drakeson: I heard about that but haven't gotten a chance to take a look yet

14:23 imho that's much more valuable than lisp-level completion. =)

14:24 deafmacro: Chousuke: but I would still have to bind write (loop [coll coll] ... since it requires even args?

14:24 ben_m: I thought defn is like an implicit loop?

14:25 Drakeson: technomancy: it does not complete java.lang.Inte<TAB>, yet, but it completes java.lang.Integer/<TAB>

14:25 technomancy: cool

14:26 is that using the same C-c TAB?

14:26 Drakeson: no, just TAB

14:26 technomancy: Drakeson: you must have rebound it; needs C-c TAB here

14:26 TAB is for indentation. =)

14:26 Drakeson: well, I am in repl now

14:27 ambient: I do C-c I for Java classes, which inspects them. almost as good as completion, but not quite. don't know of a better way

14:27 technomancy: Drakeson: oh, gotcha.

14:27 C-c I is really great too

14:32 deafmacro: Chousuke: never mind. figured it out. thanks!

14:37 durka42: deafmacro: you have a brilliant username. that is all.

14:53 ben_m: Is there a way to import everything from a namespace?

15:07 weissj: can someone recommend a library or strategy for storing clojure data in a db? i am working on a defect tracking system, one feature i intend to have is user-created record types, so it's a bit more dynamic than straight db tables.

15:08 i checked out clj-record, that might work for me, is there anything else?

15:09 tmountain: weissj: strategies for storing data, or data serialization?

15:09 weissj: storing data

15:11 the data structure isn't complex, but i want it to be dynamic - can remove fields from a record or add them during runtime

15:11 tmountain: weissj: AFAIK, clojure-contrib has a sql library (JDBC wrapper), there's persist (Java lib), and also Berkeley DB

15:11 weissj: BDB is more of a key / value store IIRC

15:11 weissj: tmountain: yeah that's a bit too simple for my purposes

15:14 tmountain: weissj: have you seen datalog?

15:27 roberto_: ping

15:34 chouser: (.show (proxy [java.awt.Frame] [] (paint [g] (dotimes [y 256] (dotimes [x 256] (.setColor g (#(java.awt.Color. % % %) (bit-xor x y))) (.fillRect g x y 1 1))))))

15:36 also nice with bit-and or bit-or instead of bit-xor

15:46 * adityo_ yawns ..good night folks

15:46 crios: 'night

15:47 ambient: how would i go about making a graphics element into a repl that i could asynchronously draw different stuff? like (start-graphics g) (draw-line g 10 10 20 20) etc...

15:50 chouser: ambient: (def g (.getGraphics (doto (java.awt.Frame.) .show)))

15:51 position that window so you can type into your repl with obscuring it

15:51 then: (.drawLine g 100 100 200 200)

15:51 ben_m: When I try to compile my program (clj -cp /usr/share/java/sdljava.jar sdl.clj) I get the following error: "Exception in thread "main" java.lang.UnsatisfiedLinkError: sdljava.x.swig.SWIG_SDLEventJNI.new_SDL_Event()J (sdl.clj:1)" Code: http://sprunge.us/KJJC

15:52 ambient: chouser thanks :)

15:52 chouser: ben_m: you have to have the swig-generated .so in your OS library path. I think that's the most likely cause.

15:53 ambient: my previous attempt was to draw a line (10 10 20 20) which I thought didn't work because it was drawn under the window border

15:54 ben_m: chouser: sigh ... :/

15:54 chouser: (.show (proxy [java.awt.Frame] [] (paint [g] (dotimes [y 256] (dotimes [x 256] (->> (+ (* x x) (* y y)) (* 0.01) Math/sin inc (* 127) int (#(java.awt.Color. % % %)) (.setColor g)) (.drawLine g x y x y))))))

15:56 ben_m: What's that ->>?

15:56 chouser: It's a macro a bit like ->

15:57 (->> a (foo b) (bar c)) becomes (bar c (foo b a))

15:57 that is, each expression is inserted as the last arg of the next expression

15:58 ben_m: Did you define it, or is that in Clojure?

15:58 chouser: it's new, in Clojure

15:58 ben_m: ooh :)

15:58 chouser: (doc ->>)

15:58 clojurebot: excusez-moi

15:59 chouser: too new for clojurebot

15:59 ben_m: too new for me too :)

16:12 hiredman: clojurebot: ant?

16:12 clojurebot: is equivilant to addresing the bot by name is equivilant to addresing the bot by name

16:12 hiredman: clojurebot: ant is dumb

16:12 clojurebot: You don't have to tell me twice.

16:13 hiredman: ugh

16:14 I've started to see errors like java.lang.NoSuchMethodError: clojure.lang.RestFn: method <init>()V not found (fnparse.clj:1) everywhere

16:15 chouser: hiredman: clean and rebuild fnparse, probably.

16:15 hiredman: that was from starting clojurebot just now, but I have was seeing something very similar when trying to get ant to build something for appengine

16:15 and fnparse was not used there

16:16 chouser: I see those all the time from contrib because I keep hoping between various versions of clojure.

16:16 hopping

16:17 hiredman: ah

16:17 the error went away when I rebuilt contrib

16:17 ,(doc ->>)

16:17 clojurebot: "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc."

16:18 hiredman: damn

16:18 sorry

16:18 kotarak: huh? ->>? hoorray!

16:21 chouser: , (->> (range 256) (filter #(or (<= 65 % 90) (<= 97 % 122))) (map char) (apply str))

16:22 oh, whoops

16:22 ,(->> (range 256) (filter #(or (<= 65 % 90) (<= 97 % 122))) (map char) (apply str))

16:22 clojurebot: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

16:22 hiredman: handy dandy

16:22 ambient: ,(* 0.01745329252 180)

16:22 clojurebot: 3.1415926536

16:23 crios: clojurebot: logs

16:23 clojurebot: logs is http://clojure-log.n01se.net/

16:25 chouser: ,(.show (java.awt.Frame.))

16:25 clojurebot: java.awt.HeadlessException: No X11 DISPLAY variable was set, but this program performed an operation which requires it.

16:25 chouser: oh, right.

16:27 crios: hi, I already posted this question but it seems it get lost in the net: did anyone read "Structure and Interpretation of Computer Programs", by Abelson, Sussma? If yes, do you think it could be an worth introductory "clojure" concepts textbook?

16:28 [this one: http://mitpress.mit.edu/sicp/full-text/book/book.html]

16:28 ambient: i've read some of it and it has helped

16:28 johnmn31: when doing (defn add1 [x] (+ x 1))

16:28 kotarak: someone made a blog with translations of the code. (maybe the book-Stuart?)

16:28 crios: I believe, for a Java programmer an introductory "Lisp" world book would help

16:29 thanks ambient

16:29 johnmn31: does this "expand" at runtime to (defn add1 ([x] (+ x 1))) ?

16:29 kotarak: crios: touch yourself scheme in fixnum days

16:29 teach

16:29 hiredman: johnmn31: no

16:29 ambient: clojure doesn't just have functional style, it has immutable data structures and strong concurrency constructs

16:30 crios: kotarak: "fixnum days" ?

16:30 johnmn31: hiredman: well, defn "expands" to (def (fn [.. right?

16:30 ambient: crios it's going to take a lot of work (at least it did for me) to grok it all, but i think it's worth it

16:30 johnmn31: I mean (def foo (fn [...

16:31 crios: kotarak: I got it: http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-1.html

16:31 kotarak: crios: well, I didn't choose the title. ;) In Scheme numbers are stored in fixnums, that is in 32 (or 64) bit. When the grow larger they are saved in Bignums.

16:31 hiredman: johnmn31: yes

16:31 johnmn31: k thanks

16:32 arohner: is there a clojure.contrib fn for calling (read) on a string?

16:32 kotarak: crios: it's for Scheme, but that should be sufficient for lispiness.

16:32 hiredman: johnmn31: macroexpand and macroexpand-1

16:32 kotarak: ,(doc read-string)

16:32 clojurebot: "([s]); Reads one object from the string s"

16:32 ambient: crios you've looked at this, right? http://java.ociweb.com/mark/clojure/article.html

16:32 arohner: kotarak: thanks

16:32 that's new since the last time I needed to do this

16:33 crios: ambient: yes, and read also "Clojure Programming". But I feel I'm missing something

16:33 ambient: just write some code

16:34 johnmn31: hiredman: tried that, but (macroexpand add1) didn't get me what I expected.

16:34 hiredman: johnmn31: that is not how you use macroexpand

16:35 kotarak: ,(macroexpand-1 '(defn add1 [x] (+ x 1)))

16:35 clojurebot: DENIED

16:35 crios: ambient: yes, I write some code, but I feel I miss perhaps the right "conceptual" world's view - a shared vocabulary

16:35 ambient: sicp lectures were quite eye opening in some parts

16:35 johnmn31: ah, ok, I forgot the '

16:36 crios: ambient: ok, I'll read it (keeping to check also your blogs and chat, sure :) )

16:37 johnmn31: ahah! it does add parens:

16:37 (def add1 (clojure.core/fn ([x] (+ x 1))))

16:38 hiredman: but not in the defn form

16:38 johnmn31: so one could make mulit-arity lambdas as well then...

16:39 hiredman: sure

16:39 johnmn31: sweet

16:41 chouser: Revenue on T-shirt sales is rolling in at a steady clip of about $2.50 per month.

17:35 ambient: does clojure in future have some more revealing ways of communicating about errors?

17:36 im just having a bit of a difficulty in debugging

17:36 (which is happily easier in functional style because i can test each piece of my program separately)

17:40 arbscht: ambient: c.c.trace can help debugging in some cases

17:47 hiredman: wheee

17:47 appengine app built (hello world page)

17:48 and it runs on the local dev server thing

17:48 ambient: with clojure? grats

17:48 arbscht: compojure?

17:48 hiredman: yeah

17:48 arbscht: neat. a few people have been doing that lately

17:49 hiredman: the shellscript for launching the local dev server of course has #!/bin/bash but if you change it to #!/bin/sh it runs fine

17:49 * hiredman hates #!/bin/bash shebangs

17:49 ambient: hmm, i wonder how that works in windows...

17:49 probably not at all

17:49 hiredman: there is a seperate .cmd script for launching it on windows

17:50 ambient: got to try that someday soon

17:50 on my list of things to do

17:51 hiredman: I followed a howto I fould googling "clojure appengine"

18:07 somnium: hiredman: do you have the repl setup for it?

18:07 http://www.hackers-with-attitude.com/2009/08/intertactive-programming-with-clojure.html

18:08 it shows how to setup the appeninge api for the thread you run the devserver in, so you do live lispy development without any recompiles locally

18:09 ben_m: Alright guys, this is driving me insane.

18:10 I've got /usr/share/sdljava.jar and a lot of *.so files in /usr/lib/sdljava/ ... I try to run a little example like this: clj -Djava.library.path=/usr/lib/sdljava/ -cp /usr/share/java/sdljava.jar SDL.clj

18:10 When I leave out the -D line, I get an UnsatisfiedLinkerError

18:10 When I include it, I get Exception in thread "main" java.io.FileNotFoundException: -Djava.library.path=/usr/lib/sdljava/libsdljava.so (No such file or directory)

18:11 Without the libsdljava.so at the end, that was the wrong line I pasted, but yeah, same error

18:11 ambient: "/usr/share/sdljava.jar" "/usr/share/java/sdljava.jar" different directory

18:11 ben_m: ambient: I'm using the right ones when I try it, sorry.

18:11 Just typed them here incorrectly.

18:13 ambient: are the binaries compatible?

18:14 JVM & libsdljava.so etc

18:14 i got some weird errors using 32 bit libs in 64 bit environment

18:15 ben_m: uhm

18:15 All the .so files are 32bit libs, and I'm on 32 bit too.

18:17 Errors + Source + commands I run: http://sprunge.us/ZdTU

18:21 ambient: i wonder how two -cp commands work in java executalbe, do they replace or concatenate

18:21 it might be in the clj script, just a thought

18:22 hiredman: yeah

18:22 the clj script is trying to pash the -D stuff as a file name argument to java

18:22 pass

18:22 use java -Dwhatever directly

18:31 ben_m: I'll try.

18:33 I get the same UnsatisfiedLinkError :(

19:24 somnium: is there support for variable arity multimethods?

19:27 arbscht: somnium: yes

19:28 somnium: could you give a simple example? I wasn't able to improvise the syntax

19:30 (defmulti foo (fn (....) (....)) and then (defmethod foo ([a] ...) ([a b] ...)) ?

19:31 arbscht: http://gist.github.com/200252

19:32 somnium: ah, thank you

19:56 rsynnott: anyone know is there a way to view repl history in enclojure with keyboard shortcuts?

20:01 danlei: ctrl+uparrow

20:02 (if you meant input hist)

20:03 plain pgup otherwise

20:06 rsynnott: ah, thanks :)

20:07 CTRL-SHIFT-UP on the mac, oddly

20:07 (I'm mostly an EMACS/slime person, but giving this thing a go)

20:08 danlei: I have it installed, but use emacs almost exclusively (wanted to know at least one alternative)

21:16 cschreiner: clojure needs to be distributed together with emacs as a one-install-package targeted newcomers

21:17 hiredman: ~google clojurebox

21:17 clojurebot: First, out of 28 results is:

21:17 Clojure Box, alpha - Clojure | Google Groups

21:17 http://groups.google.com/group/clojure/browse_thread/thread/6fd17fb97f058192

21:18 cschreiner: for mac?

21:18 arbscht: iirc, clojure-mode has an install routine that makes it quite easy to get started

21:19 cschreiner: arbscht: you're missing my point

21:20 it's too easy to get lost in emacs

21:20 but when you get use to it, it rocks the world

21:21 and when you are adding "common" components, like compojure, or this 3d thing, I don't recall; (penumbra?) you have to deal with the ugliness of classpaths, in addition!

21:22 Raynes: If you want to use Emacs, you're probably better being committed to learning Emacs, rather than wanting and expecting to be spoon-fed Emacs with a dumbed down installation. If you don't want to learn Emacs, Enclojure is always an option.

21:22 arbscht: I'm not convinced there is any way around that -- such is emacs. even if there was, it has little to do with clojure, which is independent of any editor

21:22 cschreiner: from the perspective of a beginner, this is daunting

21:23 albino: emacs is like any other piece of technology, the learning curve has a pay off

21:23 arbscht: a beginner would do well to learn emacs first, or avoid it altogether

21:23 albino: I would vote for avoidance so you're not trying to learn two big technologies at the same time, but that's just me

21:23 Raynes: arbscht: Exactky.

21:23 cschreiner: my point is to get up and running with clojure (with most of the libraries preinstalled) in as little time as possible

21:23 Raynes: exactly*

21:24 cschreiner: Then you would want to just install Enclojure.

21:24 Or Clojure-dev, or whatever.

21:24 cschreiner: but are they good?

21:24 and what about customization?

21:24 arbscht: they're suited to your constraint :)

21:24 Raynes: Enclojure is fine, Clojure-dev leaves a lot to be desired, and La Clojure is pretty good.

21:25 cschreiner: ~google enclojure

21:25 clojurebot: First, out of 248 results is:

21:25 enclojure - home

21:25 http://enclojure.org/

21:25 Raynes: cschreiner: You need to decide what you want. Do you want superpowers and customization, or do you want to get up and running with Clojure really fast?

21:26 You can't really have one or the other unless you're already an Emacs user. ;)

21:26 cschreiner: first up and running, then superpowers

21:26 everybody wants to have superpowers

21:26 most geeks anyway

21:29 enclojure seems to suit my needs, thx

22:25 Drakeson: how can I get a lazy random sequence?

22:28 chouser: ,(take 20 (repeatedly #(rand-int 100)))

22:28 clojurebot: (45 59 66 15 15 27 40 4 29 10 74 77 17 99 17 12 13 33 31 83)

22:29 Drakeson: thanks

23:32 how can I apply a function to all vals of a hashmap and obtain a "transformed" hashmap?

23:33 chouser: ,(

23:33 clojurebot: EOF while reading

23:34 chouser: ,(let [m {:a 1, :b 2, :c 3}] (zipmap (keys m) (map #(* 5 %) (vals m))))

23:34 clojurebot: {:c 15, :b 10, :a 5}

23:35 Drakeson: right now I am doing (defn map-map [h f] (apply hash-map (mapcat (fn [[k v]] [k (f v)]) h))), which looks inefficient

23:35 chouser: thanks

23:35 is there a function for that?

23:39 kevin__: are (keys m) and (vals m) going to have a stable ordering?

23:42 slashus2: only in a sorted-map

23:42 well..

23:44 kevin__: that's what i figured, so calling them seperatly to map a hash would be unsafe right?

23:46 slashus2: ,(keys (apply hash-map [6 8 1 2 3 4 5 6]))

23:46 clojurebot: (1 3 5 6)

23:46 slashus2: I am not sure... hmm

23:46 hiredman: ,(let [h {:a 1 :b 2} f (fn [f v] (reduce #(conj %1 [(key %2) (f (val %2))]) {} v))] (f inc h))

23:46 clojurebot: {:b 3, :a 2}

23:49 slashus2: ,(keys (apply hash-map [:c 8 :a 2 :b 4 :d 6]))

23:49 clojurebot: (:a :c :b :d)

23:49 slashus2: ,(keys (apply sorted-map [:c 8 :a 2 :b 4 :d 6]))

23:49 clojurebot: (:a :b :c :d)

23:50 ngoc: How to remove element from a hash? I can use "remove", but it is long way because it takes a function.

23:50 kevin__: ,(let [h {:a 1 :b 2 :c 3 :d 4}] [(keys h) (vals h)])

23:50 clojurebot: [(:a :b :c :d) (1 2 3 4)]

23:50 kevin__: ,(let [h (apply hash-map [:a 1 :b 2 :c 3 :d 4])] [(keys h) (vals h)])

23:50 clojurebot: [(:a :c :b :d) (1 3 2 4)]

23:51 hiredman: ngoc: dissoc

23:51 kevin__: same wrong order this time, i guess that's ok

23:51 slashus2: :-(

23:53 ngoc: hiredman: thanks

23:53 kevin__: i was concerned that since they were unordered, keys and vals might be unordered in different ways

23:54 so if you zipmap'ed them back you would associate the wrong keys and vals

23:55 hiredman: some future IPMap migth do that

23:59 ngoc: hiredman: I also notice that "remove" changes the class of the hash to sequence

23:59 (def h {:a 1, :b 2})

Logging service provided by n01se.net