#clojure log - Dec 26 2009

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

8:35 hchbaw: どこかを参考にしていたのですけれども、どこを参考にしていたのか忘れた!

8:35 Oh! I'm very sorry. :)

8:36 chouser: ooh, your exclemation point looks much nicer than mine.

8:57 hchbaw: Just a FYI, http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=978-4-274-06789-1

8:57 "Programming Clojure" Japanese edition :)

8:58 I would like to buy it, thanks!

9:16 emacsen: hchbaw, I think that if they translate it back to English, it will be very popular

9:16 after the Japanese translation it has all those cartoon high school girls

9:56 liebke: morning

9:57 liebke: emacsen: good morning

9:57 emacsen: liebke, where in DC are you?

9:58 liebke: I'm a few miles outside of DC in MD, up in the Silver Spring area

9:58 emacsen: Oh. I'm right downtown

9:58 (downtown SS)

9:58 I was thinking of heading to the Wheaton Maul later

9:59 It's too bad no one's taken up Conrad's request to run FringeDC

10:01 liebke: yeah, it's also too bad that dc study group has been inactive

10:02 emacsen: liebke, well you can revive it :)

10:02 Michael and I have been busy, but if you took it over, I'd help again

10:04 liebke: I'm hoping the new Reston group will get some momentum.

10:04 emacsen: too far for my blood :)

10:05 liebke: DC and Reston are equally inconvenient locations for me

11:07 neotyk: Hi

11:07 saml: hi neotyk

11:07 how are you doing?

11:08 neotyk: I'm good, how are you?

11:08 saml: I am ok. Thank you

11:09 neotyk: If in silme repl I do (use '(ns-name mod)) I get error that file not found

11:09 how do I specify path for swank?

11:10 the-kenny: neotyk: It's the java classpath.

11:11 neotyk: the-kenny: ok, but how do I set it?

11:11 bagucode: Is there anyone in here that knows a lot about java bytecode generation with the asm lib?

11:12 the-kenny: neotyk: Either with -cp.. at the command line or some config-variable in emacs

11:12 swank-clojure-classpath or so

11:12 Have to go, sorry

11:12 See you later

11:12 neotyk: the-kenny: thanks

11:16 chouser: bagucode: I've done a little bit with it, what are you trying to do?

11:20 bagucode: chouser: I'm interested in making a clojure wrapper for JNA (I know you made a small one already :)) and I want it to be as fast as possible. JNA supports something called "direct call mapping" but that requires static initializer code and use of the native keyword. So I was thinking of using clojure.asm to generate interface classes. But I don't know if the native keyword is supported by asm or even if it's necessary for JNA to work. I'm

11:20 doing a little research at the moment.

11:22 chouser: the approach you used is easy, but it's slower and a bit unsafe if you get the parameters wrong.

11:23 hiredman: asm does have a method modifier ACC_NATIVE

11:24 bagucode: hiredman: cool, thanks

11:24 I did a search of the manual but didn't find anything. Couldn't be bothered to read the whole thing :P

11:24 hiredman: Opcodes.java

11:26 bagucode: And the static initializer of a java class is just a static method with the name clinit right?

11:26 hiredman: sounds plausable, but I don't know

11:27 bagucode: hiredman: Alright, thanks a bunch for finding the ACC_NATIVE thing. I guess I can give this a go then.

11:38 erikprice: I'm getting a ClassNotFoundException when trying to compile a trivial Clojure file via the compile function in the REPL. I think my classpath is fine because I can run the file directly as a script at the command line. Any ideas?

11:41 somnium: erikprice: check *compile-path*

11:43 erikprice: somnium: Thanks. It was set to "classes" so I (set! *compile-path* ".") and retried the compile. Must be making progress because I no longer get an error, although the call to compile hasn't returned yet.

11:48 Interesting. Ctrl-D stopped whatever was hanging the REPL and showed that the problem was a NoSuchElementException on a line in which I was calling a function directly in the Clojure file. Commenting out that line allowed it to finish compiling. Thanks!

11:49 joshua-choi: Anyone here good at monads? I'm trying to create a monad operation (m-repeat pred m) that is like m-seq except in that it repeats a single monadic value until the result fulfills the predicate. But I'm stuck.

11:49 somnium: joshua-choi: try #haskell :P

11:50 joshua-choi: Ha ha, I can't understand Haskell at all, unfortunately

11:50 I only understand monads in Clojure :)

11:55 somnium: joshua-choi: I think Im still two or three tutorial (re)reads away from getting m-seq

11:55 joshua-choi: I was lucky in that I found monads at exactly the right time for myself

11:55 I was trying to write a parser library, and monads turned out to be perfect

11:56 * technomancy was under the impression learning monads was like having a baby

11:56 joshua-choi: I found it much easier thinking in terms of let and for, the two built-in Clojure monads

11:56 technomancy: there's never really a good time for it =)

11:56 somnium: joshua-choi: is there anything you need them for that you cant do with ->/->>/comp, do, and a macro or two?

11:57 joshua-choi: For my parser library, yes

11:57 And I'm sure for other things too

11:57 But the most useful usage of monads for me by far is the domonad form

11:57 somnium: joshua-choi: hmm, Id like to learn about the details

12:00 joshua-choi: can you recommend any detailed explanations of the monad laws? (I only found an utterly incomprehensible haskell page)

12:00 notostraca: Warm Fuzzy Things

12:00 joshua-choi: The monad laws? I only pay attention to them when I need to, which is only when I'm creating a new monad that has m-zero and/or m-plus

12:01 They're important, but I suggest that you try to get what monads are good for first; the laws are more petty practically in my opinion

12:02 My parser library uses monads like this: a "parser" is essentially a function that takes a sequence of tokens and returns two things: a new sequence of tokens with some tokens at the front consumed, and a data structure representing the consumed tokens

12:02 somnium: joshua-choi: all the tutorials Ive seen seem to show uses that are trivial without them

12:03 joshua-choi: Well, probably without m-zero and m-plus

12:03 I forgot: are there laws that involve just m-bind and m-result too?

12:03 somnium: joshua-choi: Ive been writing compiler, but I just pass a map up a recursive chain

12:03 joshua-choi: Yeah, you can do that

12:03 notostraca: maybe asking this in #haskell is a good idea

12:04 somnium: joshua-choi: I dont know, but it bothered me that the associative property made no sense to me

12:04 joshua-choi: notostraca: Well, I'm kind of afraid; I don't understand Haskell at all, so they might be annoyed at some non-Haskell person asking them questions

12:04 somnium: What do you mean by the associative property?

12:04 notostraca: they weren't annoyed when i tried to learn it

12:05 somnium: joshua-choi: theres probably some graduate students who will be to discuss monads in #haskell

