#clojure log - Nov 15 2010

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

0:26 amalloy: there's some kind of reader macro that causes code to be executed even when you're reading it with read-string, right? what is that, and how do i disable it?

0:28 dnolen: amalloy: ?

0:28 ,(read-string "(+ 4 5)")

0:28 clojurebot: (+ 4 5)

0:29 amalloy: dnolen: i remember hearing in #clojure a while ago that there's some syntax you can put into the string to make it actually execute the code

0:29 or execute some code, anyway

0:30 dnolen: ,(-> "(+ 4 5)" read-string eval)

0:30 clojurebot: DENIED

0:32 cemerick: &(read-string "#=(+ 4 5)")

0:32 sexpbot: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

0:32 cemerick: ,(read-string "#=(+ 4 5)")

0:32 clojurebot: java.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

0:32 cemerick: amalloy: whatever, ^^

0:33 amalloy: ah, thank you, cemerick

0:33 cemerick: amalloy: Warning, there be dragons. Very limited set of things you can do in that context, and it's all undocumented.

0:33 amalloy: i note that #= isn't in the clojure page on reader

0:33 cemerick: yes, all very experimental

0:34 amalloy: cemerick: yes, i want to restrict that to #{}, not actually use it :P

0:34 cemerick: related to the print-dup stuff in core_print.clj and elsewhere

0:35 amalloy: ?

0:35 &(read-string "#{1 2 3}")

0:35 sexpbot: ⟹ #{1 2 3}

0:35 amalloy: er

0:35 cemerick: i.e. no #= needed?

0:35 amalloy: nono

0:35 i mean, i want the empty set of #= operations :P

0:35 ie, none

0:35 cemerick: oh, oh :-)

0:36 amalloy: which just means setting *read-eval* to false, it seems

0:36 cemerick: this is sandboxing?

0:36 amalloy: cemerick: yeah, more or less

0:36 cemerick: hot topic again these days

0:37 amalloy: i'm not actually eval'ing the code - there's already a sandbox for that - but i want to use read-string to identify what the first node/tree/object is

0:37 and not let someone hack me at that point before the real sandbox takes over

0:37 cemerick: sure

0:52 pppaul: $8ball more chocolate?

0:52 sexpbot: pppaul: As I see it, yes.

0:58 amalloy: is there a convenient function that always returns nil, or do i have to write out (constantly nil)?

1:02 cemerick: amalloy: #(do %& nil)? :-P

1:02 constantly is pretty decent

1:02 amalloy: cemerick: sure, i'm not complaining very loudly

1:03 but i wouldn't mind if the language had already implemented everything i can imagine ever wanting

1:03 cemerick: (make-me-a-sandwich!) :-D

1:03 &(make-me-a-sandwich!)

1:03 sexpbot: java.lang.Exception: Unable to resolve symbol: make-me-a-sandwich! in this context

1:03 cemerick: bummer. :-(

1:09 amalloy: &(constantly "Delicious sandwiches for cemerick!") ; call this when you get hungry

1:09 sexpbot: ⟹ #<core$constantly$fn__3551 clojure.core$constantly$fn__3551@f49909>

1:10 cemerick: :-)

1:10 Raynes: Man.... It's only 12AM. :<

1:10 I thought I'd wake up later than this...

1:11 amalloy: Raynes: i get the feeling you're drifting farther east every day

1:11 Raynes: Is github back up? I'm afraid to check.

1:11 amalloy: it was working fine an hour ago

1:11 Raynes: How 'bout clojars? Is it teh fixed?

1:12 amalloy: Raynes: if every server you know is broken, it's probably just you

1:12 Raynes: amalloy: No, it was everybody.

1:12 amalloy: lrenn broke clojars, and Github faced a major outage.

1:13 status.github.com

1:13 haskell.org has also been down for two days.

1:13 Shit, even reddit went down for a while.

1:13 The internet is falling apart.

1:13 amalloy: Raynes: wild. i'm glad i wasn't trying to work

1:15 Raynes: wrapping up a change to make sexpbot not catch the # # syntax if the next token isn't some kind of collection. i assume this is a feature you would like?

1:16 Raynes: Sure. I don't see anybody embedding stuff like ###'print or ##0

1:16 sexpbot: #'print or ⟹ #'clojure.core/print

1:16 0 ⟹ 0

1:16 Raynes: Or...

1:16 amalloy: You could just make it so that it tries to `read` what comes after ##.

1:16 sexpbot: java.lang.Exception: Can't take value of a macro: #'sandbox6588/dot

1:17 amalloy: Raynes: that's how i'm doing it

1:17 well

1:17 not really i guess

1:17 that's my planned next step though

1:17 Raynes: Well, I guess that wouldn't help in this particular situation.

1:18 Well, I have to go see if that dog is still breathing.

1:18 * Raynes runs off.

1:29 LauJensen: Morning all

1:40 Derander: LauJensen: good morning sir

1:40 zmyrgel`: hi, how can I replace digits in a string with E letters?

1:41 like if a string is "pp3pp" it becomes "ppEEEpp"

1:42 Mimisbrunnr: java.lang.String.replace( old, new );

1:42 zmyrgel`: I'd like something easier, as the digits run from 1 to 8

1:43 like use regexp to match the digit and then replace the matching part with that many \E chars

1:44 clojure.contrib.string seems to have some functions but I don't know how to use them to achieve this

1:46 Mimisbrunnr: eh you can probably do it with map and a nice lamdba function

1:48 shachaf: zmyrgel`: Is it just digits from 1 to 8, or possibly-multi-digit numbers made of those digits?

1:49 zmyrgel`: it's just 1 to 8, a single digit

1:49 http://richhickey.github.com/clojure-contrib/string-api.html#clojure.contrib.string/replace-by

