#clojure log - Nov 01 2011

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

0:08 eggsby: how could I rewrite this in clojure? http://pastie.org/2791611

0:09 I'm trying to work through the little schemer using clojure :|

0:11 brehaut: eggsby: im not exactly sure what the equivalent is in clojure, it seems that theres a bit of conceptual mismatch

0:12 eggsby: just my luck :)

0:12 yacin: (not (coll? x))

0:12 would probably be sufficient

0:12 brehaut: yacin: good thought

0:12 yacin: atom? in that context means not null and not a list made with cons

0:13 brehaut: (def scalar? (complement coll?))

0:13 eggsby: hmm ya that seems like such a loose definition yacin

0:13 hiredman: coll? checks for IPersistantCollection

0:13 so most java collections fail

0:15 eggsby: hmm. Maybe I should work my way through scheme before moving to clojure :) Seems there's a bit of impedance mismatch between them

0:15 I figured a lisp would be a lisp :(

0:16 brehaut: eggsby: depends what your motivation for learning scheme and / or clojure is, but why not just go straight to clojure?

0:16 hiredman: well, really a lot of lisp related literature just tasks lists and cons cells, but common lisp and scheme both have other datastructures

0:16 no idea how pair? would deal with a vector in scheme

0:16 eggsby: brehaut: I just picked up this book 'the little schemer', my motivations are just to understand recursion/functional programming better

0:16 yacin: pair? checks for stuff made with cons

0:17 hiredman: they are more in your face in clojure because there is a literal syntax for them and used everywhere

0:17 eggsby: I have some friends who use clojure and love it, so I figured it'd be a nice lisp to try. I was going to try to adapt the book to clojure

0:17 hiredman: yacin: there is a cons in clojure, but it doesn't create cons cells

0:17 so you cannot use it to create pairs

0:17 yacin: i'm aware

0:18 hiredman: so there are no pairs

0:18 so (def pair? (constantly false))

0:18 eggsby: I saw the strangeloop talk by rich hickey, "simple made easy", was a big vote of confidence for the language to me

0:18 technomancy: couldn't you count a MapEntry as a pair?

0:19 hiredman: depends how fast and loose you want to be

0:19 https://github.com/hiredman/tuples <- you could call a Tuple2 a pair

0:19 brehaut: hiredman: im curious, does clojure.lang.Cons count as a cons cell?

0:19 hiredman: not in the same sense as cons in scheme or cl

0:20 c.l.Cons is always proper

0:20 so it is always a list

0:20 (seq really)

0:20 brehaut: hiredman: by proper do you mean that it cant be used as a dotted pair?

0:20 hiredman: yes

0:21 brehaut: aha. thanks

0:23 hiredman: IPersistantList is a classical linked list under the covers, but the links are not exposed

0:52 jayunit100: i want to calculate the same thing "n" times.... is there a good function template for that [consider an iterative algorithm , like newtons method, for example]

0:52 technomancy: (doc iterate)

0:52 clojurebot: "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

0:53 jayunit100: excellent !

0:53 i always knew iterate wa good fur sumthin

0:54 TheBusby: if you call something like (macro foo), the macro will receive "foo" as the argument. How can I do (macro foo) where the macro will receive the value bound to "foo"?

0:57 without modifying the macro being called.

1:13 gtrak``: what's foo?

1:13 TheBusby: (def foo 5)

1:14 I think I'm trying to find the value of a symbol passed to a macro

1:14 gtrak``: the value of the symbol?

1:14 ,'foo

1:14 clojurebot: foo

1:14 gtrak``: like that?

1:15 ,(str 'foo)

1:15 clojurebot: "foo"

1:15 gtrak``: (class 'foo)

1:15 ,(class 'foo)

1:15 clojurebot: clojure.lang.Symbol

1:15 gtrak``: there you have it

1:18 (eval 'foo)

1:19 ,(eval 'foo)

1:19 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

1:25 mange: Macros are run at compile time, so in what environment do you want the value of the symbol? The run time environment doesn't exist yet.

1:28 TheBusby: ahh,

1:30 gtrak``: Thank you, that was it! So the only way to get the value of a symbol is with eval.

2:20 michaelr525: hey

2:33 TheBusby: hey?

2:33 clojurebot: hey is for horses

2:34 Raynes: Grass is sheaper.

2:34 Cheaper*

2:35 michaelr525: grass is cheaper to grow @ home

2:41 TheBusby: atleast there is an alternative spelling, not like "sake"

2:47 michaelr525: what's wrong with sake?

4:01 minsa: what would be clojure equivalent of the following list comprehension in haskell:

4:01 rightTriangles = [ (a, b, c) | c <- [1..10], b <- [1..10], c <- [1..10], a^2 + b^2 == c^2, a+b+c == 24]

4:03 opqdonut: rewrite that comprehension using map and filter, then you can straightforwardly translate it to clojure

4:04 the other option is ##(for [a (range 1 10) b (range 1 10) c (range 1 10) :when (= (* c c) (+ (* a a) (* b b))) :when (= 24 (+ a b c))] [a b c])

4:04 lazybot: ⇒ ()

4:04 minsa: ok.

4:04 opqdonut: oh, did I typo something there?

4:05 right,

4:05 ##(for [a (range 1 11) b (range 1 11) c (range 1 11) :when (= (* c c) (+ (* a a) (* b b))) :when (= 24 (+ a b c))] [a b c])

4:05 lazybot: ⇒ ([6 8 10] [8 6 10])

4:08 minsa: opqdonut, thnx a lot.

4:11 opqdonut: minsa, np

8:58 jweiss: tried to google for the meaning of this error (migrating to clojure 1.3), but found no answers: "Caused by: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V"

9:01 opqdonut: wow

9:09 llasram: jweiss: I think I might have run into that before, but my memory isn't fully jogged... More context?

9:11 jweiss: llasram: http://paste.lisp.org/display/125616

9:11 i get the exception on the first line of the defn

9:12 llasram: i saw a transcript of this channel where someone was discussing this error, they were saying NoSuchMethodError only occurs with AOT compiled code... but I don't think i have any

9:13 * jweiss checks

9:13 llasram: Ah, that was it! I had stale AOT code sitting around. Sorry if that isn't helpful in your case

9:16 jweiss: llasram: yup, that was the case for me as well, lein clean fixed it

9:16 llasram: Awesome!

9:16 jweiss: wow, i stopped AOT compiling a long time ago, didn't realize those class files just sat around :)

9:18 llasram: They do seem to hang... I think I saw a few days ago that technomancy wanted to figure out when people find the need `clean' and fix those situtations. Maybe a future release of leiningen will detect stale AOT class files (or do it better? not sure if it tries to today)

9:28 jweiss: another strange clojure-1.3 upgrade error is sudden inability to recognize java.io.Writer classname - now have to explicitly import?

9:31 llasram: Huh. It seems kind of random that <1.3 would randomly import a few java.io classes into your namespaces anyway. That may have been a bug?

9:33 jweiss: llasram: IIRC in clojure 1.2 you didn't have to import java.lang and java.io

9:35 fdaoud: ,(new String "test")

9:35 clojurebot: "test"

9:35 fdaoud: ,(new File ".")

9:35 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: File, compiling:(NO_SOURCE_PATH:0)>

9:36 Bronsa: ,*clojure-version*

9:36 clojurebot: {:major 1, :minor 3, :incremental 0, :qualifier nil}

9:36 llasram: ##(File. ".")

9:36 lazybot: java.lang.IllegalArgumentException: Unable to resolve classname: File

9:36 llasram: ##(identity *clojure-version*)

9:36 lazybot: ⇒ {:major 1, :minor 3, :incremental 0, :qualifier nil}

9:36 fdaoud: I get the same results in 1.2 repl

9:36 llasram: Oh, lazybot got an upgrade

9:37 jweiss: hm, i am not sure how this same code worked in 1.2 then

9:37 llasram: Anyway, like fdaoud I tried in a 1.2 local REPL. Writer is imported, but most of java.io is not

9:37 fdaoud: llasram how do you see that Writer is imported?

9:38 llasram: Er, I just type "Writer", and it evaluates to java.io.Writer instead of throwing an exception :-)

9:38 jweiss: my code is like this: (defmethod print-method :bz-blocker [o ^Writer w]

9:38 (print-method (::source (meta o)) w))

9:38 compiles fine in 1.2

9:38 fdaoud: llasram: maybe it's the lack of coffee on my part. I don't understand. "Writer" is just a string...?

9:39 jweiss: no, symbol

9:39 llasram: Yeah, sorry. No quotes

9:39 ,(ns-resolve *ns* 'Writer)

9:39 clojurebot: nil

9:39 fdaoud: sheesh. where's my coffee?

9:39 well just Writer gives me java.lang.Exception: Unable to resolve symbol: Writer in this context

9:40 String does give me java.lang.String

9:40 I'm on 1.2.0 to be precise

9:40 jweiss: llasram: which version are you using?

9:41 ,Writer

9:41 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Writer in this context, compiling:(NO_SOURCE_PATH:0)>

9:41 fdaoud: ,String

9:41 clojurebot: java.lang.String

9:41 jweiss: ,java.io.Writer

9:41 clojurebot: java.io.Writer

9:41 llasram: Interesting. Must be a leiningen bug. `lein repl' pulls Writer into *ns*, but java ... clojure.main with clojure 1.2.1 does not

9:42 Wait, no. Ok, *I* need more coffee

9:42 I've got 1.3 stuff in my lein init.clj. That was causing `lein repl' to bail out during init, leaving me in the `clojure.core' namespace. *That* namespaces has Writer imported

9:42 Wheeeee

9:43 fdaoud: cool

9:43 jweiss: i can tell you that when i ran my code with 1.2.0 i didn't need to specify java.io at all

9:48 fdaoud: in programming clojure book (definitely pre 1.3), it says classes outside of java.lang must be fully qualified or imported.

9:48 jweiss: hm... i thought i read java.io was included, which is why i left it off. And it worked so i figured that was correct

9:48 fdaoud: maybe that was 1.1 and something changed in 1.2?

9:49 jweiss: now i can't find any reference to java.io being imported by default

9:49 so i don't know why it ever worked

9:50 well, easy fix at least, even if i can't explain why it suddenly broke

9:51 fdaoud: strange

11:38 is there something more idiomatic than (not (nil? x))

11:39 lucian: fdaoud: x

11:39 abedra: fdaoud: are you looking to filter a collection or just test a single thing?

11:40 fdaoud: and are you explicitly looking for nil, or do empty collections and blank strings apply?

11:42 fdaoud: lucian: thanks, so simple that I missed it!

11:42 abedra: just test a single thing, but I am interested in what you have to say about filtering a collection, empty collections, and blank strings

11:42 abedra: fdaoud: you can filter nils out of a collection with (filter identity collection)

11:42 fdaoud: to filter, it would be keep?

11:42 abedra: but there are lots of ways of doing that

11:42 yes

11:43 you only get real values back, no nils

11:43 (filter identity [nil 1 nil 4 5 nil 6])

11:43 ,(filter identity [nil 1 nil 4 5 nil 6])

11:43 clojurebot: (1 4 5 6)

11:43 fdaoud: difference between filter and keep seems to be for false values

11:44 i.e. false is returned with keep, filtered out with filter

11:44 abedra: ,(doc filter)

11:44 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects."

11:44 abedra: ,(doc keep)

11:44 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects."

11:45 fdaoud: ,[(keep identity [nil 1 false 2]) (filter identity [nil 1 false 2])]

11:45 clojurebot: [(1 false 2) (1 2)]

11:45 abedra: yep

11:45 fdaoud: nice, thanks

11:45 abedra: np

11:47 fdaoud: there's also remove

11:47 ,(remove nil? [1 nil 2 false 4])

11:47 clojurebot: (1 2 false 4)

11:47 fdaoud: ,(doc remove)

11:47 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns false. pred must be free of side-effects."

11:48 abedra: fdaoud: just like filter, takes a predicate, but removes on true

11:48 fdaoud: ,(remove identity [nil 1 false 2])

11:48 clojurebot: (nil false)

11:48 abedra: it removes when the predicate is true

11:49 identity returns false on nil and false

11:49 fdaoud: I see

11:49 abedra: so if you are looking to remove only nil values and still have things like false around, you can use remove nil? or keep identity

11:50 i prefer remove

11:51 fdaoud: ,(let [coll [nil 1 false 2]] (= coll (mapcat #(% identity coll) [filter remove])))

11:51 clojurebot: false

11:52 fdaoud: ,(let [coll [nil 1 false 2]] (= coll (mapcat #(% identity coll) [remove filter])))

11:52 clojurebot: false

11:53 fdaoud: ,(let [coll #{nil 1 false 2}] (= coll (mapcat #(% identity coll) [filter remove])))

11:53 clojurebot: false

11:53 fdaoud: ,(let [coll #{nil 1 false 2}] (= coll (set (mapcat #(% identity coll) [filter remove]))))

11:53 clojurebot: true

11:55 iris1: Dear experts, how can I do a recursive definition of a seq in a let? Here is an example illustrating my problem: http://pastebin.com/RSc1Wekf It appears that in a let, the name being defined is not available (which is not the case in a def). Thank you!

12:05 chouser_: iris1: that's a tough one

12:06 chouser: I think I've done it, but I'm having trouble remembering how

12:10 iris1: one option is to use letfn which specifically allows expressions to refer to the local names being defined.

12:10 (letfn [(v1 [] (range 10)) (w1 [] (lazy-cat [0] (map + (v1) (w1))))] (w1))

12:11 iris1: Thank you, chouser! My best guess was to bung a defn in there but this is clearly better.

12:12 ipostelnik: why would you want to do something like this in the first place?

12:13 chouser: ipostelnik: I'll let iris1 handle that one. :-)

12:15 iris1: In math notation, I have a sequence (f0, f1, f2, f3, ...) as an input. I want to use it to generate an output sequence (g0, g1, g2, g3, ...), where gi depends on g(i-1) and fi. Basically the fi are a sequence of observations about the world, and the gi are my representation of what the world looks like based on those observations. There is probably some fancy name for this, like folding or reducing (although I don't think it's exactly one

12:15 those two)

12:17 chouser: iris1: another option is to use a promise

12:17 ,(take 20 (let [fib (promise)] (deliver fib (lazy-cat [1 1] (map + @fib (next @fib)))) @fib))

12:17 clojurebot: (1 1 2 3 5 ...)

12:17 ipostelnik: iris1, I think reductions is what you really want

12:17 ,(doc reductions)

12:17 clojurebot: "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

12:19 ipostelnik: ,(reductions + 0 (range 10))

12:19 clojurebot: (0 0 1 3 6 ...)

12:20 iris1: chouser: Thank you! I haven't really learned about promises yet. I am just learning Clojure, from a number of books including yours. Thank you for your help!

12:21 ipostelnik: Thank you! That's great. Reductions does look like what I need. It seems like I am going to need to zip f and g together first in order to introduce g into the calculation. I am going to give that a try.

12:21 ipostelnik: iris1, your fn will get called with g(i-1) and f(i)

12:22 iris1: ipostelnik: Ah yes, you are so right! Thanks & sorry for missing that point. Absolutely no need for zipping. This is awesome. (I'll still learn about promises as they look useful too.)

12:32 phf: i'm trying to move a lein/emacs based development environment from mac to a windows machine that doesn't have internet connection. is it enough to grab lein.bat, ~/.m2, ~/.lein and emacs?

12:33 TimMc: Good question. I wonder if any of the maven artifacts are arch-dependent.

12:34 phf: Are you able to try it multiple times? THat is, do you have access to both machines at once?

12:35 phf: TimMc: yes, but i'd like to minimize the number of tries. (lotus 8, email and "split" are involved in the process :/)

12:35 TimMc: heh

12:36 Maven will yell if it needs a dependency, and you can manually install those.

12:36 phf: i guess as long as nobody jumped in with "you also need X", i'm just going to go ahead and try it

12:36 TimMc: Report back either way!

12:36 phf: ack

12:37 technomancy: llasram: clojure 1.2 let you have type hints to classes that didn't exist

12:37 nothing changed in what was imported automatically

12:51 llasram: technomancy: Oh, cool. That is useful to know.

13:11 pcarrier: hey

13:11 I'm trying to transform an array into a hash, and I'd like to avoid destructuring into symbols then creating the map...

13:12 for example [a b c] becomes { :foo a :bar c }, with b being discarded

13:12 dnolen: ,(object-array [1 2 3 4])

13:12 pcarrier: is there a clean way to do that?

13:12 clojurebot: #<Object[] [Ljava.lang.Object;@3589e6>

13:12 dnolen: (into {} (object-array [1 2 3 4]))

13:12 ,(into {} (object-array [1 2 3 4]))

13:12 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

13:12 dnolen: oops

13:13 ,(into {} (map vec (parition 2 (object-array [1 2 3 4]))))

13:13 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: parition in this context, compiling:(NO_SOURCE_PATH:0)>

13:13 dnolen: ,(into {} (map vec (partition 2 (object-array [1 2 3 4]))))

13:13 clojurebot: {1 2, 3 4}

13:13 dnolen: finally

13:13 pcarrier: dnolen: but that's not what I'm looking for...

13:14 dnolen: pcarrier: sorry missed a line of description.

13:14 pcarrier: I'd like to transform [a b c] into { :foo a :bar c }, by saying something like (mapify [ :foo 0 :bar 2 ] [a b c])

13:14 ibdknox: how do you know to ignore b?

13:14 pcarrier: associative destructuring into a map, if I may abuse the word

13:14 ibdknox: because 0 and 2 are indexes

13:14 licenser: because it is 2

13:15 ibdknox: ah I see

13:15 pcarrier: something like (let {foo 0, bar 2} [a b c]]

13:15 licenser: pcalcado: do something like (reduce (fn [m [k v]] (assoc m k (nth v [a b c]))) {} {:foo 0 :bar 2})

13:15 pcarrier: but instead of binding foo and bar, it returns { foo ... bar ... }

13:16 licenser: not guaranteed to work but along those lines is what solves your problem :)

13:16 pcarrier: I'm not sure if I make sense

13:16 I certainly hope I do :)

13:16 (I would use that to parse a message of which I don't control the structure with a regexp into a map)

13:17 dnolen: ,(into {} (map (fn [[k i]] (vector k (nth (object-array '[a b c]) i))) (partition 2 [:foo 0 :bar 2])))

13:17 clojurebot: {:foo a, :bar c}

13:17 ibdknox: ,(let [m {:foo 0 :bar 2} v '[a b c]] (into {} (map #(vector % (v (m %))) (keys m)))

13:17 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

13:17 pcarrier: I know how to do it in an ugly way with (let [{foo 0, bar 2} [a b c]] { :foo foo :bar bar })

13:18 licenser: ,(reduce (fn [m [k v]] (assoc m k (nth v [a b c]))) {} {:foo 0 :bar 2})

13:18 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)>

13:18 pcarrier: dnolen: ok, it ends up being more verbose that my ugly approach... I'll guess I do with that :)

13:18 licenser: ,(let [a [1 2 3] (reduce (fn [m [k v]] (assoc m k (nth v [a b c]))) {} {:foo 0 :bar 2}))

13:18 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

13:18 ibdknox: ,(let [m {:foo 0 :bar 2} v '[a b c]] (into {} (map #(vector % (v (m %))) (keys m))))

13:18 clojurebot: {:foo a, :bar c}

13:19 pcarrier: ibdknox: OK, I'll learn how this works :)

13:19 ibdknox++

13:20 * technomancy wonders if map-keys and/or map-vals should be promoted to core

13:20 technomancy: the zipmap trick is pretty cumbersome

13:21 ibdknox: yeah the zip-map version is longer

13:22 srid: ibdknox: would you recommend anyone to use your socket.io server implementation, or use something else (if yes, what would that be?)?

13:22 i realized that directly using websockets (via aleph) in my application doesn't work for basic auth

13:22 ibdknox: srid: using my socket.io server is not for the faint-hearted

13:23 srid: and how would it help solve an issue that cannot be solved with aleph?

13:24 srid: the websockets standard doesn't seem to support any auth mechanism (eg: http basic auth).

13:24 so maybe I should switch to long polling, flash or something else

13:24 for that, I need a server-side abstraction

13:25 ibdknox: srid: you probably shouldn't be using basic auth

13:25 srid: also, in the time it would take you to switch to a different mechanism, you could've easily written simple auth for your app

13:25 srid: would anything else work with websockets? you mean like manually authorizing the passed-in user/pass via websocket channel?

13:26 ibdknox: I assume you're serving a page, right?

13:26 srid: serving a page, and then "streaming" events (as they come in from many servers) to the just served-page via WS

13:26 imagine a "multitail" web frontend

13:27 the page itself can be protected with basic auth. but WS data would still be exposed

13:27 ibdknox: so serve a login page and then send the ring-session-id as the first thing down your socket

13:27 store the session ID's in an atom when a user logs in

13:28 and problem solved

13:29 srid: what is ring-session-id?

13:30 ibdknox: srid: it's the id in the cookie that is set for ring-sessions, though really you can use anything. You could set your own cookie

13:31 srid: ok, i'll try that. (cookies are not automatically sent to the server in 'request'? will check ...)

13:31 seancorf`: i had a bunch of folks try my "emacs on windows" post and everyone on windows 7 ran into the same problem: clojure-jack-in fails with an error about non-hex characters in a unicode escape sequence

13:32 i'm guessing that it's due to "c:\users\..." in strings because the "home" folder is buried under that folder

13:32 on win xp, it's "c:\documents and settings\..." so i didn't run into it

13:32 anyone using emacs on windows 7 have any suggestions?

13:32 chouser: %something%

13:33 heh -- of course I don't use emacs or windows

13:34 but I was following some tutorial the other day and the path was wrong, but they had a % thingy that worked in both XP and 7

13:35 seancorfield`: maybe %homepath% ?

13:36 seancorfield: it would help if i could figure out where in the elisp code the error was occurring

13:36 it looks like the installation process for a package puts the path into the code?

13:37 i just looked on my mac and found a lot of "~/..." paths in the code

13:37 would setting default-path in init.el (to some

13:38 simple path) help i wonder?

13:51 Squee-D: Morning

13:54 pcarrier: how can I have nice and clean clojure backtraces in my processes?

13:55 I'm running threads, which breaks my clj-stacktrace attempt

14:17 Raynes: technomancy: Looking good. The Heroku tryclj.com tweet just went out and the site is getting pounded, but still seems to be going strong.

14:17 technomancy: still on one dyno?

14:17 Raynes: Yep.

14:18 Still snappy.

14:18 technomancy: rocking

14:19 Raynes: Even people using it from iPads.

14:19 technomancy: what'll they think of next.

14:19 fdaoud: <-- tried it from iPad

14:19 Raynes: I actually just updated the jquery-console. I guess it's supposed to have improvements in iOS now, so good thing.

14:20 fdaoud: Did it work properly?

14:20 I've used it from Android.

14:20 Works fine there.

14:20 fdaoud: context = reading clojure book on ipad, want to try stuff out, don't want to transit to computer

14:20 Raynes: yes sir

14:20 Raynes: Great!

14:22 abedra: technomancy: when do you get into our neck of the woods next week?

14:22 technomancy: abedra: should be Wednesday evening

14:22 abedra: ok cool.

14:22 technomancy: want to catch up with you on your plans for world domination at your new gig

14:23 technomancy: and other general plotting and scheming

14:23 Raynes: abedra: Also, I may or may not decide you should stand up and talk about something during my talk. Haven't decided if I want payback for last year.

14:23 abedra: Raynes: :)

14:23 technomancy: abedra: sure; I should be at the game room thing handing out drink tickets the night before.

14:23 abedra: Raynes: I was just breaking you in for this year

14:23 technomancy: cool!

14:24 Raynes: Heh. Breaking what, my neck? My legs were shaking so bad that I could hardly stand.

14:24 abedra: :)

14:24 Raynes: and now you're giving a talk

14:24 ibdknox: welcome to public speaking ;)

14:24 Raynes: I'm hoping that the preparation will prevent the whole vibrating legs fiasco this year.

14:25 abedra: Raynes: mine were too, but that's because I drank too much tequila the night before

14:25 Raynes: Heh

14:25 ibdknox: lol

14:25 Squee-D: Raynes it wont. you gotta just trip on it :D

14:25 abedra: Raynes: you'll do great, just bring your passion and all will be right in the world

14:25 chouser: the only thing I know that actually kills the nerves is standing up and doing it nervous several dozen times

14:26 Squee-D: chouser totally

14:26 abedra: ^^

14:26 Raynes: I really like my talk. I'm mostly paranoid that I wont be able to keep it all going for 40 minutes. I may have to improvise.

14:26 ibdknox: Tehe truth is that the worst that could happen is you look ill prepared. There's no question of intelligence here. So *shrug*

14:26 Squee-D: chouser really enjoying the book btw

14:26 chouser: actually, abedra's right too -- being passionate about what you're saying helps tons

14:26 Squee-D: thanks!

14:27 abedra: If you have time before hand, you can work out some of the excess nervous energy by working out

14:27 it really helps

14:27 ibdknox: +1

14:27 Raynes: I'm pretty passionate about sandboxing, I think. My most important projects depend on it, and amalloy_ and I have put a lot of work into clojail.

14:27 Squee-D: Thats a good idea

14:27 abedra: just hit the treadmill or stationary bike for 20-30 mins

14:27 it really helps clear you

14:27 chouser: Squee-D: did you see the movie of the commits that fogus posted? Demonstrates quite clearly how much you should be complimenting him not me. :-)

14:27 Raynes: I also think it is a sufficiently interesting subject. I just need to be a sufficiently interesting presenter.

14:28 Squee-D: chouser no i did not. Fogus is not here to thank is he?

14:28 chouser: Squee-D: apparently not at the moment.

14:29 Squee-D: Raynes i dont know many presenters who can kill my interest in a topic. What makes a good presenter for me is that they bring an interesting topic to light

14:29 Raynes: He is never here. At least, never here when I want to say something amusing to him.

14:29 ibdknox: yeah, a good topic can mostly stand on its own

14:29 the key as was said is passion

14:29 if you're excited, everyone else will be too

14:30 Raynes: I'll consider singing the talk.

14:30 ibdknox: lo

14:30 l

14:30 Raynes: Maybe even some dancing with amalloy_ and ninjudd.

14:30 TimMc: Raynes: Bring a kitten, everyone will love your talk.

14:30 Raynes: TimMc: There are *tons* of cats in my talk. :D

14:30 And exactly one dog.

14:30 TimMc: Good, you'll be fine.

14:31 Squee-D: Raynes a great presenter will help me make cognitive leaps to understanding.. thats really hard for any presenter, but the lack of doesn't mean the presentation wont be compelling.

14:32 fwiw, i think it's almost impossible to screw up with an interesting topic.

14:32 abedra i'm going to try your suggestion before my next speaking gig

14:33 If im dead exhausted i can probably polish it up as 'relaxed and considered'

14:33 fdaoud: abedra I do stationary bike 45 mins first thing in the morning, it really helps kick start the day

14:33 Squee-D: Raynes the dog comes to no harm i hope.

14:33 ibdknox: It's a well known "trick" for speakers

14:34 abedra: Squee-D: I was surprised by how much it helps calm the jitters

14:34 * ibdknox has done a lot of speaking :)

14:34 Squee-D: abedra it makes a lot of sense

14:34 abedra: Squee-D: I picked the idea up from "Confessions of a Public Speaker"

14:34 Raynes: If I don't start getting sleep at night, I'm not even going to wake up the morning of my talk. Problems solve themselves.

14:34 ibdknox: abedra: Scott is a fun guy

14:35 Raynes: The lack of sleep is only related to the actual writing of the talk (because I waited until the last minute) and not performing the talk. I just need a) less to do or b) more hours in a day.

14:35 fbru02: Raynes: I always underestimate the effort of giving a talk then i suffer at the end

14:35 ibdknox: it's a lot of work

14:36 and a lot of standing in front of a mirror :)

14:36 fliebel: Raynes: Why is there a dog in the talk?

14:36 ibdknox: to eat the cats, of course.

14:37 chouser: uh oh, I don't stand in front of a mirror. Does it show?

14:37 Raynes: ninjudd is convinced that I need to practice the talk with him and friends over skype. I'm convinced that I need to not practice at all and put all my effort into one good performance. I'm going with him, since he employs me. ;)

14:37 fliebel: Because he's cute.

14:37 ibdknox: chouser: it's just another trick

14:38 chouser: Raynes: oh, definitely practice, and do it out loud, even if nobody is listening.

14:38 ibdknox: that's part of what the mirror helps with, you're talking to somebody

14:38 lol

14:38 chouser: ah

14:38 Raynes: I've been doing complex slides out loud to myself to make sure they make sense.

14:38 ibdknox: gotta go it all the way through

14:39 Raynes: I just don't like cameras with people on the other end. CCTV makes me *want* to rob stores, just to spite the owner who put it there.

14:39 ibdknox: a good talk has a rhythm. Once you've internalized that by going through it a couple times, you'll find that it's much easier to just go with the flow on the actual day

14:39 fliebel: when is the conj? wil htere be video?

14:40 dnolen: next week!

14:41 chouser: whew! must finish the talk...

14:41 fliebel: dnolen: And the logic guy will be there right? ooorh, can't we do it in Europe next time?

14:42 gtrak: who's the logic guy?

14:42 Raynes: chouser: Tell me about it. ._.

14:42 fliebel: Isn't the logic guy dnolen?

14:42 fliebel: gtrak: The one who write miniKanren, me thinks

14:42 flognikr: raynes: http://www.forbes.com/sites/jerryweissman/2011/10/26/vinod-khoslas-five-second-rule/

14:42 chouser: gtrak: he wrote core.logic. He's really smart, and comes here sometimes

14:43 Raynes: Guess not.

14:43 It's that Australian fellow.

14:43 chouser: yes, I think we're all talking about dnolen

14:44 fliebel: I guess dnolen know best, but what I understand is that dnolen and ambrosebs based core.logic on miniKanre, and *that* guy is going to be there as well, I thought.

14:45 Raynes: chouser: I see a talk by Ambrose about logic programming.

14:45 chouser: fliebel: ah, I see -- I didn't understand you

14:45 Raynes: dnolen's talk is about predicate dispatch.

14:46 fliebel: from dosync: "I'm excited to hear William Byrd and Daniel Friedman describe the ideas behind cKanren at the Clojure/conj."

14:46 ibdknox: dnolen's so famous now that I'll have to get a picture taken with him and get it autographed! :D

14:46 Raynes: I've already met him.

14:46 :>

14:46 ibdknox: srsly?

14:46 what was it like?

14:46 Raynes: He has cool hair.

14:47 ibdknox: haha

14:47 (inc dnolen) :)

14:47 lazybot: ⇒ 1

14:47 dnolen: fleibel: Dan Friedman is going to be there - big Scheme fellow who wrote some awesome books Little Schemer, Seasoned Schemer, Reasoned Schemer.

14:48 as well as the classic text on creating programming languages - The Essentials of Programming Languages - on the Hickey bookshelf.

14:48 joly: love those books, though I need another pass through Reasoned Schemer

14:49 abedra: joly: we all do :)

14:50 fliebel: dnolen: oww, so many books I need to read.

14:50 abedra: I just took another pass through it recently

14:51 dnolen: fliebel: William Byrd as well who wrote the miniKanren dissertation.

14:53 fliebel: dnolen: But they are not on the lineup, so they're just attendants, right?

14:53 hiredman: there is the disj

14:54 dnolen: fliebel: they'll be unofficially presenting

14:54 fliebel: hiredman: disj?

14:54 ejackson: hiredman: lol, that's for the unreformed ?

14:55 fliebel: dnolen: So, will there be a video of that?

14:55 hiredman: conj : disj :: conf : unconf

14:55 gtrak: lol

14:55 dnolen: fliebel: hmm, I dunno that would be *awesome* if there was.

14:56 maybe we can convince someone to bring their own video camera

14:56 fliebel: dnolen: If there isn't, just point your smartphone at them. (says the guy with a brick for a phone)

14:57 hiredman: I think I brought my video camera to the first conj, but didn't use it

14:58 oskarth: I have a long string I want to display in a web form. How can I format the code nicely (ie no word wrap and correct indentation) without destroying the form text layout?

15:02 ThreeCups: Is this a good way to initialize a vector with empty maps?

15:02 (let [v (transient [])] (dotimes [i 10] (conj! v {})) (persistent! v))

15:02 ibdknox: ,(vec (take 10 (constantly {})))

15:02 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$constantly$fn__3656>

15:02 ibdknox: ,(vec (take 10 (repeat {})))

15:02 clojurebot: [{} {} {} {} {} ...]

15:03 joegallo: ,(vec (repeat 10 {}))

15:03 clojurebot: [{} {} {} {} {} ...]

15:03 ThreeCups: ibdknox: thanks! I had a feeling there was a better way

15:03 ibdknox: hah

15:03 didn't know repeat took a number

15:03 ,(doc repeat)

15:03 clojurebot: "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."

15:03 ibdknox: cool

15:19 iwillig: in the old clojure contrib repl-utils there was this great function called `show`

15:19 does any know if that is still around after the contrib revamp ?

15:19 hiredman: it is not

15:19 iwillig: mmm ;(

15:19 sad face

15:19 okay thanks

15:20 hiredman: there is some similar stuff in clojure.reflect, and I think there was some interest in providing something like show based on clojure.reflect

15:20 iwillig: oh cool thanks hiredman

15:56 technomancy: if you're using slime, C-c S-i is a great replacement for show

16:01 joegallo: oooh, pretty

16:01 fyi, I would write that as C-c I (that being an uppercase i)

16:02 your way sent me off to the internets in search of how to define a Super key

16:02 but i'm pretty ignorant

16:06 technomancy: heh; super is lower-case s

16:15 srid: lein question: how to get the version in project.clj from within code?

16:16 technomancy: srid: (System/getenv "LEIN_VERSION") should do it

16:17 srid: thx

16:17 i was about to check the env.

16:18 technomancy: oh wait. that's lein's version, not my project's

16:19 I don't see any other LEIN_* environment.

16:19 technomancy: oh, that's a System property

16:20 (into {} (System/getProperties)) ; <- should be in there

16:20 mtm_: heh, I just got bit by 'clojure-jack-in's port selection policy (it just happened to pick a port that was already in use). Is there any elisp floating around to find an unused TCP port in some range?

16:20 srid: yup, "<name>.version"

16:21 technomancy: mtm_: don't know off the top of my head but that would be great

16:21 mtm_: I'll dig into it

16:26 simard: hello, I'd like to have some feedback on this snippet of code: http://pastebin.com/kT1gaaZr

16:26 specifically, I'd like to know if the binding is a good idea, and if there is an alternative to it

16:26 (line 21)

16:28 the thing is I'm using multimethods (transform-translate-type), but that method needs to be given a point (delta-xy), and the only way I could think of it was using a binding in the (transform-translate) call.

16:28 ibdknox: just add the point to the map you pass in?

16:28 even better

16:29 just pass the point in?

16:29 simard: yeah wait, there was a reason I had for not doing that.

16:29 let me see :P

16:31 brehaut: simard: i have no idea what this code is doing

16:32 simard: brehaut: well, it transforms geometric objects.

16:32 translation is all there is in that pastebin

16:33 more precisely, it transforms lists of objects, recursively. a transformable object is a map containing :x and :y keys

16:33 ibdknox: that binding shouldn't be there

16:33 simard: yeah

16:33 ibdknox: honestly I've been working on the solution for a good hour now and I .... forgot why I was doing it that way

16:34 ibdknox: simard: haha that's how it goes

16:34 simard: I seem to recall there was a good reason to that ... :)

16:36 jayunit100: how to count % chars in a string

16:36 to a map

16:36 ibdknox: lol

16:36 who got Rio Grande to sponsor the Conj?

16:36 srid: ,(frequencies "ab%sd%")

16:37 clojurebot: {\a 1, \b 1, \% 2, \s 1, \d 1}

16:37 srid: jayunit100: ^

16:37 ibdknox: or the lower level version:

16:37 svdberg: hi

16:37 ibdknox: ,(count (filter #{\%} "some%st%ring"))

16:37 clojurebot: 2

16:38 svdberg: any idea why doc or (clojure.repl/doc) stopped working in my slime?

16:38 using clone's of the latest slime/swank-clojure

16:38 srid: happens to me too, sometimes

16:38 svdberg: and clojure 1.3

16:38 it still works in a normal repl

16:39 jayunit100: something like [count [map [filter c] myString]] , where c is a given character

16:39 would give a count for an individual char.... but I want to do for all chars in the string, to get a map.

16:39 svdberg: srid: any idea how I can fix it?

16:40 jayunit100: ABC->

16:40 {A 1, B 1, C 1}

16:40 raek: ,(frequencies "ABC")

16:40 clojurebot: {\A 1, \B 1, \C 1}

16:41 brehaut: ,(frequencies "hello, world")

16:41 clojurebot: {\space 1, \d 1, \e 1, \h 1, \, 1, ...}

16:41 brehaut: ibdknox: i was wondering that too

16:42 ibdknox: brehaut: 's pretty awesome

16:42 fdaoud: ,(frequencies "kenneth")

16:42 clojurebot: {\k 1, \e 2, \n 2, \t 1, \h 1}

16:44 brehaut: ibdknox: it really is :)

16:45 svdberg: is there any way to check what ns are in scope? (from the repl)

16:48 dnolen: svdberg: what do you mean "in scope"

16:48 jayunit100: (frequencies "ABBBBACAKAAKAC")

16:48 ,

16:48 ,(frequencies "ABBBBACAKAAKAC")

16:48 hmm. how to get clojure bot to run it ?

16:48 #(frequencies "ABBBBACAKAAKAC")

16:48 llasram: svdberg: What do you mean by "stopped working"?

16:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

16:48 {\A 6, \B 4, \C 2, \K 2}

16:48 _ulises: hi all, what's the preferred/most mature couchdb client?

16:49 svdberg: dnolen: I'm trying to find out why slime doesnt see "doc" and my lein repl does

16:49 dnolen: svdberg: doc is no longer loaded by default.

16:49 ibdknox: _ulises: https://github.com/ashafa/clutch

16:49 _ulises: ibdknox: thanks

16:50 svdberg: dnolen: even (clojure.repl/doc ..) doesnt work

16:50 _ulises: ibdknox: quick question; I've seen that one but it mentions the clojure view server. Is that a required dependency?

16:50 * _ulises is after a couchdb client

16:50 brehaut: _ulises: no

16:50 _ulises: thanks

16:51 dnolen: svdberg: did you (require 'clojure.repl) ?

16:51 svdberg: dnolen: I'll ty

16:51 try*

16:51 brehaut: _ulises: ive just been using it as a client API on my site and it works fine

16:51 svdberg: dnolen: ah.. got it

16:52 I guess lein repl does use it by default?

16:52 jayunit100: why is persistent! necessary ? I just did source frequencies to see how it worked

16:52 dnolen: svdberg: yes

16:52 brehaut: jayunit100: does it use a transient map in the reduce?

16:53 svdberg: dnolen: hmm is there any way to automate it? doc and find-doc are very usefull in a slime repl

16:53 jayunit100: not sure :]

16:53 dnolen: svdberg: you can probably customize the slime repl to run some initial forms, I haven't looked into it.

16:53 svdberg: dnolen: thanks

16:53 jayunit100: yes

16:53 it does

16:54 ibdknox: ,(source frequencies)

16:54 clojurebot: Source not found

16:54 jayunit100: @dnolen +1 your talk on macros on youtube

16:54 brehaut: jayunit100: i think it does, as the initial accumulator. persistent! is required to get a persistent collection back from a transient. transients are a performance optimisation and shouldnt bleed out of a function

16:54 jayunit100: (defn frequencies

16:54 "Returns a map from distinct items in coll to the number of times

16:54 they appear."

16:54 {:added "1.2"}

16:54 dnolen: jayunit100: it's an optimization, not strictly necessary.

16:54 jayunit100: thx!

16:54 jayunit100: [coll]

16:54 (persistent!

16:54 (reduce (fn [counts x]

16:54 (assoc! counts x (inc (get counts x 0))))

16:54 (transient {}) coll)))

16:54 nil

16:54 oh ok

17:00 svdberg: alrighty back to making presentation

17:00 jayunit100: does anybody understand this function ?

17:00 [[about to paste]]

17:01 (defn counts [words]

17:01 (reduce

17:01 (fn [map-so-far word]

17:01 (assoc map-so-far word (inc (get map-so-far word 0))))

17:01 {}

17:01 words)) ;;what is the "get map-so-far word 0" part doing ?

17:01 ibdknox: jayunit100: you should use gists or pastebin or something instead of pasting in here

17:01 jayunit100: oh ok

17:01 from now on.

17:02 ibdknox: jayunit100: ##(doc get)

17:02 lazybot: ⇒ "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

17:02 ibdknox: ,(get {} :woot 0)

17:02 clojurebot: 0

17:03 ibdknox: ,(get {:woot "someval"} :woot 0)

17:03 clojurebot: "someval"

17:03 jayunit100: oh i see. you customize the default return in the last arg.

17:03 ibdknox: yep

17:04 iris1: What's the idiomatic way to rebind *in* and *out* in Clojure? I tried to find this in the docs but have failed so far. My use case is that I want to write a program that communicates via stdin and stdout, but would like to bind *in* and *out* to files as well for testing purposes. Thank you!

17:05 _ulises: iris1: perhaps using (binding [ ...] ...) ?

17:06 iris1: Yes I agree "binding" looks useful, would you mind giving some more detail? I think this is not just a special case of rebinding a var because I would also like the file to be automatically closed when I go out of scope.

17:06 _ulises: iris1: I believe there's a macro to that extent, something along the lines of with-file or something, let me check

17:06 ibdknox: ,(doc with-open)

17:06 clojurebot: "([bindings & body]); bindings => [name init ...] Evaluates body in a try expression with names bound to the values of the inits, and a finally clause that calls (.close name) on each name in reverse order."

17:06 _ulises: with-open! that one

17:07 ibdknox: so you'd do something like (with-open [my-file ...] (binding [*out* my-file] ...

17:09 iris1: ibdknox, _ulises: I see. Thank you!

17:10 _ulises: iris1: didn't do much myself but you're welcome :)

17:20 technomancy: should with-redefs be backported to 1.2 to ease with writing compatible code?

17:21 ibdknox: +1

17:22 technomancy: how awful would it be for a library to define clojure.core/with-redefs if it wasn't already present?

17:22 apexi200sx1: anyone know any good books/websites for learning the basics of compiler design (non acedemic texts)

17:22 ibdknox: apexi200sx1: that's inherently an academic subject :p

17:22 apexi200sx1: lol I know

17:23 :)

17:23 _ulises: apexi200sx1: try this http://compilers.iecc.com/crenshaw/

17:24 apexi200sx1: See I knew a Lisp channel would have some input

17:24 :)

17:24 gtrak: maybe a check if it's bound, then a custom version if it isn't?

17:26 apexi200sx1, what kind of compiler you talking here?

17:28 brehaut: apexi200sx1: http://stackoverflow.com/questions/1669/learning-to-write-a-compiler

17:28 apexi200sx1: gtrak: it is in fact a Python to Javascript compiler/translator

17:29 gtrak: I just wanted a basci grounding in what it is I am letting myself in for first

17:29 brehaut: apexi200sx1: like http://pyjs.org/ ?

17:29 apexi200sx1: gtrak: i usually find having a good high level overview helps digesting

17:29 brehaut, yes I am on that channel now...

17:29 it is just very quiet

17:30 gtrak: I'm afraid a high-level overview is too high-level to be useful in this case, but maybe take a look at the cljs compiler for inspiration

17:30 brehaut: personally i think you gain very little by writing javascript in python ;)

17:30 gtrak: then stop what you're doing and just write clojurescript

17:30 brehaut: gtrak: lol

17:31 the coffeescript compiler might also be worth a look

17:31 gfrederi1ks: coffeescript has the advantage of being very transparent

17:31 gtrak: i spent some time learning python, went to conferences and such, once I latched onto clojure I haven't touched it

17:32 brehaut: clojure is python 3000 done right ;)

17:32 apexi200sx1: The pyjamas project (of which the python to javascript translator is part of)

17:32 gtrak: basically a compiler is lexer->parser->AST->output code

17:33 lisps are basically macros->AST->output code

17:33 apexi200sx1: brehaut: I am aware that Clojure seems to be an excellent language and I enjoy Rich Hickeys talks he does, he is a smart guy, I just unfortunately don;t have any need/reason at the moment to write Clojure codfe

17:34 gtrak: yeah another reason I chose the Clocjure channel

17:34 :)

17:34 gtrak: well, it's a general purpose language, I recommend just piddling around with it until you see the light :-)

17:34 brehaut: apexi200sx1: i write python every day, but i wish i were writing clojure

17:34 apexi200sx1: Lispy/Clojure isn;t learnt by people to get a job done, it is learnt by people who know what they're doing

17:35 I meant, as in to get a job with a corporation

17:35 brehaut: people who are just 'getting the job done' dont choose to learn anything though

17:35 apexi200sx1: brehaut: you know what I mean, i just didn;t articulate it very well, I mean as in learning the language for its own merits rather than popularity

17:36 gtrak: apexi200sx1, actually some folks do clojure to get a job done

17:36 apexi200sx1: brehaut: interesting you saying you write Python in your day job, you are lucky even to be doing that, most people have to write java/c#/c/c++

17:37 brehaut: apexi200sx1: not lucky; determined. i hope to ditch python too

17:38 apexi200sx1: brehaut: just out of interest is it you dislike Python, or that you just think Clojure is more productive/nicer to program in, just interested to hear

17:38 gtrak: brehaut, start by transitioning to jython, then bring in clojure as a concurrency lib :-)

17:38 brehaut: gtrak: lol :)

17:39 gtrak: apexi200sx1, http://jkkramer.wordpress.com/2011/03/29/clojure-python-side-by-side/

17:39 brehaut: apexi200sx1: high on the list is mutable by default, a lack of higher order operations, an extremely weak iterator model (mutable iterators such a bad idea), shoddy enviroment stuff (easy_install, pip, virtual env etc are easy to create a huge mess with)

17:41 technomancy: heh; isn't easy_install the one with no uninstaller?

17:41 brehaut: technomancy: i think so yeah

17:41 technomancy: every time i have to use one of those i wish i had lein

17:41 gtrak: the maven model is superior, though cumbersome

17:42 brehaut: gtrak: managing the mess that the python 'model' can create becomes dramatically more cumbersome in the long term even if it seems easier in the short term

17:43 gtrak: brehaut, yea, those systems are living in denial of the inherent complexity

17:43 brehaut: gtrak: ever installed PIL (the python imaging library)?

17:43 gtrak: i never really had to deal with it, except by noticing just how wrong it was :-), i'm sure it's a nightmare

17:44 apexi200sx1: brehaut: Yeah I been through the book seven languages in seven weeks, so had a cursory overview of a fair few languages just not used them in anger, my shortlist has been Clojure and Erlang to learn in detail next (depending on the problem I want to solve)

17:44 brehaut: PIL seems to have magic in its packaging that means you cant easily predict what the top level namespace will be (none, PIL, Imaging)

17:45 apexi200sx1: brehaut: so what was your preferred language before Clojure showed up a few years back

17:45 brehaut: Python

17:46 apexi200sx1: brehaut: and what made you look into Clojure

17:46 just having a look at Clojurescript

17:46 brehaut: writing multithreaded code in python sucks :P

17:47 apexi200sx1: brehaut: multi threaded programming generally sucks

17:47 in any language :)

17:47 brehaut: its quite managable in clojure and haskell

17:48 dnolen: apexi200sx1: Clojure basically goes out of it's way to make sure that multi threaded programming is actually pleasant.

17:48 Chousuke: I've been doing just a bit of coding in python and I wish I didn't have to deal with weird class stuff already

17:48 apexi200sx1: OK, more specifically, shared state multithreaded concurrency is a pain in most languages

17:49 Chousuke: clojure solves that too :P

17:49 dnolen: apexi200sx1: which is what Clojure was designed to address.

17:49 or one of the things rather.

17:49 Chousuke: the problem with shared state in most languages is that everything is state

17:50 in clojure, only certain things are state

17:50 so it's much easier to handle

17:50 brehaut: apexi200sx1: my clojure programs are an order of magnitude more reasonable (ie, i can reason about them) than the equivalent python

17:50 apexi200sx1: hey, I am sold on the whole concurrency thing in Clojure, I am not sticking up for Python at all , I was just curious as I like Python even with its shortcomings but I have no allegiance to it

17:50 :)

17:50 brehaut: apexi200sx1: and im a better and more experienced python programmer than clojure programmer

17:51 Chousuke: I don't hate python either but after programming clojure lots of things in python feel unnecessarily complicated :P

17:51 technomancy: I knew more about Clojure after one year using it than I knew about Ruby after 5 years.

17:52 apexi200sx1: If I was tasked with writing a high performant highly concurrent server application then I would seriously look into Clojure or more likely Erlang

17:52 Chousuke: that might just be urwid though. (I'm working on a console interface for transmission)

17:53 apexi200sx1: Brehaut: thanks for the insight

17:53 brehaut: the only thing that has put me off Clojure is the association with Java

17:54 brehaut: apexi200sx1: the jvm is an incredible platform

17:54 gtrak: apexi200sx1, that's kind of why it was created in the first place

17:54 dnolen: apexi200sx1: Clojure is also good at all the simpler programs that you would use Python for (I also used Python for a while). Admittedly it's not great for scripting, but for that you have ClojureScript.

17:54 brehaut: apexi200sx1: i dont tihnk you can beat it for server applications

17:55 apexi200sx1: brehaut: not to get into a language war, but Erlang is also worth a look in the server side department, the whole platform from the ground up was built with concurrency in mind

17:55 Chousuke: urwid's signal system in particular is weird. I can't just send signals and have their registered callbacks called nicely; for some reason urwid requires you to register every class that can send signals :P I'm sure there's a reason for that but it's not documented anywhere as far as I can tell.

17:55 brehaut: apexi200sx1: erlang is a really impressive system

17:55 gtrak: is there a good article on message passing vs shared-state immutable concurrency?

17:56 i haven't used erlang, but my gut says the overhead of its model would be too annoying for most cases

17:56 brehaut: apexi200sx1: but if you are not writing distributed systems, then it makes some decisions that are going to work against you

17:56 apexi200sx1: brehaut: true

17:56 brehaut: ive dabbled in erlang

17:56 apexi200sx1: anyway, basically what I am currently needing to write is a browser delivered client app that communicates with a webserver :(

17:56 brehaut: the biggest complaint i have is that actors model can cause youto create really brittle architectures

17:57 gtrak: brehaut, do you get transactions?

17:57 brehaut: (that and the prolog derived syntax is a bit quirky, but thats just syntax)

17:57 Chousuke: gtrak: shared state means reading values doesn't require message passing so many things are easier

17:57 apexi200sx1: hence the Pyjamas (pyjs) thing, but there are still a few issues with language support and so I was wanting to look into how difficult it would be to get my head around the translator :)

17:57 brehaut: gtrak: i never got to OTP but the actors model doesnt provide them

17:57 Chousuke: gtrak: but on the other hand it doesn't work with distributed systems

17:57 gfrederi1ks: so I create a deftype class to be called in a Class.forName("...") style from java. When java calls it, the method errors as the namespace hasn't been loaded. So I added a (require 'my.ns) call inside the method of the deftype. Is this the cleanest way to handle it?

17:57 gtrak: Chousuke, why couldn't it?

17:58 Chousuke: gtrak: you can't "just read" memory that might be on another computer over the internet

17:58 apexi200sx1: brehaut: why you say the actor model can cause you to create brittle archtectures

17:58 Chousuke: gtrak: I mean, you could try but the result would be a mess

17:58 brehaut: apexi200sx1: its not composable

17:59 gtrak: Chousuke, yea... still i think it's better to opt-in for this sort of thing

17:59 dnolen: apexi200sx1: have you played much with ClojureScript? IMO, it's one of the best compile to JS options if you're looking for something more sophisticated then CoffeeScript

17:59 gtrak: if you want messages, use a queue

17:59 brehaut: apexi200sx1: actors can be reasoned about easily enough, but changing an existing actors system to incorporate new requirements can be exceedingly difficult

18:00 Chousuke: gtrak: yeah. Java has libraries for distributed computing I'm sure :P

18:01 apexi200sx1: dnolan: the thing is that Clojurescript although cool, seems to be just a langauge. Pyjamas (for python) is a Python implementation of GWT and has widget sets and DOM manipulation library, it also abstracts away browser differences etc. which from what i can gather clojurescript isnt

18:01 *clojurescript is just a clojure to javascript compiles/translator

18:01 gtrak: apexi200sx1, well, you get google's closure libs built-in, though I've had a hard time to figure it out

18:02 dnolen: apexi200sx1: ClojureScript ships with Google Closure which has almost all of that stuff.

18:02 brehaut: apexi200sx1: 'just a language' is a strength

18:04 apexi200sx1: brehaut: I am not criticising it, just sayng that for me it probably isn;t a reason to learn clojure, and probably isn;t comprehensive enough for my needs regarding web development but things may change in future

18:04 brehaut: i just dont believe in silver bullets

18:04 gfredericks: brehaut: silver bullets believe in you

18:05 gtrak: last time i checked out pyjamas, it looked rough

18:05 brehaut: gfredericks: this is suddenly very theological

18:05 gfredericks: :)

18:05 apexi200sx1: gtrak: you are correct, you have to REALLY want to get the thing working sometimes

18:05 :)

18:06 gfredericks: I'm excited to see the sorts of abstractions that clojurescript can create for browser development

18:06 brehaut: gfredericks: im particularlly looking forward to something for async

18:06 apexi200sx1: but once you have hacked it a bit, it is way less painful than the Javascript/CSS/HTML/DOM/Browser incompatibility nightmare alternative. GWT is more comprehensive and polished, but you write 5 time as much code, cos its java

18:07 a Clojure GWT type thing might be interesting though

18:07 * brehaut dies a little inside

18:07 gtrak: clojure writes straight to bytecode though, that might be really hard to do

18:08 brehaut: ring ecosystem on the server + clojurescript on the client written as seperate server and client components without magic ftw

18:08 apexi200sx1: gtrak oh yeah it isn;t possible as it stands, you can;t use anything but Java in GWT, not Jython JRuby or anything

18:08 anyway I will stop hijacking the this CLOJURE channel

18:08 :)

18:08 gtrak: shun the nonbeliever... shun..

18:09 apexi200sx1: :)

18:10 gfredericks: brehaut: I'M looking forward to being able to write fun algorithms for a browser in a decent language.

18:10 decent == "has integers"

18:12 apexi200sx1: It is also annoying though that mobile devices have to be programmed in crummy languages (android java) iphone (Obj C) - or you can use c# using monotouch/monodroid. Why not Clojure or Python. It seems all the coding I wanna do (web and mobile) you have to use shit languages or jump through hoops

18:12 gtrak: well, clojurescript is good for that too

18:12 dnolen: apexi200sx1: you can program most mobile devices with JavaScript - thus again ClojureScript

18:12 gtrak: android's java is too weak

18:12 dnolen: apexi200sx1: for iOS you have JSCocoa which proper full bridging to Obj-C apis.

18:13 gtrak: phonegap

18:13 dnolen: apexi200sx1: I'm assuming similar things exist for Android JS.

18:14 brehaut: gfredericks: modern javascript implementations do have a distinction between integer and floating point; they just happen to pretend they dont with the Number type :/

18:15 gfredericks: brehaut: well that's the first I've heard of it

18:15 brehaut: gfredericks: im more interested in a map type that has more than string keys

18:15 gfredericks: brehaut: in any case even if that objection is met the stack of objections is still a mile high :)

18:16 brehaut: gfredericks: most definately :)

18:17 llasram: Any language with both '==' and '===', where the main difference between the two is that the former broken <something> by me!

18:17 s,broken,is broken is,

18:18 technomancy: sad fact: most language designers have never read Henry Baker's "Equal Rights for Functional Objects"

18:18 gfredericks: how about "you need a 3rd party library just to tell the difference between its built in data types"

18:18 brehaut: gfredericks: huh?

18:18 gfredericks: objects, arrays, functions...

18:19 brehaut: it has operators for that. two of them

18:19 gfredericks: eh?

18:19 brehaut: gfredericks: typeof and instanceof

18:19 gfredericks: and they act funny

18:19 brehaut: typeof tells you the primative type of somethng, and instance of does a prototype comparison

18:19 llasram: Oooh -- I knew that being too lazy to stop supporting the ACM's anti open-access policies would come in handy some day

18:19 brehaut: of course :P

18:21 gfredericks: brehaut: underscore's version is: toString.call(obj) == '[object Array]';

18:21 I couldn't say why but I'm sure there's a good reason

18:21 in one sense

18:22 brehaut: huh. weird

18:22 gfredericks: maybe the root cause of all that is just that you don't get to pick the version of JS your code runs on, for client stuff

18:24 tolstoy: If you "lein swank" and then M-x slime-connect and get a "happy hacking" message, what's wrong if the repl buffer never shows up?

18:24 Can't seen anything revealing in *Messages* or *slime-events*.

18:24 technomancy: tolstoy: slime has a separate slime-repl elisp package

18:25 tolstoy: technomancy: Ah, okay. Was working yesterday, I'll check that out.

18:25 Might be because I'd tried clojure-jack-in yesterday.

18:27 gtrak: what's the difference between clojure-jack-in and slime-connect?

18:29 tolstoy: Alas, installing slime-repl didn't work. Hm.

18:30 llasram: gtrak: the latter connects an existing slime to a running swank server. The former bootstraps slime, launches a swank server, and connects to it

18:30 gtrak: ah I see

18:33 mtm_: technomancy: I wrote a snippet of elisp that will let you know if a TCP port is available

18:44 tolstoy: When I call a function (via slime repl) with a number (do-something "foo" 12) and get something like "cannot cast to java.lang.Number", is there something I should be looking for?

18:44 Some invisible float in there somewhere?

18:46 gtrak: ,((fn [x] (+ x 1)) "hello")

18:46 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

18:46 gtrak: like that?

18:47 tolstoy: I must have renamed something and created a collision, I guess.

18:57 todun: I see somewhere that doing this is a problem (println "Hello" "World"). However, it runs fine in the repl and it looks ok to me. Am I missing something?

19:00 joegallo: what would be the problem?

19:01 dakrone: ,(println "Hello" "World")

19:01 clojurebot: Hello World

19:16 apexi200sx1: OK, just watched the Rich Hickey talk on Clojurescript. Very interesting, especially considering integration with the Google Closure tools

19:21 todun: joegallo: thant's what I'm trying to find out.

19:39 ThreeCups: noob question: Is there a way in the std lib to copy fields from one map into another. I want to do something like (assoc m (key-values [:key1 :key2] {:key1 1 :key2 2 :key3 3})) where m would end up with keys :key1 and :key2 and values for each key (plus whatever was in m to begin with)

19:40 Actually, not m, but the map that assoc returns

19:40 ibdknox: merge and select keys

19:40 though I think there's probably a more clever way to do it

19:41 ,(doc select-keys)

19:41 clojurebot: "([map keyseq]); Returns a map containing only those entries in map whose key is in keys"

19:41 ThreeCups: ibdknox: Thanks

19:41 ibdknox: ,(let [orig {:a 1 :b 2}] (merge orig (select-keys [:c :g] {:c 3 :d 4 :g 5})))

19:41 clojurebot: {:a 1, :b 2}

19:42 ibdknox: hm

19:42 oh

19:42 ,(let [orig {:a 1 :b 2}] (merge orig (select-keys {:c 3 :d 4 :g 5} [:c :g])))

19:42 clojurebot: {:c 3, :g 5, :a 1, :b 2}

19:58 aperiodic: $findfn "foo" "bar" "foo bar"

19:58 lazybot: [clojure.core/print-str]

20:01 ThreeCups: one more: I want to use doseq over two sequences. But I only want to see each value once. E.g. (doseq [v1 [1, 2] v2 [3, 4]] (println (str v1 " " v2))) prints "1 3\n1 4\n2 3\n2 4\nnil". But I only want to see "1 3\n2 4\nnill". Is there an easy way tot do this?

20:01 brehaut: ,(doseq [[a b] (map vec [1 2] [:a :b])] (prn a b))

20:02 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$vec>

20:02 ibdknox: ,(doseq [[v1 v2] (map list [1 2] [3 4])] (println v1 v2))

20:02 clojurebot: 1 3

20:02 2 4

20:02 ibdknox: brehaut: bwhaha

20:02 brehaut: ibdknox: curses!

20:03 ThreeCups: You guys rock! Thanks. Let me say that I've spent time in the Scala IRC as well, and I definitely prefer this one when I'm learning a new language

20:09 brehaut: ibdknox: how is korma progressing?

20:09 ibdknox: brehaut: on track for my intended Conj release :)

20:10 brehaut: mostly just finishing up documentation now

20:11 brehaut: excellent :)

20:18 technomancy: nothing showcases the value of Clojure metadata like implementing a help system

20:21 ibdknox: :)

20:31 tolstoy: technomancy: Is there a way to get JVM args to a "lein trampoline run" ?

20:32 technomancy: tolstoy: hmm... if JVM_OPTS and :jvm-opts are ignored that would be a bug

20:32 tolstoy: JAVAOPTS="blah" lein trampoline run ;; doesn't seem to work. Nor :jvm-args in project.clj.

20:32 Ah, maybe I misspelled javaops.

20:32 technomancy: JAVA_OPTS should be a backwards-compatibility alias for JVM_OPTS

20:32 but definitely open a bug for :jvm-opts

20:34 TimMc: tolstoy: :jvm-args or :jvm-opts?

20:34 tolstoy: Ok, JVM_OPTS definitely works. I'll double check the :jvm-opts thing. (Using jvisualvm to check this stuff out.)

20:34 TimMc: you and technomancy wrote different things

20:34 tolstoy: I'm using jvm-args. Is it opts?

20:34 technomancy: yeah, it should be opts

20:34 tolstoy: :jvm-opts

20:35 :jvm-opts ["-Xmx1g" "-server"]

20:36 Man, oh, man. I've got a memory leak in a most confusing way. Argh! Maybe clojure laziness is tricking me.

20:36 TimMc: tolstoy: Holding onto the head of a seq, maybe?

20:37 tolstoy: No idea. Can't see where I'm doing that. Might be that I'm generating way too much garbage (big byte arrays).

20:40 Spawning a bunch of threads that send byte arrays to a web service. All of a sudden heap spikes all the way to the ceiling. Anyway, it's something I'm not used to debugging.

20:40 technomancy: I sure enough can't get the jvm-opts to make it through trampoline. Issue on github?

20:40 technomancy: tolstoy: fer shure

20:48 ibdknox: I'm having a brain failure. What is the correct way to format a number to two decimal points?

20:48 brehaut: two decimal places?

20:48 ibdknox: yes

20:49 brehaut: %.2f ?

20:49 ,(format "%.f" 1.234)

20:49 clojurebot: #<UnknownFormatConversionException java.util.UnknownFormatConversionException: Conversion = '.'>

20:49 brehaut: ,(format "%.2f" 1.234)

20:49 clojurebot: "1.23"

20:49 ibdknox: duh. thanks

21:14 goodieboy: Is there a built-in function that will take a map as data, then another map that remaps the keys? (remap {:id 1} {:id :ID}) => {:ID 1} ?

21:14 dnolen: ,(require 'clojure.set)

21:14 clojurebot: nil

21:14 dnolen: ,(doc clojure.set/rename-keys)

21:14 clojurebot: "([map kmap]); Returns the map with the keys in kmap renamed to the vals in kmap"

21:15 dnolen: goodieboy: ^

21:15 goodieboy: dnolen: dang, very nice :) thanks.

21:15 dnolen: ,(clojure.set/rename-keys {:id 1} {:id :ID})

21:15 clojurebot: {:ID 1}

21:16 goodieboy: perfect! I'm glad I asked before came up with some kludgy solution.

21:17 brehaut: ,(into {} (map (juxt (comp {:id :ID} first) second) {:id 1})) ;)

21:17 clojurebot: {:ID 1}

21:17 ibdknox: lol

21:18 brehaut: juxt!

21:18 gfredericks: if you didn't use juxt and comp, you're doing it wrong.

21:18 ibdknox: ~juxt

21:18 clojurebot: juxt is a little hard to grok but it's the best thing ever

21:18 ibdknox: aw

21:18 someone changed it

21:19 ~amalloy

21:19 clojurebot: amalloy is <amalloy> just use juxt, it'll be great

21:19 gfredericks: ~juxt

21:19 clojurebot: juxt is a little hard to grok but it's the best thing ever

21:19 gfredericks: ~grok

21:19 clojurebot: grok is a little hard to juxt but it's the best thing ever

21:19 brehaut: lol

21:21 thats it. we should call *** grok

21:21 gfredericks: that rename-keys function oughta take a function instead of a map

21:22 maybe

21:22 $findfn {:foo 12 :bar 13} name {"foo" 12 "bar" 13}

21:22 lazybot: []

21:26 brehaut: gfredericks: theres a special case of that particular instance as stringify-keys in clojure.walk

21:27 theres also keywordize-keys

21:28 gfredericks: brehaut: I know. That was merely the easiest example to try.

21:38 Raynes: &(+ 3 3)

21:38 lazybot: ⇒ 6

21:38 Raynes: &(System/exit 0)

21:38 lazybot: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)

21:38 Raynes: All of that had purpose, I assure you.

21:38 brehaut: making slides?

21:39 Raynes: brehaut: You've got skills.

21:49 TimMc: Raynes: Am I on teeeveee?

21:49 Raynes: TimMc: Sadly, no. Screenshot was already taken. :(

21:49 TimMc: C'mon, you don't need to crop it so much...

21:49 Raynes: :)

21:49 brehaut: &((clojure.lang.Compiler/maybeResolveIn *ns* (symbol "eval")) '(+ 3 3))

21:49 lazybot: ⇒ 6

21:50 TimMc: brehaut: You can get even shorter with clojurebot.

21:50 brehaut: Raynes: enjoy

21:50 TimMc: im sure you can with lazybot too :P

21:50 Raynes: brehaut: When you find things like that, you probably shouldn't wait until I'm giving a talk to tell me about it. :p

21:51 brehaut: Raynes: but i only just found it!

21:51 Raynes: Heh

21:51 brehaut: especially!

21:51 TimMc: ,((resolve (symbol "eval")) '(+ 3 3))

21:51 clojurebot: 6

21:51 brehaut: lol

21:51 TimMc: &((resolve (symbol "eval")) '(+ 3 3))

21:51 lazybot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

21:51 Raynes: clojurebot isn't really going for real security there.

21:52 Not that I'm exactly worried to death about it in lazybot.

21:52 I do fix things when I see them though.

21:52 Assuming fixing them keeps thing useful.

21:52 TimMc: Why is eval restricted?

21:53 brehaut: Raynes: you know about Schneier's Law ?

21:53 Raynes: $google schneier's law

21:53 TimMc: There are already Java sandboxing restrictions on filesystem access, etc.

21:53 lazybot: [Schneier on Security: "Schneier's Law"] http://www.schneier.com/blog/archives/2011/04/schneiers_law.html

21:54 brehaut: doctrow's revision reads better than the original i think

21:54 Raynes: clojail uses the JVM sandbox. A good part of my talk is emphasizing that the JVM sandbox keeps your computer safe while clojail is focused on keeping the state of your evaluation context safe.

21:54 brehaut: sensible

21:55 TimMc: So... eval could be used to mess up the environment for other users.

21:55 brehaut: &*clojure-version*

21:55 lazybot: ⇒ {:major 1, :minor 3, :incremental 0, :qualifier nil}

21:55 brehaut: with more difficulty now ;)

21:55 TimMc: I think I saw someone do that with one of the bots at one point.

21:56 brehaut: Right! Someone rebound a var or somesuch.

21:56 Raynes: Man, everything can be used mess up the environment for others.

21:56 I'm surprised someone hasn't broken it with println yet.

21:56 TimMc: haha

21:56 brehaut: lol

21:56 TimMc: ,((resolve (symbol "eval")) '(def random-number 17))

21:56 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

21:57 Raynes: Just got denied by the SANBOX

21:57 TimMc: indeed

21:57 which is different from the SANDBOX

21:57 Raynes: Yep.

21:57 brehaut: a cthulhu player will tell you that having a safe place to store your SAN is very important

21:58 TimMc: Has def been redef'ed?

21:59 Raynes: You can't redef def.

21:59 TimMc: Oh right, compiler prim.

21:59 I KNEW THAT

23:14 adeandrade: Hey everybody. Sorry to bother but can someone explain me why this works (map #(vector :p %) '(1 2 3 4 5)) but this doesn't (map #([:p %]) '(1 2 3 4 5)) ?

23:15 Raynes: Your anonymous function in the second example is the equivalent of (fn [x] ([:p x]))

23:16 #() wraps what is inside of it in parens, calling it.

23:16 So it is trying to call a vector as a function, but vectors as functions take more than 0 args and thus you get an exception.

23:16 &([])

23:16 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector

23:17 Raynes: The reason the error message seems bizarre is because vectors actually *are* functions, but they take an argument. ##([1] 0)

23:17 lazybot: ⇒ 1

23:17 Raynes: In this case, it isn't getting an argument.

23:19 adeandrade: Uhmm I don't fully understand, let me run some tests in the repl to see if I get it. Thank you.

23:19 Raynes: adeandrade: #([:p %]) = (fn [x] ([:p %]))

23:21 adeandrade: Yeah.. but how can I use [] as a function?

23:21 Raynes: You don't want to here.

23:21 I was more confusing than I should have been.

23:22 &(map #(vector :p %) [1 2 3 4 5])

23:22 lazybot: ⇒ ([:p 1] [:p 2] [:p 3] [:p 4] [:p 5])

23:22 Raynes: adeandrade: ^ This is what you want.

23:22 Or, ##(map (partial vector :p) [1 2 3 4 5]), either of these will do.

23:22 lazybot: ⇒ ([:p 1] [:p 2] [:p 3] [:p 4] [:p 5])

23:23 brehaut: or ##(map #(-> [:p %]) [1 2 3])

23:23 lazybot: ⇒ ([:p 1] [:p 2] [:p 3])

23:23 Raynes: brehaut: Are you trying to kill the poor guy?

23:23 aperiodic: adeandrade: a vector is also a function that takes an index, and returns the thing at that index

23:23 Raynes: But in this case, that isn't what you want.

23:23 brehaut: Raynes: thats the 'i read joy of clojure' version

23:23 adeandrade: Yes I got it.. but now I'm wondering how [] can get used as a function. Shouldn't the reader understand it is a data structure and treat it as one?

23:24 aperiodic: ,([:foo :bar :baz] 1)

23:24 clojurebot: :bar

23:24 adeandrade: ohh

23:25 so by calling it like #([]) it thinks I'm asking for a location given a key?

23:25 aperiodic: the other way around (a member given a location), but more or less

23:26 since you didn't give it a location, it threw the arity error (arity refers to the number of arguments a function takes)

23:26 make sense?

23:27 adeandrade: now I get it

23:27 yes now it does

23:27 aperiodic: cool!

23:29 adeandrade: thank you everyone, I'll use the (vector) solution, but I'm gonna find more about your suggested solutions using -> and partial

23:29 aperiodic: brehaut: the arrow macro? really?

23:29 brehaut: aperiodic: joy of clojure!

23:29 adeandrade: lol

23:30 ibdknox: nooooooooooooooooooooooo

23:30 github is down

23:30 brehaut: thats a prety great 500

23:31 ibdknox: but, but... I need it.

23:32 aperiodic: brehaut: i mean, i love the arrow macro, but...

23:32 poor octocat

23:33 brehaut: aperiodic: footnote 14, page 102 of joy of clojure ;)

23:34 aperiodic: brehaut: shamefully still need to pick that up

23:34 ibdknox: and we're back

23:35 Raynes: ibdknox: I use bitbucket for my talk.

23:35 Because it has free private repositories. :>

23:35 ibdknox: but it's not as pretty

23:35 and it's missing the octocat.

23:35 Raynes: Agreed.

23:35 ibdknox: -1000

23:35 Raynes: Recognized.

Logging service provided by n01se.net