12:05 will be delighted

12:05 joshua-choi: I think its the third LAW OF MONADS

12:07 joshua-choi: Yeah...it's "(m-bind (m-bind mv f) g) is equal to (m-bind mv (fn [x] (m-bind (f x) g)))" from Intensive System's tutorial

12:07 Yeah, I don't think about that at all

12:07 I'm sure there's some theory behind the law that has a good, non-arbitrary reason for it

12:09 But I find that I usually don't need to care about it to use (or even create) monads, as long as I'm using (or carefully altering) already made monads

12:09 I don't think you should worry about the laws for now; are they the only things hindering you?

12:10 somnium: joshua-choi: I think if I believed that I understood the algebra I would have an easier time

12:11 joshua-choi: Well, you'd probably have a deeper understanding, but I found that they're not necessary; I think of them as just axioms that monads happen to have to fulfill, or else monadic operations don't work on them

12:11 (not necessary to work through, I mean)

12:11 somnium: joshua-choi: clojure made much more sense to me once I understood exactly what fn* let* and var meant, but I suppose thats different

12:12 joshua-choi: Yeah, I still don't know what fn* and let* do

12:12 somnium: useless fact:

12:12 ,(macroexpand '(fn [] :x))

12:12 clojurebot: (fn* ([] :x))

12:13 joshua-choi: Oh, I see

12:13 somnium: ,(macroexpand #(keyword 'x))

12:13 hiredman: fn* is the primitive

12:13 clojurebot: #<sandbox$eval__4654$fn__4656 sandbox$eval__4654$fn__4656@19a83f3>

12:13 joshua-choi: I was under the impression than fn and let were considered special forms

12:13 Chousuke: they are.

12:13 somnium: ,(macroexpand '#(keyword 'x))

12:13 clojurebot: (fn* [] (keyword (quote x)))

12:13 Chousuke: the real special forms are fn* and let* but that's just a detail :P

12:13 joshua-choi: I see

12:14 Incidentally, which form implements the unpacking of parameter vectors: fn* or let*? I've always wondered

12:14 somnium: Im curious as to why #() expands different than single arity (fn [])

12:15 if its intentional or accidental

12:15 joshua-choi: ,(macroexpand '#())

12:15 clojurebot: (fn* [] ())

12:15 hiredman: ~#()

12:15 clojurebot: #() is not a replacement for fn

12:16 somnium: hiredman: that wasnt the question :)

12:16 hiredman: my js compiler is almost done, and the different expansions caused some odd behavior before I noticed them

12:19 argh, and Ive seen the #([1 2 3]) mistake so many times...

12:19 hiredman: if #() didn't expand the way it does you would have to double wrap everthing

12:20 #(first x) v. #((first x))

12:20 somnium: yeah, for some reason I just saw fn* and assumed they would be the same

12:21 is that behavior of fn* documented anywhere?

12:21 (fn* [] ()) vs (fn* ([] ()) ?

12:22 ,(doc fn)

12:22 clojurebot: "([& sigs]); (fn name? [params* ] exprs*) (fn name? ([params* ] exprs*)+) params => positional-params* , or positional-params* & next-param positional-param => binding-form next-param => binding-form name => symbol Defines a function"

12:30 chouser: somnium: no, "fn*" is an internal detail -- intentionally undocumented.

12:31 joshua-choi: neither fn* nor let* implement destructuring.

12:31 joshua-choi: chouser: Where, then? I couldn't find it whenever I looked at the source

12:31 chouser: destructure is a Clojure fn used by both the 'fn' and 'let' macros

12:32 joshua-choi: I see

12:32 chouser: I think. I'm seeing it in 'let' anyway.

12:33 somnium: ,(macroexpand '(let [[x y] [1 2]] {:keys [a b]} {:a 1 :b 2}))

12:33 clojurebot: (let* [vec__4682 [1 2] x (clojure.core/nth vec__4682 0 nil) y (clojure.core/nth vec__4682 1 nil)] {:keys [a b]} {:a 1, :b 2})

12:34 chouser: oh, I see -- 'fn' jsut detects that destructuring is required and expands to use 'let'

12:36 somnium: chouser: are there any examples of the core datastructures with deftype/defprotocol?

12:39 something like (deftype Cons [first more]) (deftype List [head size]) seems a reasonable start, but it would be good to seen an implementation by an experienced lisper

12:42 drewr: somnium: clojure doesn't have cons cells, but I was doing something similar a few weeks ago http://gist.github.com/248466

12:44 chouser: Clojure has a couple things very very close to a cons cell.

12:44 somnium: ,clojure.lang.Cons

12:44 clojurebot: clojure.lang.Cons

12:44 chouser: right, like that. :-)

12:45 ,(clojure.lang.Cons. :foo nil)

12:45 clojurebot: (:foo)

12:45 drewr: that's an abstration on top of seqs

12:46 but I see that somnium never really mentioned "cons cell" so I'll drop it :-)

12:48 rlb: Since java/clojure represents filenames as (utf-16) strings, what happens if the filename can't be represented as a valid utf-16 sequence?

12:49 chouser: rlb: is there such a filename?

12:49 rlb: i.e. in linux, filenames are arbitrary byte sequences

12:49 chouser: sure.

12:49 chouser: you can create any file name you want

12:50 (and there's also no way for java to know how to convert it to utf-16)

12:50 i.e. the filesystem doesn't have anything like a source encoding

12:50 (for names)

12:50 chouser: rlb: try it and let us know what happens. :-)

12:50 rlb: heh

12:51 chouser: the "correct" representation for a filename is probably a raw byte array, but that's not what java does afaik.

12:51 chouser: I think you may find any filename can be encoded into a Java string, even if it's not a "correct" translation. As long as the results are legal utf-16 and can be accurately translated back to filesystem filename bytes, you should be all set.

12:52 rlb: chouser: but some byte seqences won't be legal utf-16...

12:53 chouser: but what byte sequence can't be converted to legal utf-16?

12:53 rlb: chouser: I suppose there could be some escaping/unescaping, but how would java know the fs was in, say big5 rather than utf-8?

12:53 chouser: that's what I meant by it may not be "correct"

12:53 somnium: drewr: did you try using your implementation for map/filter et. all?

12:55 rlb: chouser: ahh, so you just mean that java may just assume that the fs is in a given encoding, say utf-8, and then perform the conversion. As long as the conversion is reversable, and you don't care which utf-16 strings you get, you may be all set.

12:55 chouser: right, though probably not utf-8 since there byte sequences that are invalid utf-8

12:55 rlb: chouser: That may be fine, as long as it's always possible to create *some* reversable valid utf-16 string from an arbitrary byte sequence.

12:55 chouser: right

12:56 but this is all speculation on my part

12:56 rlb: chouser: well, java's going to have to assume some encoding for the source, and I imagine the default is utf-8 (or something locale based).

12:56 sounds like a mess...

12:57 drewr: somnium: no, it was more a foray into mimicking haskell's type classes

12:57 rlb: No wonder you don't see many lower-level java "utility" programs (i.e. backup/restore, etc.)

12:57 chouser: are you sure filesystems can't report an encoding for their filenames?

12:58 drewr: somnium: but the example I was porting was illustrating recursion in type classes so it didn't really translate

12:58 rlb: chouser: most of the ones I know consider that an application layer issue.

12:58 chouser: the "official" type for a filename is "array of byte".

12:59 chouser: could be anything (except perhaps null).

12:59 (not sure about null)

13:00 At least for POSIX, it's dirent/opendir/readdir.

13:00 chouser: anyway, thanks for the help.

13:01 clojure doesn't have anything like a read/write syntax for arrays of bytes, does it?

13:01 chouser: rlb: into-array, aset, aget

13:01 somnium: related to seqs, what precisely is the difference between rest and next?

13:02 other that nil on '()?

13:02 chouser: that's it

13:02 in order to return nil instead of (), 'next' has to force an extra step of the lazy seq than 'rest' does.

13:04 somnium: are force and delay used to implement sazy seq

13:04 /s/sazy/lazy

13:04 chouser: nope

13:05 rlb: chouser: ok, right. Though for this purpose, I'd love something like "od -t a" where anything that was ascii was shown as a char, and other things were escaped, but I know that's a bit special-purpose. I think guile may do something like that i.e. "foo\005\001bar".

13:05 chouser: lazy-seq has what amounts to direct compiler support.

13:05 rlb: oh, I see what you meant by "syntax". There's no byte-array literal.

13:06 rlb: chouser: right, I figured there wasn't. Thanks.

13:06 chouser: or char-array, for that matter.

13:07 somnium: chouser: are there any usages of force/delay in the wild? the doc strings made me think of a contract for lazy seq

13:08 rlb: Seems like there are a number of practical things that java (and by extension clojure) would need before it could realistically be considered as a natural language for system use (a la perl/python/whatever). Though that just may not be a goal.

13:09 chouser: somnium: I used force/delay in finger-trees. I think cemerick has used them a bunch too.

13:10 rlb: mostly things that could be supported by libraries, though. swig and jna both attempt to solve several related problems while trying to provide easy access to C libs.

13:10 rlb: In this case, I wonder if the java posix lib might handle the filenames appropriately -- have to check.

13:12 chouser: true, though I just meant that (for example), in all the other languages, you immediately have getenv, the ability to see symlinks (at all), etc.

13:13 chouser: yeah, java has apparently tried hard to remove low level access to the host platform.

13:13 I'm sure they had their reasons, though I can't imagine I'd find them convincing.

13:13 rys: portability? :p

13:14 chouser: fortunately, jni was included and lets you work around those restrictions, and jna+clojure can pretty up the interface quite well.

13:14 rys: it's one thing to support writing portable code, another to try to enforce it (yet while leaving back doors like jni).

13:15 rlb: chouser: I certainly don't -- that stuff should just be optional, and have feature tests, or similar.

13:16 (don't find them convincing)

13:16 hmm -- hadn't seen jtux - that might be interesting...

13:16 chouser: rlb: I'd recommend jna instead

13:17 the posix and posix-like java libs I've tried so far have been hard to build and deploy, poorly documented, and poorly maintained compared to jna.

13:18 ~jna?

13:18 clojurebot: clojure-jna is http://github.com/Chouser/clojure-jna/tree/master

13:18 chouser: and apparently bagucode is working on something even better.

13:21 rlb: chouser: hmm, I'll have to look at that -- though I'm always a bit wary of the dynamic invocation stuff, presuming you have to hard-code the function sigs.

13:21 move from one arch to another... boom.

13:21 chouser: yeah, good point.

13:21 rlb: i386 -> amd64, etc.

13:22 (insensitivity to compiler defines, etc.) -- at least with jni/swig, the compilation step handles all that

13:22 chouser: but again, JNA is likely to have addressed common problems -- it's been a while since I looked at it.

13:22 rlb: (but it's much more tedious)

13:23 or unwieldy, rather -- to have to build the shared-libs, per-platform, etc.

13:23 Anyway, for my purposes, all really want a bulletproof subset of posix.

13:26 bagucode: rlb, chouser: Looks like the JNA folks got the native type size differences covered https://jna.dev.java.net/javadoc/com/sun/jna/NativeLong.html

13:29 rlb: To get it right every time using clojure-jna you may just need to pick which native lib to load depending on what (System/getProperty "system.arch") reports. You can bundle your app with many different native libs, one for each supported platform and architecture.

13:32 joshua-choi: Is there a function f so that (f [1 2 3] [5 7 2]) is the same as (for [x [1 2 3], y [5 7 2]] (list x y))?

13:35 rlb: bagucode: nice, though you can still have trouble figuring out what the right type is if there are a lot of header #ifdefs, etc. (and if they can vary per compilation).

13:36 but still -- it's interesting

13:49 KirinDave: Man, reading blogs on clojure by Java programmers is a tooth-grinding experience.

13:50 Reading things like, "clojure removes a few constructs which make “sense” (for loops for example)"

13:50 grind grind grind someone-wrong-on-the-internet grind grind.

13:50 pdk`: i like how "sense" is quoted

13:51 tolstoy: Does that mean it makes sense to remove them, or that clojure removes them, even though they make sense?

13:52 KirinDave: That guy is in the US. I've noticed that most of my peers in the US don't get exposed to much functional programing.

13:52 Seems like its more popular in Europe and China.

13:52 tolstoy: Link?

13:52 KirinDave: http://ossareh.wordpress.com/2009/10/12/learning-nio-via-clojure/

13:52 Bitching about NIO+Clojure.

13:52 Which is a pain. I'm still trying to figure out the right way to approach it.

13:53 somnium: KirinDave: if you figure it out let me know

13:53 KirinDave: somnium: I am going to try and mask things with the continuation monad.

13:53 pdk`: lots of colleges have moved to using more java than anything in their introductory cs cirricula

13:54 somnium: KirinDave: wow

13:54 pdk`: and beyond that even

13:54 KirinDave: somnium: ?

13:54 somnium: It makes sense since IO is chunked. It's kind of a pain to "read a line"

13:54 rlb: pdk`: unfortunately...

13:54 KirinDave: You have a Selector and a hash table carrying the current continuation for that selector.

13:54 somnium: KirinDave: right, I hadnt thought of involving monads

13:54 KirinDave: Well really, I want continuations. ;)

13:55 So you could have a (read-line) function.

13:55 And if it can't get a line it drops a continuation back out.

13:55 somnium: theres a few chunks of .java nio that read like C that Id like to get into clojure, but nio's been winning so far

13:59 KirinDave: Well I'm super impressed by netty, and I'd like to try seeing if I can make a more clojure-native system for that.

13:59 somnium: KirinDave: would it be possible to do something similar by just returning a function? or is the m-word really necessary?

13:59 KirinDave: somnium: You could, but then it makes all that work explicit.

14:00 somnium: hmm, I guess I ought to reread some haskell blogs

14:00 KirinDave: somnium: Without continuations, you'd write a macro to make a FSM language.

14:00 somnium: FSM?

14:00 KirinDave: And basically have things like (transition-> read-login) which would end with (transition-> chat-room-loop) etc etc

14:01 somnium: ah

14:01 KirinDave: somnium: finite state machine

14:03 cark: i solved the nio wait-line problem this way : the text is coming into an agent, when the agent sees a full text line it sends a message to itself, then i have the wait-line macro that only exits, leaving a "continuation function" in the agent state

14:03 when then line is received, it runs the function

14:04 KirinDave: cark: That's a nice resolution.

14:04 cark: I'm doing something somewhat like that now, myself.

14:05 cark: i'm not sure that's the best performance you can get, but the good point is that you can use send instead of send-off

14:05 there's no waiting

14:05 KirinDave: Right.

14:05 cark: so i had my whole encoding decoding line in an agent from the pool

14:05 line/stack

14:06 that's bytebuffer -> ssl -> utf -> processing then back again

14:06 err and per line chunking of course =)

14:06 KirinDave: Yeah, thats a good solution. Much simpler. :)

14:07 DeusExPikachu: anyone have any tips for learning about clojure's implementation of fn and defn? I want to read the source but looking at just how many files, I don't know where to start. Is there a way to trace evaluating a 'fn'?

14:07 KirinDave: The only reason I'm curious about this approach is that it lets you write huge long swaths of code as if you had blocking IO and a thread, transparently. Also, it lets you control the mechanism for threadpooling more carefully.

14:08 cark: KirinDave : well that's not like real continuations since the code of the "continuation" needs to be one level below the wait-line macro

14:08 but with smaller functions that's pretty readable

14:08 KirinDave: yeah.

14:09 Also, if you bury the acceptor code in a state monad, you can get away with having no refs.

14:09 Which I like very much.

14:10 cark: well you need state for the utf decoding if that's what you're doing

14:10 KirinDave: Why?

14:10 Can you just do that on the way down to the event handler?

14:10 That's what netty does.

14:10 cark: buit an atom can do, or you can stach it in the agent state

14:10 hum well

14:10 KirinDave: All your handler has to do is handle a string.

14:10 cark: you can but you never know if you're done with the decoding

14:10 KirinDave: And you can specify what kind of encoding it wants.

14:11 Why?

14:11 somnium: DeusExPikachu: clojure.core and (macroexpand '(fn []) are a start

14:11 cark: because utf might need 1 to 4 bytes for a single character

14:11 KirinDave: That's why you write your read-until function to abstract all that.

14:11 cark: so you have a byte buffer of say 1024, and it might be that the 2 last bytes are only part of a character

14:12 KirinDave: and then base things like read-line.

14:12 cark: but your read-until needs to return the state of the decoder !

14:12 unless you're using us ascii of course

14:12 KirinDave: That's in the continuation.

14:13 The decoder itself gets preserved in the continuation.

14:13 cark: oh i see

14:13 KirinDave: That's why I want to use a continuation, actually. :)

14:13 It's more efficient that way, you don't bind up threads on reads across blocks.

14:13 Or I suspect. I'd have to profile it to back that up with more than suspicion.

14:14 cark: i don't know if delimited continuations via monads are very efficient

14:14 KirinDave: I suspect they're plenty space efficient. I should profile trampoline to see how slow that is.

14:15 If trampoline is slow, then it's kind of a pain.

14:15 cark: that's pretty low level stuff, you want it very efficient (speed efficient), if it isn't you're as good using standard sockets

14:15 KirinDave: Of course, if it's slow but can handle 100,000 concurrent connections with a limited threadpool, then it's probably a fair tradeoff.

14:16 cark: That's the thing, you're not as well off using standard sockets.

14:16 cark: right

14:16 somnium: would having a form like (loop [...] (continue ...)), where continue returns a fn with the new state of the loop be equivalent to monad continuations?

14:17 KirinDave: Um, yes and no. :)

14:17 cark: though i'm yet to work on a server that requires 100k connections and does not require responsiveness

14:17 somnium: thats what I figured :)