1:49 that seems quite promising

2:03 LauJensen: &(.replaceAll "abc3def2" "[0-9]" "E")

2:03 sexpbot: ⟹ "abcEdefE"

2:04 LauJensen: zmyrgel`: looks good enough to me

2:04 zmyrgel`: "abc3def2" should become "abcEEEdefEE"

2:05 LauJensen: aha

2:05 zmyrgel`: the digits tell how many E letters to add

2:06 I was going for something like (replace-by #"\d" #(str (repeat (Integer/parseInt %) \E)) "1ppp3p")

2:10 ha, the above seems to work once I switched to use clojure.contrib.string/repeat instead of core version

2:10 Raynes: LauJensen: Remember http://blog.raynes.me/?p=37 ? Well, when Github's DB got screwed up, my gists got all mixed up. Before I fixed them, one of the gists that were appearing in the post was CL code. What are the odds, eh?

2:12 Out of all the languages that gist could have been in...

2:13 I almost left it there, but figured people would notice.

2:23 yayitswei: what's the idiomatic way to write combine numbers using a nested loop? for example, i want to list all the combinations of a^b for 2 <= a,b <= 100

2:23 currently, I have (take 5 (mapcat (fn [n] (map #(pow n %) (range 2 101))) (range 2 101)))

2:23 err, ignore the "take 5"

2:26 LauJensen: Raynes: Terrible :( I hate relying on outside services

2:26 Raynes: LauJensen: And I understand why now. :)

2:27 This'll likely be the first and only post using gist.

2:28 yayitswei: to answer my own question, (for [a (range 2 101) b (range 2 101)] (expt a b)) would work

2:33 zmyrgel`: is there a functional way to get string index and char at that index while going though a string?

2:34 Raynes: &(doc keep-indexed)

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

2:35 Raynes: &(doc clojure.contrib.seq/indexed)

2:35 sexpbot: java.lang.Exception: Unable to resolve var: clojure.contrib.seq/indexed in this context

2:35 Raynes: Well, anyway.

2:35 zmyrgel`: hmm

2:36 so I'm trying to init my chess board from a string which has the pieces at their index

2:36 the game board is a simple 128-elem vector

2:37 the string is 128 char like "rnbqkbnreeeeeeee...." and I have a function to add pieces to the board

2:38 fill-square [board index piece-value]

2:38 could I use reduce to init my board from the string somehow?

2:43 Raynes: zmyrgel`: If I'm right about what you're doing, then sure.

2:44 zmyrgel`: so does the keep-indexed return index and char from the string?

2:44 Raynes: zmyrgel`: You could reduce the string into the board. If the result of fill-square is a new board, then make the new board the result of the reducing function, and at the end, you'll have your new board. Let me see if I can think of a good example.

2:45 keep-indexed wont really work here. You need indexed from clojure.contrib.seq

2:47 zmyrgel`: ok

2:47 Raynes: (reduce (fn [board [index item]] ..use fill-square to create the new board with the piece attached..) initial-board string)

2:47 Something like that.

2:48 (indexed string), of course.

2:48 zmyrgel`: can I refer to indexed's return values with \1 and \2?

2:50 Raynes: zmyrgel`: If you call indexed on a string, I believe it will return a sequence like ([0 \a] [1 \b] ...)

2:53 zmyrgel`: Raynes: http://clojure.pastebin.com/QPds9H3J

2:53 here's my current version

2:57 can I replace the board arg with (init-game-board) on that/

2:57 ?

2:58 Raynes: You can't do \1 and \2 here.

2:58 zmyrgel`: ok

2:59 Raynes: You'll have to make the function (fn [board [index piece]] (fill-square board index (piece-char->value piece)))

3:00 zmyrgel`: ah

3:01 seems to work now :)

3:01 Raynes: Great! :)

3:02 zmyrgel`: and my code base got 20 lines shorter :)

3:02 Raynes: zmyrgel`: In shorthand anonymous functions like #(+ % %2), % and %2 refer to the arguments that have been passed to the function. However, since we needed to destructure the second argument, we needed to use (fn [] ..)