14:17 KirinDave: It would not do everything that the continuation monad can do. But it would do a lot of what we want here.

14:17 Where the continuations shine is in allowing for abstractions over the block reads in the event of full buffers or chunked reads.

14:18 somnium: that should be possible with a macro, capturing closed over state would be the trickiest part, hmm...

14:18 cark: anyways the java codec are statefull so there isn't much to change

14:19 i mean not much state bookkeeping to do

14:20 KirinDave: somnium: Macros are a given for this.

14:20 cark: Did you see that amazing use of the continuation monad for web sequences with clojure?

14:21 cark: http://intensivesystems.net/tutorials/web_sessions.html

14:22 somnium: KirinDave: I looked at that code, but without a demo I think it was lost on me

14:22 something like Seaside in 90 lines of code?

14:22 KirinDave: Yes.

14:22 And the way you write the code is pleasant too.

14:23 The use case he has and the use case that an nio socket-server has are basically identical.

14:23 somnium: I find the nio socket case more compelling (not a big fan of continuation based web apps)

14:23 KirinDave: One thing I've noticed about nio though.

14:24 It seems like using threads that include reads is very… difficult.

14:24 cark: yes i did read this blog post

14:24 KirinDave: Because you have no guarantee that you're going to end up in your thread with enough data to process things.

14:24 cark: but i'm not sold on contiuations for the web

14:24 unless you can serialize these

14:25 somnium: I think state is better handled on the client, but thats a digression

14:25 KirinDave: cark: yes, that is a problem for web continuations. Not for event-driven socket servers though.

14:25 :)

14:26 And what's an ideal place for an event-driven socket server? How about a WebSockets implementation? :D

14:27 cark: mhh well, your web socket will surely need to access a database at some point, and that's blocking

14:27 KirinDave: Ah, well...

14:27 That's where your agent solution would come into play.

14:28 cark: that's what i did for database access on this project i was talking about

14:28 but it's annoying

14:29 you know : (with-db-request customer-by-id 25)

14:29 actually more like this: (with-db-request [customer-by-id 25] .....)

14:30 but in practice that was rather ugly

14:30 KirinDave: yeah well

14:30 No one ever said it wouldn't be. ;)

14:30 WebSockets is a fairly ugly idea.

14:31 cark: also you need to be extra carefull

14:31 just a single blocking call anywhere inside your app, and that's all for nothing

14:32 give the code to a maintainer, and he WILL break it

14:32 KirinDave: I'm not from that camp. :)_

14:32 If the maintainer breaks it, it's his problem. I'm not the kind of developer that's going to play read-the-future with stupidity in play.