3:03 zmyrgel`: yeah, I haven't used the destructuring that much

3:05 there's still some horrible stuff that would need to be replaced in my chess engine

3:05 though first I should try to spot why some illegal moves still get approved

3:08 btw, is there a way to overload a function?

3:09 I mean, I have two functions to create moves, one takes 3 args and other 1 arg but both return a same move record

3:10 talios: zmyrgel: yep - just have multiple forms of param/body in defn - http://clojure.org/special_forms shows that in the example

3:11 zmyrgel: talios: ok, thanks

3:59 fbru02: I'm calling a method in a Java library which in turns calls another method, this last method makes an explicit cast from Integer to String, but somehow Clojure gets a ClassCastException, why could this be?

4:08 cais2002: fbru02: can u provide more details?

4:10 fbru02: cais2002: yes just a sec

4:12 esj: morning

4:12 fbru02: cais2002: here https://gist.github.com/700192 , this is basically the problem

4:18 cais2002: fbru02: do you pass an int value as key? maybe you could convert it to string manually before passing it to .sadd

4:21 fbru02: cais2002: sorry i didn't quite understand you, where am i passing an int?

4:26 cais2002: fbru02: isn't "key" a parameter passed into the .sadd method call?

4:36 fbru02: cais2002: sorry, mi connection died, yes key is a a parameter to the .sadd method

4:40 cais2002: fbru02: do u have an example of the line that invokes (setr (RedisSet. xxx) yyy value) ? I guess xxx is not a String

4:41 fbru02: cais2002: xxx in your example i'm invoking it with a string, and still i get the same ClassCastException :(

4:46 cais2002: fbru02: I think protocol.read(inputStream) is returning int? is that where line 121 is? sorry, I am not familiar with redis

4:47 fbru02: cais2002: yeah my guess is that too... my guess is that (String) part is not casting correctly

4:55 cais2002: fbru02: is status code by definition an int? could be a bug in jedis. but I could be wrong

5:01 fbru02: cais2002: in jedis the definition for read is : public Object read(RedisInputStream is) which then getStatusCodeReply converts to String by doing (String)

5:01 cais2002: seems perfectly valid java to me don't know why is not working when called from Clojure

5:05 Chousuke: what, java allows you to cast ints to strings? :/

5:05 That doesn't sound right.

5:05 fbru02: Chousuke: nop, but from Object to String yes

5:05 AFAIK

5:06 Chousuke: right. that's fine.

5:06 as long as the object is a String, anyway

5:07 fbru02: Chousuke: the problem as i imagine it, is that Clojure is deciding "oh this is an int" (or any oter numeric type) before I can tell him that it is a String really

5:08 Chousuke: add type hints to the method call?

5:08 are there overloads?

5:08 fbru02: no overloads, how do i add type hints ?

5:08 Chousuke: (.sadd #^String key #^String value)

5:08 in the -> form

5:08 fbru02: oh cool the metadata

5:09 Chousuke: that'll at least prevent Clojure from picking the wrong method

5:09 of course, if your key or value is an integer you'll still get the error

5:12 fbru02: Chousuke: thanks !

5:42 octe: what's the best way of defining a unction with an optional argument in clojure?

5:43 AWizzArd: octe: you can do (defn f ([x] (f x 10)) ([x y] (+ x y)))

5:43 This defines f for two arities. (f 5) will call (f 5 10).

5:44 LauJensen: AWizzArd: Did you release yet?

5:45 octe: AWizzArd, thanks, just what i was looking for :)

8:48 tonyl: morning

9:07 mattmitchell: is it possible to destructure an argument that is a single value map, so that i can get the key and value without using let?

9:10 mfex: mattmitchell: can you elaborate on why you might need that and why let is not an acceptable way?

9:10 tonyl: you can do it like this: (defn foo [{k v}] ...) i think

9:11 mattmitchell: mfex: well don't know if it's really what i need, just curious

9:11 tonyl: cool i'll give that a try

9:13 Raynes: mattmitchell: The easiest way would be to just call first on the map and pass that to your function.

9:13 tonyl: my bad, u can destructure, but the key won't be passed

9:13 (defn foo [{k :v}] [k])

9:14 then the passed map should have a key named :v to work

9:16 mattmitchell: tonyl: ahh right. that makes sense.

9:17 Raynes: yeah good idea

9:18 mfex: there's also the key and val functions: (key (first {:a 1})) and (val (first {:a 1}))

9:21 mattmitchell: thanks everybody!

10:01 hsuh: anyone used ring's wrap-session ?

10:42 pair: Best textmate bundle for clojure, anyone?

10:46 Other than "uninstall it and use Emacs".

10:48 fogus_: pair: are there multiple options?

10:50 tonyl: I've heard textmate with the lisp bundle works fine with clojure

10:50 pair: Google found three, all on github. But github's search only found two. Figured there'd be opinions on here...

10:51 Thanks tonyl.

11:22 rpg: I have been trying to use swank-clojure from leiningen, but find that the slime connection keeps crashing with "unreadable message" errors. Is there an easy solution to this?

11:23 clojurebot: the leiningen screencast is on full disclojure: http://vimeo.com/8934942

11:23 raek: rpg: which versions of slime and swank are you using?

11:23 rpg: slime from CVS a couple of days ago. swank-clojure pulled by leiningen

11:24 two days ago

11:24 LIME 2010-11-07

11:24 s/LIME/SLIME/

11:24 sexpbot: <rpg> SLIME 2010-11-07

11:24 raek: the bleeding edge version of slime has been known to break compability

11:25 rpg: raek: Unfortunately, SLIME has no stable version. It's CVS or nothing...

11:25 :-(

11:25 raek: rpg: the version in ELPA should work

11:25 rpg: raek: OK, but I have no idea what damage that will do to my accustomed SBCL hacking....

11:26 raek: the docs for swank-clojure lists some preferences: https://github.com/technomancy/swank-clojure

11:26 rpg: raek: Not the fault of swank-clojure --- I wish there was more version discipline in SLIME.

11:29 raek: thanks.

11:31 raek: I'm sorry that I can't give you any better answer than "oh, I use this old version I found here, and it works for me"... :)

11:45 * raek has borrowed "Java Concurrency in Practice"

11:46 raek: it's a bit scary that every other line in the TOC is marked with "Don't do this"...

11:47 esj: that's funny

11:49 raek: I think the chapter about the executor framework could be useful for Clojurians too

11:49 AWizzArd: `(foo ~'object) produces (foo object). I want to type-hint object being a date, so ==> (foo ^Date object). Do I need something like `(foo (with-meta ~'object (assoc (meta ~'object) :tag Date)))? Or is there a better way to achieve this, when the actual type can vary?

11:50 rpg: raek: as a side note, given the problems with slime/swank compatibility, maybe it would be appropriate to modify swank clojure to simply catch stuff it can't parse, log it, and continue, instead of falling over...

11:50 raek: AWizzArd: with-meta is not done during compile time

11:50 AWizzArd: maybe you could do a `(foo ~(with-meta 'object ...))

11:52 AWizzArd: raek: but the principle idea to use meta & with-meta is correct yes?

11:52 tonyl: I don't get the need for ArrayMaps explained in http://clojure.org/data_structures

11:53 I think I am missing something here, are they Java arrays that can be used with maps fns?

11:53 raek: AWizzArd: do you always have 'object, or do you get that term from a parameter?

11:53 AWizzArd: you could also do `(foo ~' ^Date object), I think

11:54 stuartsierra: tonyl: no, just a map that happens to be stored as an array of key-value pairs, which is slightly more efficient for very small maps

11:54 AWizzArd: raek: I will probably enforce it to be always named object. But the type that I want to hint - that will vary.

11:54 raek: maybe one should write that as `(foo ~(quote ^Date object)) for clarity...

11:54 (meta 'foo)

11:54 ,(meta 'foo)

11:54 clojurebot: nil

11:54 tonyl: oh, wouldn't that make you loose the constant accessibility of values

11:55 raek: it doesn't seem like symbols have any metadata by default, so a (with-meta 'object {:tag <something>}) would perhaps be sufficient

11:55 ,(doc vary-meta)

11:55 clojurebot: "([obj f & args]); Returns an object of the same type and value as obj, with (apply f (meta obj) args) as its metadata."

11:58 technomancy: rpg: that would be nice. a lot of people complain about using swank-clojure and CL simultaneously, but precious few ever do anything about it.

11:59 rpg: technomancy: A challenge is that the two are maintained in divorced revision control systems. Also, I am a novice @ clojure so was pulling swank-clojure from technomancy, rather than using the git copy.

12:00 I tried to use the git copy, but didn't understand the instructions (as a novice, "what is this leiningen project of which you speak?")

12:02 I have only a binary, and nothing to attempt to cargo-cult fixes into.

12:05 amalloy: tonyl: if the type you want to hint to isn't always the same, i don't think type-hinting will be any better than using a java cast

12:05 AWizzArd: raek: yes, this vary-meta can be good

12:05 amalloy: (.cast Date 'obj) ; will return a Date object

12:06 er but without the quote :P

12:07 chouser: The video for my Strange Loop talk, "Clojure's Solutions to the Expression Problem" is up: http://bit.ly/9RMQGo

12:07 hiredman: :D

12:07 tonyl: ok mm

12:07 amalloy: tonyl: actually i just tried it in a REPL, and i think i'm wrong

12:08 (defn f [x] (.length (cast String x))) ; reflection

12:08 (defn f [x] (.length ^String x)) ; no reflection

12:08 esj: chouser: I really did wonder why you had all those photobombers on slide 2.... audio is so useful :)

12:08 clojurebot: In Ordnung

12:08 amalloy: why can't the compiler figure out the first one?

12:10 (it doesn't do any better with .cast, which surprises me more)

12:11 chouser: esj: :-)

12:11 tonyl: (doc cast)

12:11 clojurebot: "([c x]); Throws a ClassCastException if x is not a c, else returns x."

12:12 tonyl: cast is not much help

12:12 amalloy: tonyl: yes, i figured that out. but .cast should work

12:12 tonyl: what class is .cast from?

12:12 is not from object

12:13 amalloy: hm. it should be from Class, but i can't find it now

12:13 oh. i was looking at 1.4 docs :P

12:13 rpg: technomancy: seems like read-swank-message prints a System/err for unreadable message, and then throws it. That takes down the connection (at least the one I have). Any reason to throw this instead of logging it? There's no one to catch it, is there?

12:13 tonyl: there is a Class named Class?

12:13 amalloy: tonyl: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#cast%28java.lang.Object%29

12:13 tonyl: that is confusing lol

12:14 amalloy: tonyl: maybe, but it's necessary for a lot of things

12:15 tonyl: well, I am guessing it doesn't help because maybe the T is also a generic Object

12:15 amalloy: eg, this.getClass() == other.getClass() tests whether two objects are the same class. it's much harder to do this with instanceOf

12:15 tonyl: String.class is of type Class<String>

12:15 so in theory this should work - the java compiler gets it right

12:15 tonyl: but with clojure it doesn't

12:16 amalloy: well, the clojure compiler doesn't

12:16 tonyl: ok

12:16 so metadata in clojure

12:18 chouser: (doc cast)

12:18 clojurebot: "([c x]); Throws a ClassCastException if x is not a c, else returns x."

12:19 tonyl: $source cast

12:19 sexpbot: cast is http://is.gd/h8LH2

12:21 amalloy: chouser: i realize now that (cast) can't really type-hint the return type effectively since clojure doesn't have generics, but .cast should go straight to java, and the return type will be known, so long as String.class is treated as a constant

12:26 chouser: amalloy: (defmacro cast* [class obj] `^{:tag ~class} (.cast ~class ~obj))

12:27 amalloy: chouser: ah, well done. yes, it works as a macro, but cast isn't implemented that way

12:27 chouser: right

12:27 amalloy: for good reasons, of course, but it would be nice to have both

12:27 chouser: I suspect that's intentional -- keeping the type hint and the assertion separate, non-compound.

12:28 amalloy: chouser: more likely it's because you don't always have a class literal

12:28 chouser: oh, sure

12:28 good point

12:33 amalloy: and i guess whenever you do have a literal, you can use it to type-hint

12:34 chouser: if the type isn't known at compile time, you'll have to do reflection at runtime anyway.

12:34 amalloy: right

12:37 i note that ^hinting doesn't throw an exception on mismatched types until you try to use the wrong class; just storing the wrong class is okay

12:38 which seems reasonable, but tonyl, you may want to use cast as well as hinting

12:38 chouser: right, a hint is not an assertion

12:39 tonyl: i use both and actually use chouser's cast* for this project, which makes sense since I use class literals

12:39 thanks for the help guys

12:43 amalloy: chouser: i don't quite understand the style/idiom for *, still. doesn't foo* usually indicate a "you probably shouldn't use this" internal version of foo? it seems like cast* is the opposite, and i might call it cast+

12:43 tonyl: cast+ seems to me for multiple casts

12:43 chouser: amalloy: as far as I know, foo* in general just means "like foo"

12:44 like a prime tick mark in math. (x, y), (x', y')

12:44 there are specific cases where the foo* version isn't meant to be used, but I don't think that's always the case.

12:44 amalloy: chouser: mmmm, okay. speaking of which, doesn't 1.3 introduce +', *', and so forth?

12:45 chouser: but none of that is really meant to defend the name "cast*" Perhaps I should have used something else. "hint-cast" or something

12:45 amalloy: yes

12:45 clearly +* ** etc would have been less confusing. :-)

12:45 amalloy: hm. when i enter +' in my 1.2 repl, it doesn't evaluate as a symbol

12:45 chouser: har har. i'm not advocating that :P

12:45 chouser: amalloy: yeah, the reader changed to support that

12:45 amalloy: ah

12:46 hiredman: should just use the unicode prime mark

12:47 x′

12:47 tonyl: how do you get that mark?

12:48 amalloy: tonyl: my advice: don't :P

12:48 tonyl: yeah, can't seem to find it in my keyboard

12:48 i like hint-cast for the name though

12:49 amalloy: &[\u1234 \u2351 \u4351]

12:49 sexpbot: ⟹ [\ሴ \⍑ \䍑]

12:49 amalloy: tonyl: characters selected at random from unicode

12:50 tonyl: yeah my keyboard is not unicode friendly

12:50 amalloy: &\u2032

12:50 sexpbot: ⟹ \′

12:51 tonyl: there you go

12:51 :P

12:51 amalloy: &\u2057 ; extra ridiculous

12:51 sexpbot: ⟹ \⁗

12:51 tonyl: awesome

12:52 * tonyl time to go grab some lunch

13:17 quizme: how do you walk a social graph like this? {"david" '("sally" "ralph" "mark") "sally" '("ralph" "buddy") "buddy" '("david" "sally")}

13:17 i just want to count how big sally's social network is.

13:17 amalloy: quizme: what do you mean, walk it? you want to get out a series of pairs, like [david sally]. [david ralph]?

13:17 quizme: as in friend of a friend of a friend . . . .

13:19 amalloy: i'm thinking there will be separate (disjoint) social networks, and i want to count how many members are in one starting with one person.

13:20 amalloy: quizme: this is trickier. maybe clojure.walk/prewalk will be useful

13:20 quizme: but it's going to be big, so i dont' want to execute a memory-consuming algorithm.

13:20 jarpiain: quizme: there's lazy-walk in clojure.contrib.graph

13:20 quizme: thanks.

13:20 i'll look at both

13:21 amalloy: yeah, clojure.walk doesn't look useful for this case actually

13:23 i'm not sure there's a way to do this without using the stack, so memory consumption will be an issue

13:23 quizme: amalloy: it can hold N copies of the social network in memory, for small N.

13:24 amalloy: quizme: but you'll have to hold your place for every branch in the network. when you recur into sally's friend mark, you'll have to remember that you're supposed to look at eva next, for example

13:25 (only for every branch you actually traverse, of course)

13:26 quizme: amalloy: yeah that's the kind of problem i'm running into.

13:26 amalloy: you can put that memory in the heap or in the stack depending on how you want to do it, but the memory consumption will have to be O(mn) where n is the number of links you traverse to get to a friend, and m is the branching factor

13:27 n will tend to be log-base-m of the size of the input tree, i think

13:29 *disclaimer: i look forward to being proven wrong

13:35 Tordmor: ,(clojure.string/split "1xxxx2xx3xxxxx4" #"x*")

13:35 clojurebot: java.lang.ClassNotFoundException: clojure.string

13:36 amalloy: &(require 'clojure.string)

13:36 sexpbot: ⟹ nil

13:36 amalloy: &(clojure.string/split "1xxxx2xx3xxxxx4" #"x*")

13:36 sexpbot: ⟹ ["" "1" "" "2" "" "3" "" "4"]

13:36 Tordmor: thx amalloy

13:37 amalloy: welcome Tordmor. also, i'm 95% certain you don't mean x*

13:37 &(clojure.string/split "12345" #"x*")

13:37 sexpbot: ⟹ ["" "1" "2" "3" "4" "5"]

13:37 amalloy: &(clojure.string/split "12345" #"x+")

13:37 sexpbot: ⟹ ["12345"]

13:37 Tordmor: shouldn't * be greedy?

13:37 Ah, Ok, got it. Thanks amalloy

13:37 amalloy: Tordmor: yes, but it allows a match of length 0

13:37 qbg: &(clojure.string/split "1xxxx2xx3xxxxx4" #"x+")

13:37 sexpbot: ⟹ ["1" "2" "3" "4"]

13:38 Tordmor: It's obvious once you think about it :)

13:38 amalloy: indeed. a mistake everyone should make twice, and then never again

13:41 hey rhickey, quick question if you don't mind. i was discussing with chouser earlier why .cast doesn't include a type-hint when you're casting with a class literal. couldn't (.cast String "foo") return a String, since String.class is a Class<String>?

13:41 Tordmor: &(clojure.string/split "1xx2xx3xx4" 2)

13:41 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.regex.Pattern

13:41 Tordmor: &(clojure.string/split "1xx2xx3xx4" #"x+" 2)

13:41 sexpbot: ⟹ ["1" "2xx3xx4"]

13:42 Tordmor: shouldn't that be ["1" "2" "3xx4"] ? split twice?

13:42 amalloy: Tordmor: off by one. it means it will return a vector of at most N

13:42 Tordmor: &(clojure.string/split "1xx2xx3xx4" #"x+" 3)

13:42 sexpbot: ⟹ ["1" "2" "3xx4"]

13:43 Tordmor: Ok, thanks.

13:43 the docstring is misleading I think.

13:43 amalloy: Tordmor: it's poorly-phrased, but i wouldn't go so far as misleading

13:44 it's reasonable to call the tokens splits, rather than calling the delimiters splits

13:44 Tordmor: K, I'm not a native english speaker. I trust you there. :)

13:46 amalloy: the right answer is not to use the word "splits" at all in the docstring :)

13:47 jarpiain: amalloy: generics don't exist at runtime. clojure sees just that Class.cast() returns Object

13:47 amalloy: jarpiain: that's why i said class /literal/

13:47 (.cast String foo) can be resolved at compile time, because String is a Class<String>

13:48 (.cast some-class-obj "foo") can't type-hint, i agree

13:49 jarpiain: it could be done (there's some special code for instance? like that) but i doubt it's worth it

14:34 chouser: I still think OOP first so often

14:35 tonyl: guilty too, but some FP is creeping on my OOP programming too

14:43 amalloy: but i bet you both cry when you write a for loop instead of a map, reduce, or filter :)

14:43 and that's what counts

14:44 tonyl: yeah, for loops seem tacky now

14:50 rickmode: regarding OOP vs FP in Clojure, I find I use protocols frequently, as I all this OO experience let's me think polymorphically. I worry I overuse them.

14:51 prior to Clojure, I had the opinion that inheritance hierarchies should be as flat as possible to avoid the object-orgy problem, so moving to protocols is a natural transition for me

15:06 cemerick: Surely list comprehensions (for …) are still ok… ;-)

15:07 jcromartie: rickmode: the "object orgy problem" is new to me :) hah

15:11 http://c2.com/cgi/wiki?ObjectOrgy

15:11 rickmode: jcromartie: it's something I kept seeing even before the clever name. The other insidious variant is the break in encapsulation happening with inheritance leading to rigid inheritance structures.

15:21 jcromartie: also humans are fairly good at decomposing things in taxonomies (like Human, Mammal, Animal, Reptile, Snake, etc.). and so we do this in OO design, but forgetting that in reality, humans "map" taxonomies to reality, and change those taxonomies rather easily. So we end up with OO designs that calcify on an early understanding of a system that is increasingly incorrect. Sometimes we can "refactor" to fix thing, but often it

15:21 slightly wrong and gets worse over time.

15:24 jcromartie: basically, yes

15:24 seems like protocols are much better

15:46 rickmode: jcromartie: I like the Clojure approach of avoiding inheritance. Basically says: "we're human, we'll get it wrong anyway, so don't bother in the first place." ;)

16:05 jjido: rickmode: do you think inheritance is a good thing+

16:06 rickmode: jjindo: sure, but only in moderation. I think deep inheritance is fraught with danger. We rapidly pass that magic 7 +/- 2 limit in the brain.

16:09 jjido: Protocols are nice

16:09 rickmode: jjindo: that's my opinion anyway. The only cases where I've seen good deep inheritance are in general frameworks like java collections and cocoa touch where the domain is well known and the developers had lots of prior experience. even then it seems inconsistencies appear (I'm pretty sure java collections has some warts)

16:10 jjido: yes

16:10 it took time to establish current interface of Java collections

16:11 dnolen: rickmode: Cocoa is anti-deep inheritance as well. At least for points which are to be extended by users. Protocols are *extremely* important in Objective-C. Concrete derivation not so much. The main classes which are meant to be subclasses are views, and they don't generally come with much behavior.

16:13 rickmode: dnolen: ah.. it's been a few months since I looked... I just recall it being "clean"

16:13 dnolen: behavior + subclassing disastrous. I'm experiencing that right now with Django and Python.

16:14 I'm curious if there are any other dynamically typed languages that have something analagous to Clojur's Protocols ... none come to mind.

16:15 Chousuke: dnolen: a lot is done with delegates in Cocoa, right?

16:15 slyrus: so is the name of *clojure-version* going to change for 1.3?

16:15 dnolen: Chousuke: a *ton* yes.

16:16 Chousuke: it also seems to make it difficult for newbies to grasp - I've had difficulty teaching the beauty of writing extension points around protocols.

16:16 jcromartie: OK so let's talk... I'm pretty sold on building web apps in Seaside. But at the same time, I love object-less functional code in Clojure.

16:16 What about something like Seaside in Clojure?

16:17 Chousuke: dnolen: that might just be because subclassing is so prominently taught in schools :p

16:17 or just about everywhere

16:18 given a tutorial on extensible software, there's probably a greater than 50% probability it focuses on subclassing :D

16:19 jcromartie: I just hit a subclassing limit in OOP design today. Let's say you are building a web app and want to add tagging to certain model objects.

16:19 It doesn't make any sense to have some model objects be subclasses of TaggedObject

16:19 and if you just have an interface, then you're spreading a lot of copy/pasted code around

16:19 jjido: jcromartie: that is why AOP was "invented"

16:19 jcromartie: ah, hmm

16:19 seems like that should be easy in Smalltalk eh?

16:19 quile: jcromartie: that's also what categories are for in objective-c

16:19 rickmode: jcromartie: or mixins

16:19 jcromartie: yeah

16:21 rickmode: jcromartie: I know obj-c (not smalltalk) but can't you do slick delegation, adding in the specific behavior to the object (not classes) that need it?

16:21 jcromartie: yeah you can

16:21 I mean you can do whatever you want

16:25 rickmode: jcromartie: it's just this issue that kills me with OO. The taxonomy is subtly wrong. It sounds like what you have is an orthogonal concern and no idiomatic way to express it.

16:25 jcromartie: pretty much

16:25 rickmode: time to break out the GoF Design Pattern book... lol

16:25 jcromartie: although open classes and duck typing go a long way

16:25 heh

16:26 but with protocols in Clojure, it would be no problem at all

16:26 although really, I guess having an informal interface in OOP is close enough

16:26 it just breaks when you have rigid type systems

16:26 jjido: I am writing my own language. At first I thought I could use Clojure protocols to implement its object system, but it was too alien after all

16:26 rickmode: if you can get the effect of a mixin at runtime, then perhaps you have a good solution. Especially if this a common thing in smalltalk, and so you wont surprise other developers (or yourself in a few months)

16:27 jcromartie: there's no "runtime" in Smalltalk rickmode :)

16:27 there's only real time :)

16:28 that and the debugger are enough for me to toss out everything nice about Clojure for front-end/web apps

16:28 Clojure for the data layer

16:29 web services, things like that

16:29 rickmode: jcromartie: huh.. well I'm trying to use clojure for a web-tier. I feel like I'm reinventing a lot though.

16:31 dnolen: rickmode: like missing libraries?

16:31 rickmode: dnolen: like form validation... like authentication and authorization. I could use sandbar, i guess, but I'm really trying not to use dynamic vars (they feel like a cheat to me)

16:33 I'm trying to build on top of compojure / hiccup / ring

16:33 so that's still pretty raw compared to Rails or Django

16:37 dnolen: rickmode: sure but you could write a killer formset/validation library with protocols

16:38 rickmode: the django ones stink to high heaven when you need to specialize it

16:39 rickmode: dnolen: ya - i'm heading that way. at the moment i'm spinning my wheels with monads to see if that's a better approach. I already have something basic with protocols. The trick is to keep the validation logic separate enough from presentation so it isn't a ball of mud.

16:39 dnolen: rickmode: the only way to sanely simulate/extend the behavior django form/formset is dig through a lot of classes and worse metaclasses

16:40 and then you're still not sure if you have the complete set of functionality - there's no way to verify.

16:40 well besides trial and error

16:40 rickmode: dnolen: bummer. But then that makes sense. The more the framework does, the more specific it ends up being. Clojure's web building blocks are still nicely mix and match. It'll be nice if/when there are blocks for string localizable string resources, authentication and authrozating, form validation, form building, AJAX.

16:41 at some point the pieces probably end up specific, like sandbar and conjure though

16:42 dnolen: rickmode: untrue, the problem is not how much the framework does. i.e. Django is a toy compared to Cocoa. It's all about taking the time to decide the sane points of extension. But the Python language doesn't really support you there. Clojure nicely Protocols do IMO.

16:44 rickmode: dnolen: i see what you mean. that said, it is far easier to build a specific framework of any sort than a generalized and flexible one.

16:44 dnolen: rickmode: no argument there :)

16:45 rickmode: dnolen: couple that with "not-invented here" and over-engineering, and one can easily spend too much time in the wrong direction. *sigh*

17:01 jcromartie: yay/boo (strike as appropriate) for framworks

17:03 amalloy: is there a less ugly way to read a single character from *in* than (.read *in*)? it seems like it would be in clojure.java.io, but i don't see it

17:04 tonyl: (first *in*) maybe?

17:04 amalloy: tonyl: no, readers aren't seqable

17:05 tonyl: yeah, just tested it.

17:05 should've done that before opening my mouth

17:06 amalloy: tonyl: i have that problem a lot

17:06 tonyl: (first (read-line))

17:06 amalloy: that consumes a whole line. definitely no good

17:07 anyway .read isn't that bad, i was just hoping i could do it without . or earmuffs

17:07 chouser: Clojure doesn't fully absract IO

17:07 tonyl: http://clojuredocs.org/clojure_contrib/clojure.contrib.monadic-io-streams/read-char

17:08 bhenry: ring users in the house?

17:08 chouser: clojure.java.io (as hinted by the name) provides helpers for common tasks, but doesn't let you forget you're on Java.

17:08 amalloy: hah

17:09 SergeyD: behnry: Ring newbie

17:09 sorry, bhenry

17:10 jjido: damn, my IRC client died (again). Is this channel archived?

17:10 tonyl: clojure-log.n01se.net

17:10 bhenry: i want to wrap a ring handler so that exceptions lead to a custom 500 page. i have a wrapper for 404, but when there is a server error i just get a blank white browser window.

17:10 i think i'll take a look at wrap-stacktrace in ring-devel

17:11 it just came to me while typing that

17:12 amalloy: jjido: have a bouncer you can use, maybe?

17:12 rickmode: bhenry: check out Mark's own writeup on the subject: http://mmcgrana.github.com/2010/07/develop-deploy-clojure-web-applications.html

17:13 bhenry: rickmode. thanks

17:13 rickmode: bhenry: np. that was enough for me to create my own logging and nice, site specific 500 page

17:15 jjido: tonyl: thanks, I saw the part of the conversation I missed :)

17:15 tonyl: np

17:15 jjido: amalloy: a bouncer???

17:16 amalloy: $google znc

17:16 sexpbot: First out of 77600 results is: ZNC

17:16 http://en.znc.in/

17:16 amalloy: jjido: ^^

17:16 if you have an external server you can run daemons on...

17:17 jjido: allright. I think a less crashy IRC client will do for me :D

17:25 arohner: is there a way to get clojure paredit functionality in the slime buffer?

17:25 clojure+paredit works great on my source files, but in the slime repl, I don't get highlighting across { }, etc

17:56 nickik: @arohner there is but I don't have it either. You should be able to google it.

18:02 pppaul: paredit is a pain in the ass

18:02 really hard to delete parens when i want to

18:02 i guess it's a bit similar to parents

18:03 $8ball paredit mode?

18:03 sexpbot: pppaul: My reply is no.

18:03 pppaul: it has spoken!

18:04 nickik: @pppaul why do you have parans do delete?

18:05 pppaul: if i make mistakes in the structure of my code, there are usually lots of parents to delete

18:06 "(((" wont be deletable until everything inside of them is deleted... totally crappy most of the time

18:06 joegallo: M-r

18:06 pppaul: M-r?

18:06 $8ball M-r?

18:06 sexpbot: pppaul: Outlook not so good.

18:07 joegallo: (((foo bar baz))) -- cursor before the last (

18:07 M-r

18:07 pppaul: ok

18:07 joegallo: ((foo bar baz)

18:07 M-r

18:07 pppaul: i'll try that

18:07 joegallo: (foo bar baz)

18:07 "raise a sexp"

18:07 pppaul: nice

18:07 joegallo: Quite. :D

18:08 pppaul: well, maybe paredit mode will be more sexy from now on

18:08 i'm still a total emacs noob

18:08 joegallo: I'm only ahead of you by a few months, so never fear. You'll get there!

18:10 ivey: paredit is awesome once you learn the extra commands

18:10 you can knock sexps around

18:12 pppaul: enlighten me

18:12 how do i find the help file for paredit mode in emacs?

18:14 ivey: C-h a

18:14 is apropos

18:14 and then you can type anything there, like 'paredit'

18:14 joegallo: C-h m

18:14 ivey: and see a list of related funs

18:14 joegallo: will give you help for the currently enabled modes in the buffer you are in.

18:15 In a clj file, one of those modes will be paredit, and you can navigate there.

18:22 amalloy: pppaul: i usually end up using M-<up> or M-<down> cause i have trouble understanding M-r

18:30 pppaul: :D

19:29 Derander: ... and that takes care of work for today

19:33 amalloy: Derander: now, time to do more work, eh?

19:34 Derander: yep

19:34 interesting. apparently w/ those new amazon gpu instances you can crack any sha passwowrd hash < 6 characters in 45 minutes

19:34 <= *

19:42 * amalloy changes all his passwords from "java" to "clojure"

19:50 clizzin: Anyone know what the difference is between lein compile and lein javac?

19:54 pppaul: anyone think that implicit indexing (used in newlisp) will make it's way into clojure?

19:54 lancepantz: clizzin: i think lein compile compiles clojure, vs javac which compiles java code

19:55 clizzin: lancepantz: ah i see. do you know if javac also happens to compile any clojure code in the project?

19:57 _ato`: pppaul: it already has it

19:57 lancepantz: clizzin: the correct way to compile clojure code is to put it's namespace in the :aot key in project.clj

19:57 _ato`: if I understand correctly what you mean by implicit indexing...

19:57 lancepantz: clizzin: ie) :aot [foo bar]

19:57 pppaul: $(1 [4 5 6])

19:57 &(1 [4 5 6])

19:57 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

19:57 _ato`: ,(["a" "b" "c"] 1)

19:57 clojurebot: "b"

19:58 pppaul: oh

19:58 &( [4 5 6] 5)

19:58 sexpbot: java.lang.IndexOutOfBoundsException

19:58 pppaul: &( [4 5 6] 2)

19:58 sexpbot: ⟹ 6

19:58 pppaul: cool, didn't know that

19:58 amalloy: well, it doesn't work for non-vectors

19:58 just sets, vectors, and maps, i think

19:59 &((range) 2)

19:59 sexpbot: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

19:59 clizzin: lancepantz: oh weird, i never used :aot in project.clj before. how is using that different from the usual lein compiling/jarring process?

19:59 technomancy: clizzin: :aot used to be called :namespaces

20:01 lancepantz: clizzin: as i understand it, no clojure code will get compiled in the compile or jar tasks if they are not in the :aot or :namespaces key

20:01 clizzin: technomancy: i didn't use that either…maybe i misunderstand something here, but the projects i've worked on haven't defined either :namespaces or :aot, but i can still run all the usual lein commands on them. am i doing something different?

20:02 technomancy: clizzin: no, most projects don't require AOT. it's only needed for a few special cases

20:02 oh :main can also trigger AOT.

20:04 clizzin: technomancy: oh i see it's only for ahead-of-time compilation (hence the name "aot"…) great, thanks!

20:05 on an unrelated note, does anyone know why an attempt to include a dependency from clojars would fail? i'm trying to grab http://clojars.org/org.clojars.bmabey/clj-ml

20:08 Derander: does anyone know how to get something like this: http://www.youtube.com/watch?v=lf_xI3fZdIg (the arg list highlighting/persistence) up and running?

20:10 amalloy: clizzin: works for me. what's your project.clj look like?

20:24 clizzin: amalloy: yeah, just tried to pull it from inside a clean project.clj and it works fine. it actually looks like one of my original project's repositories is down, and the error there leads leiningen to quit early and then report clj-mj as missing, which misled me into thinking it was a clojars issue. thanks for checking!

21:20 defn: hola

21:23 tonyl: hello

22:21 dmiles_afk: good idea

22:40 bhenry: http://bearassbear.blogspot.com/2010/11/clojure-report-generation.html looking for constructive criticism.

22:49 jimduey: A few months back, I saw a blog post about analyzing stock charts using Clojure.

22:49 I've lost the link. Anyone know where that was?

22:52 dnolen: bhenry: w/o diving too deep that looks like pretty idiomatic Clojure code to me. only thing that stands out is going over report-items twice

22:59 bhenry: dnolen: thanks. do you see a way to avoid that? not that i personally can think of any report that would have over 100 columns.

23:25 dnolen: bhenry: maybe something like this? https://gist.github.com/701413. Not very efficient, may or may not matter your case. Might make sense to break out into a helper function for readability.

23:28 ,(map (juxt inc dec) [1 2])

23:28 clojurebot: ([2 0] [3 1])

23:28 dnolen: that's fun.

Logging service provided by n01se.net