14:34 somnium: I wonder if they say things like that in #perl :P

14:34 KirinDave: Google my screen name and find out which camp I come from. It's not hard.

14:35 But I'm not going to argue developer philosophy here. I know I'm in a radical minority opinion. :)

14:38 DeusExPikachu: somnium, any tools for tracing code? I'm used to using slime for CL

14:39 somnium: DeusExPikachu: clojure.contrib.trace?

14:42 or stuff like this?

14:42 ,(let [f #(* % %) g (fn [f x] (let [a (f x)] (println x a) a))] (map #(g f %) (range 5)))

14:42 clojurebot: (0 1 4 9 16)

14:43 somnium: :/

14:43 wheres his *out*?

14:46 ,(let [f #(* % %) g (fn [f x] {:input x :output (f x)})] (map #(g f %) (range 5)))

14:46 clojurebot: ({:input 0, :output 0} {:input 1, :output 1} {:input 2, :output 4} {:input 3, :output 9} {:input 4, :output 16})

14:47 quizme: http://github.com/ztellman/penumbra/blob/master/src/examples/tetris.clj <--- i am trying to get clojure tetris to work. but getting an error

14:47 the-kenny: quizme: "an error" shouldn't be there. Why aren't you fixing the error? ;)

14:47 quizme: http://pastie.org/757172

14:48 the-kenny: http://pastie.org/757172

14:48 the-kenny: ah sorry

14:48 quizme: Is penumbra in your classpath?

14:49 quizme: the-kenny i don't think so, i couldn't find any .jar files so not sure what to do

14:49 the-kenny: quizme: Take a look at the readme

14:50 hm.. nothing there

14:50 quizme: the README is in .md format

14:50 not sure how to read that

14:50 sorry i'm not a java guy

14:50 i'm lost

14:51 hey i found some jar files

14:52 the-kenny: quizme: readme is just text, but there aren't any instructions there

14:53 quizme: i'm going to copy all the jar files to my classpath

14:53 and see if that helps

14:54 the-kenny: quizme: ahh got it

14:55 http://wiki.github.com/ztellman/penumbra/getting-started

14:55 Found at the bottom of the readme

14:55 quizme: thanks

14:56 the-kenny: You're welcome

14:58 fliebel: What is a good web framework in Clojure? All I need is some prxml like stuff and an included server. I noticed thare are a few different ones, ant I wanted to know your opinions.

14:59 I'm not writing a web application, but an application that can serve some pages.

15:01 cark: fliebel : i think compojure is the most used

15:02 the-kenny: Yes, compojure is very nice

15:02 Integrated tools which are almost like prxml, simple start

15:02 fliebel: cark: but how about the other ones I found? I beleive they where caled webjure and cascade...

15:02 the-kenny: You'll have a simple application up in a few minutes

15:03 fliebel: Isn't cascade more like gwt?

15:03 (Widgets etc.)

15:03 fliebel: Does any of them have their own server, or do they all use servlets?

15:04 the-kenny: I only need to serve strings and files...

15:04 LauJensen: fliebel: Compojure runs both Grizzly and Jetty

15:05 danlarkin: ~ was working on something called clabango a while ago when suddenly

15:05 fliebel: LauJensen: that java stuff means nothing to me… Can I run it alone, or do I need a servlet container?

15:05 LauJensen: oh, that used to trigger something from clojurebot I think

15:05 danlarkin: :-D

15:05 LauJensen: fliebel: It stands on its own

15:05 Did you see my screencast?

15:06 the-kenny: fliebel: If you use leiningen, it pulls everything you need

15:06 fliebel: LauJensen: yea, You typed something like that, but it might just as well be configuration for the conatiner.

15:06 the-kenny: just add compojure to the dependencies and it will pull you a jetty.jar and everything

15:06 quizme: it is customary to put source files *and* .jar files in the CLASSPATH ?

15:06 LauJensen: fliebel: No, you actually saw Jetty boot up in the inferior lisp buffer

15:07 fliebel: LauJensen: Might have missed that… I'll look at it again now that I know more about Compojure :)

15:10 quizme: the-kenny: i copied the linux/64 *.jar files into ~/jars/penumbra/lib/ and the src files into ~/jars/penumbra/src/ and added those two directories to my $CLASSPATH environment variable, so do i have to restart the JVM ?

15:11 fliebel: LauJensen: you worked quite fast at times, at least for people who don't know emacs+clojure+compojure like me.

15:11 the-kenny: quizme: Quit the repl and restart it :)

15:11 quizme: the-kenny ok thanks

15:14 fliebel: LauJensen: Yea, It's at 9 min. I remember asking you about the html thing, but I must have missed the details of the server part.

15:20 quizme: http://pastie.org/757199 <--- is there a more intelligent way of adding multiple directories to my CLASSPATH? I have a feeling I'm doing something dumb.

15:21 neotyk: slime/swank question: how do I make swank see *clj files from src of my leiningen poject

15:21 I start swank via lein swank, and connect from emacs via slime-connect

15:27 fliebel: LauJensen: Now that I am going to use Compojure, are you going to do more screen casts about that? Your previous was a good overview of what is possible, it would be cool to see more detailed action of those things.

15:28 LauJensen: I'm actually preparing a screencast now which I hope to release in a few hours - its just about getting started with swank-clojure. You're looking for more Compojure oriented screencasts?

15:30 neotyk: LauJensen: I would like you to describe a bit more your setup, really liked this interactiveness in it, and now I'm struggling with emacs

15:30 LauJensen: neotyk: then this next screencast is for you

15:30 I show how to set up slime on emacs on a fresh install, so should be easy to follow

15:31 neotyk: LauJensen: this is awesome

15:31 LauJensen: :)

15:32 neotyk: If you can include some basic stuff after setup

15:32 that would make it great

15:32 LauJensen: I'm throwing in the kitchen sink, my .emacs

15:32 fliebel: LauJensen: Yes, I'll stick to Vim, but I will keep an eye on your blog.

15:33 LauJensen: fliebel: Thats fine, not everybody can handle the speed and power which comes with Emacs - and we respect that

15:33 fliebel: lol

15:33 neotyk: LauJensen, fliebel : you know that real man use ed, right?

15:34 fliebel: neotyk: no, what's that?

15:34 LauJensen: neotyk: M-x ed ?

15:34 Vim is M-x viper

15:34 neotyk: ed is less than sed

15:34 clojurebot: google ed

15:34 clojurebot: First, out of 40900000 results is:

15:34 fliebel: btw: real man don't eat honey, they chew bee's :D

15:34 clojurebot: Main Page - Encyclopedia Dramatica

15:34 http://www.encyclopediadramatica.com/

15:35 neotyk: clojurebot: not that

15:35 clojurebot: whose job is<reply>that is turbo24p1gs job

15:35 neotyk: clojurebot: google ed editor

15:35 clojurebot: First, out of 33400000 results is:

15:35 ed (text editor) - Wikipedia, the free encyclopedia

15:35 http://en.wikipedia.org/wiki/Ed_(text_editor)

15:36 neotyk: ohh my, just look at Example and its friendliness

15:39 fliebel: neotyk: you actually use this stuff?

15:39 "In current practice, ed is rarely used interactively"

15:40 neotyk: do you know some tutorial on how to manage windows/splits/buffers in emacs?

15:40 fliebel: noway, I'm VIM by nature

15:44 cark: neotyk : you should do the emacs tutorial

15:44 there you learn how to get healp

15:44 help =/

15:44 fliebel: neotyk: I also use Vim, but I just started, so in a very noobish way… only when I'm moving around stuff I'll try to use command mode. Sometime I even use the mouse as a quick way to move around and copy stuff! *hides*

15:45 neotyk: fliebel: I love vim, been using it for last decade, but emacs lisp powers are very attractive :)

15:46 cark: thanks, I'm starting Emacs tutorial right now

15:48 fliebel: I know lein downloads dependencies automatically, but half of them time I'm just running of the repl or running clj files directly. Is there a way I can have those dependencies in my cp? At the moment I keep copies of everything installed somewhere, which is not very nice.

15:48 tolstoy: Just remember Control-G. Backs you out of any command sequence. That was the key for me learning enough emacs to get by.

15:53 fliebel: find ~/.m2/repository | grep .jar$ sort of gets me a list of jars, but that is not exactly what I had in mind…

16:03 Found a solution I think… lein deps adds them to /lib, so I need to add that to cp.

16:04 How can I add Compojure to dependencies? I'm not sure about the version.

16:05 LauJensen: neotyk: Vimeo is converting the file now, so if it looks good, blogpost should be ready soon

16:06 neotyk: LauJensen: very nice, will provide feedback :)

16:06 LauJensen: Ye

16:06 yes, please send me a lot of positive feedback as I'm new to screencasting, if you happen to have some negative criticism, please send it to cgrand instead

16:08 fliebel: LauJensen: You said I can add Compojure to lein… what is the artifact and the version? http://clojars.org/repo/compojure/compojure/0.3.1/ == 404 :(

16:08 LauJensen: I did ? I don't use Lein

16:09 I remember somebody saying it, but it wasn't me

16:09 fliebel: Sorry...

16:09 *scrolling*

16:09 the-kenny: fliebel: wait

16:10 I have [org.clojars.liebke/compojure "0.3.1-master"] in my project.clj

16:11 fliebel: the-kenny: thanks! I found out via google that ato also contains it.

16:13 the-kenny: working!

16:13 the-kenny: fliebel: Nice :)

16:15 fliebel: booom! 10 extra jars in lib :D

16:15 neotyk: hey, what is with this versioning scheme all dependency resolution is done by maven subsystem, but version number contain -master-SNAPSHOT?

16:18 LauJensen: on what platform you record screencasts?

16:21 fliebel: Can someone tell me the correct line to show my cp? This is not it, apparently: (.getProperty (System.getProperties.) "java.class.path", null)

16:23 bagucode: fliebel: (import 'java.lang.management.ManagementFactory) (.getClasspath (ManagementFactory/getRuntimeMXBean))

16:24 or rather (.getClasspath (java.lang.management.ManagementFactory/getRumtimeMXBean))

16:24 fliebel: bagucode: "intensive research" turns out it's (System/getProperty "java.class.path") Prior java examples consisted of at least 10 lines.. man, these people got to love lines...

16:25 LauJensen: neotyk: Ubuntu 9.10

16:25 neotyk: LauJensen: what do you use to record sessions?

16:26 LauJensen: gtk-recordmydesktop

16:26 bagucode: fliebel: Oh I misread your previous post. I thought you said (System/getProperty... and that it didn't work :)

16:26 fliebel: My way is not the preferred, rather an alternative to getProperty

16:27 fliebel: bagucode: I would think so… It's about as long as most java examples I found.

16:27 well, probably not

16:27 bagucode: fliebel: One cool thing about the RuntimeMXBean though is that it knows the jvm arguments as well, if you want to get at those.

16:28 fliebel: cool

16:28 neotyk: ,(System/getProperty "java.class.path")

16:28 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission java.class.path read)

16:28 fliebel: What happens when I have multiple clojure jars on the cp?

16:28 bagucode: ,(.getClasspath (java.lang.management.ManagementFactory/getRumtimeMXBean))

16:28 clojurebot: java.lang.NoSuchFieldException: getRumtimeMXBean

16:28 bagucode: haha Rumtime

16:29 LauJensen: neotyk: http://www.bestinclass.dk/index.php/2009/12/clojure-101-getting-clojure-slime-installed/

16:29 bagucode: ,(.getClasspath (java.lang.management.ManagementFactory/getRuntimeMXBean))

16:29 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessClassInPackage.sun.management)

16:29 LauJensen: Hope it makes entry a little easier

16:29 hamza: guys what was the name of the function that returned a dir as a sequence? which lib it is located?

16:29 fliebel: file-seq

16:29 just core i guess

16:29 bagucode: ,(doc file-seq)

16:29 clojurebot: "([dir]); A tree seq on java.io.Files"

16:30 hamza: i was checking contrib lol , thanks..

16:30 fliebel: bagucode: I got the repl runnign with 2 versions of clojure and contrib on the cp… strange...

16:30 neotyk: LauJensen: thanks, watching

16:31 fliebel: LauJensen: me to...

16:32 LauJensen: Great

16:32 (I hope)

16:32 fliebel: But not with 100% attention… I'm just a little curious.

16:32 bagucode: fliebel: That totally works. I hate when stuff like that happens. I do Java at work, large webapp stuff and there is actually pretty often trouble with "version salad" and classloader issues related to stuff like that.

16:33 fliebel: bagucode: meh… bad! I'll have to work around that.

16:33 bagucode: fliebel: Here is the link to the doc for that bean thing by the way: http://java.sun.com/javase/6/docs/api/java/lang/management/RuntimeMXBean.html

16:44 fliebel: I made a clj script that works with the lib directory of any lein project and puts you in src :)

16:46 bagucode: Not an emacs fan? I always use lein swank.

16:46 neotyk: fliebel: you know that this is named JarHell?

16:46 LauJensen: Very nice video

16:47 LauJensen: informative will help a lot of people

16:47 fliebel: neotyk: how do you mean? I just put the dependencies of that project on the cp...

16:47 LauJensen: neotyk: Great - Glad you could use it (just realized who you were when I saw your photo on twitter)

16:47 neotyk: fliebel: multiple version of same thing on CP

16:48 bagucode: neotyk: I call it version salad :)

16:48 fliebel: neotyk: not anymore, I removed the other clojure… now I got clj for normal repl and cljp fro projects :)

16:48 so only lib and current directory on cp

16:48 neotyk: bagucode: I was hoping for OSGi to solve those problems

16:49 fliebel: neotyk; this also means I'm also using the actual clojure version that lein uses.

16:50 bagucode: neotyk: I don't know much about OSGi, I always distrust stuff at first and I haven't been forced to look at it at work so I haven't bothered learning more about it. Not really into Java stuff actually, it just pays the bills :(

16:51 fliebel: Time to leave, bye!

16:51 neotyk: fliebel: bye

16:51 bagucode: neotyk: Clojure actually made me more interested in Java hehe, at least the jvm bit

16:51 bye

16:52 neotyk: bagucode: agree, java is not much fun

17:14 quizme: is there a way to do this: -Djava.library.path=/.../penumbra/lib/osx with environment variables?

17:17 neotyk: quizme: what is ... ?

17:17 quizme: ... is the path to penumbra

17:18 neotyk: /home/david/.jars/

17:18 neotyk: than you do $ ENVNAME=env_value your_command and its parameters

17:19 quizme: neotyk: export java.library.path=/home/david/.jars/penumbra/lib/linux/64 ?

17:19 neotyk: CP=myjars java -cp $CP clojure.main

17:20 I think we are not on same page

17:20 quizme: i agree with that lol

17:20 the-kenny: neotyk: java.library.path is not the classpath

17:20 neotyk: what you want is not to provide -D to java but provide env vars that will do the job?

17:20 quizme: it's a library bpath

17:21 i remember seeing some documentation that clojure.main reads some environment variables besides CLASSPATH

17:21 something like LIB_OPT or something like that

17:22 the-kenny: quizme: Maybe the following works: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#setProperty(java.lang.String,%20java.lang.String)

17:22 neotyk: the-kenny: I was thinking of defining local env vars per execution, but I miss understood the question in first place

17:22 quizme: LD_LIBRARY_PATH ?

17:23 quizme: neotyk: there are a bunch of *.so files i want to load up

17:24 http://wiki.github.com/ztellman/penumbra/getting-started

17:24 neotyk: that's what we had to do for a client month ago, and nether bothered to blog about it

17:24 interacting with native code from JVM

17:29 quizme: the-kenny neotyk: maybe this DYLD_LIBRARY_PATH ?

17:29 neotyk: on Mac DYLD_LIBRARY_PATH on Lin LD_LIBRARY_PATH should contain all *.so you need and loading it from jvm should be ok

17:30 quizme: LD_LIBRARY_PATH

17:50 http://pastie.org/757287 <--- can somebody help me plz sorry...

17:51 i'm on 64 bit java on ubuntu 9.10,

17:51 trying to get the penumbra examples working...

17:53 the-kenny: quizme: Add clojure to your classpath

17:53 quizme: /opt/clojure ?

17:53 the-kenny: wait.. strange

17:54 quizme: Is $CLJ_ROOT/clojure/clojure.jar the location of clojure.jar

17:54 /opt/clojure/clojure/clojure.jar

17:54 quizme: i, ;e,,e cjecl

17:54 ino such file

17:54 /opt/clojure/clojure.jar

17:55 that's where it is

17:55 and also it's in /home/david/.jars/clojure.jar

17:55 /opt/clojure/clojure/clojure.jar doesn't exist

17:55 the-kenny: Then correct your call to java

17:57 quizme: oh i see

17:57 the guy who wrote that make a directory called /opt/clojure

17:57 then inside that directory, he did git clone

17:57 polypus: any overtone hackers in here?

17:58 quizme: the-kenny that makes sense

17:58 the-kenny i'll do it his way

18:04 the-kenny: finally got it working. Thanks so much.

18:04 the-kenny: quizme: You're welcome

18:08 quizme: the-kenny: a clojure version of tetris is what I always wanted for Christmas...

18:22 Raynes: I think somebody wrote a tetris clone a while back.

18:40 joolsa: Does anyone have experience of using clojure.xml/parse ?

18:40 I'm having trouble getting it to read from an InputStream

18:43 The repl give me "org.xml.sax.SAXParseException: Content is not allowed in prolog. (hist.clj:12)"

18:57 emacsen: is it valid XML?

19:05 PrinceOfA: how do i convert a list to a map?

19:07 i mean (1 2 3 4) --> {1 2, 3 4}

19:07 joolsa: Yes. I can run the process from the command line, pipe the output to a file, then (parse) that file fine.

19:08 I think I've a problem with whether I have bytes or characters and what encoding they are in.

19:09 I come from a C++ and Python background. I'm not familiar with Java at all :(

19:11 emacsen: how are you trying to parse the inputstream?

19:11 the-kenny: PrinceOfA: (hash-map 1 2 3 4)

19:11 ,(hash-map 1 2 3 4)

19:11 clojurebot: {1 2, 3 4}

19:12 Chousuke: use apply if the values are in a seq

19:13 PrinceOfA: thx!

19:15 obviously apply did the trick.. what does it do?

19:18 (doc apply) is not really helpful :)

19:18 clojurebot: "([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."

19:20 joolsa: Ah, thanks. It turns out my xml was malformed. It's amazing how you miss the obvious, until someone points it out! When I was spawning the process to generate the xml I wasn't using the same parameters that I used to generate the test xml. Doh!

19:20 Chousuke: well, function f applied to arguments x, y means (f x y)

19:21 so basically apply does function application :P

19:22 one of those things you just need to know

19:26 PrinceOfA: so (apply hash-map [1 2 3 4]) means (hash-map 1 2 3 4)

19:26 why args* argseq?

19:26 what does it mean?

19:30 the-kenny: PrinceOfA: You can supply an arbitrary number (or zero) of "normal" args, and after that, a sequence of args

19:31 PrinceOfA: (apply + 1 2 [3 4 5]) == (apply + [1 2 3 4 5]) == (+ 1 2 3 4 5)

19:31 PrinceOfA: the-kenny: can you give me an example where the args* need to be separate from argseq?

19:33 the-kenny: PrinceOfA: hm.. it's just for convenience

19:34 you can always cons all args* to argseq and use (apply argseq)

19:34 PrinceOfA: so basically it could be [f argseq]

19:35 the-kenny: hm no, that would be like (+ [1 2 3]), but apply applies the supplied list to f: (apply + [1 2 3]) = (+ 1 2 3)

19:37 quizme: is there a way to suspend garbage collection? It's annoying to get hit by an asteroid while the jvm is doing garbage collection...

19:38 slashus2: quizme: Are you okay? :-P

19:38 quizme: slashus2 hehe it didn't hurt that much

19:41 and sometimes the keyboard inputs are not snappy responsive

22:47 chouser: ugh

22:48 devlinsf: ?

22:56 chouser: I've got code snippets I need to eval

22:57 I need to capture anything they print

22:58 but some of them start a new thread and print from there.

22:58 I'm stumped

23:00 I guess I could alter-var-root and then change it back again.

23:00 ...and that brings me back to "ugh"

23:01 devlinsf: Hmmm

23:01 It's ugly... but you could set up a temp dir, give each thread a file and look at the results

23:02 but I mean UGLY

23:02 hugod: Does (set! *out* ....) not work?

23:02 quizme: is there a way for a macro to grab what preceded it ?

23:04 i want to make clojure understand 1 + 2

23:04 rather than + 1 2

23:04 chouser: quizme: haha!

23:04 no

23:04 devlinsf: chouser: Get this one

23:04 quizme: hmm

23:05 slashus2: quizme: By the time you end up finishing that macro, you will probably realize you don't need it.

23:05 chouser: quizme: http://paste.lisp.org/display/75230

23:05 quizme: i'm sure i don't need it

23:05 just wanna mess with clojure's head

23:05 devlinsf: quizme: Just to see what happens?

23:05 quizme: to see if it's possible

23:06 devlinsf: Okay, so when you say 1 + 2, do you mean "1 + 2" or (1 + 2)?

23:06 quizme: 1 + 2

23:06 devlinsf: A string, not a datastructure

23:07 quizme: data structure

23:07 i want to type in 1 + 2 at the REPL

23:08 devlinsf: Okay, that's a string

23:08 At least, from the REPL's perspective

23:08 quizme: k

23:08 pdk`: that's not going to be read by your macro either way if you enter just that

23:08 if you enter it like (mymacro 1 + 2) maybe

23:09 devlinsf: You could implement a custom reader... I don't recommend it

23:09 Why do you want 1 + 2 at the REPL?

23:09 quizme: just to see what the limits of macros are

23:09 devlinsf: Macros operate on datastrutrues.

23:10 As long as you get the 1+ 2 in the repl as a data structure, you're golden.

23:10 quizme: thanks

23:10 that answers my question

23:10 slashus2: As was shone by chouser, it doesn't really need to be a macro.

23:11 Try a function first before you write a macro.

23:12 quizme: i was mainly wondering if it's possible to break out of the parentheses

23:12 and make up a new syntax

23:12 devlinsf: Yeah, it's possible

23:13 Highly discourages

23:13 discouraged

23:13 slashus2: You would probably have to mess with the reader macros.

23:13 devlinsf: Actually, worse

23:13 You'd have to parse your result into an abstract syntax tree

23:13 * slashus2 screams

23:13 devlinsf: It's something a list reader doesn't have to worry about

23:14 quizme: interesting

23:14 devlinsf: quizme: If you're really really really really really really interested, start at LispReader.java

23:15 quizme: probably not that interested

23:15 just trying to understand macros

23:15 devlinsf: It's amazingly small for what it does

23:15 quizme: thanks a lot

23:15 devlinsf: No problem

23:16 chouser: well, another option is to have an outer macro or fn, one set of parens. Then inside that is your playground, as long as the reader doesn't choke on anything you need.

23:16 devlinsf: Or, simply put everything in a string

23:17 ( because the reader WILL choke on SOMETHING)

23:17 chouser: heh

23:17 the reader chokes on " in strings. :-P

23:17 devlinsf: And it should

23:17 Or do you mean \"

23:17 ?

23:18 chouser: well. I still wish for alternate string-quoting syntax.

23:18 devlinsf: Yeah, except ' is taken

23:18 :(

23:18 chouser: like python's triple-quote or here-docs, or something.

23:19 devlinsf: Did you see Chas Emerick's interpolator?

23:19 chouser: I did

23:19 devlinsf: Did you like it?

23:19 Or are we talking about a different problem?

23:20 chouser: different problem

23:20 devlinsf: Ah, okay

23:21 chouser: perl and ruby support using different quoting delimiters, like q{string here with "quotes" even}

23:21 devlinsf: I've hacked Ruby, I see what you mean now

23:21 chouser: python has """triple quotes that allow singe " and double "" internally with no problem"""

23:23 devlinsf: Hmmm... triple quotes would be doable. The trick would be to add support for multiple character closing delimiters in the reader

23:23 chouser: well, alter-var-root works. :-/

23:23 devlinsf: If the plan is to add block comments eventually, this might be doable

23:23 Glad it to hear it

23:23 lisppaste8: Chouser pasted "with-root-out-str" at http://paste.lisp.org/display/92670

23:24 chouser: so horrible

23:24 _mst: that's the wonder of macros... now you can repress the implementation and never think of it again :)

23:24 chouser: heh

23:25 actually, should be just a high-order fn, I suppose.

23:26 devlinsf: chouser: Hmmm... I like the macro better

23:27 Unless you want to map it

23:29 chouser: nah, I'll leave it as it is. This whole program is a giant ugly hack.

23:29 leaving it as a macro keeps it more like with-out-str, which is the impression I want to give.

23:30 this is for checking the examples in our book

23:30 devlinsf: When will an electronic version come out?

23:32 _mst: if you've got multiple threads sending output non-deterministically, isn't it going to be hard to check the output?

23:32 chouser: I wish I knew. We were hoping to have the first 4 chapters up before Christmas, but that didn't happen.

23:32 _mst: or is there an equal amount of regex hackery involved? ;)

23:32 chouser: _mst: indeed, very ugly regex hackery.

23:33 this script is also the source of the pop quiz a few nights ago.

23:33 _mst: ah, the Pattern one? heh

23:34 chouser: right, comments in regex. :-P

Logging service provided by n01se.net