#clojure log - Sep 29 2010

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

0:16 technomancy: time to find a new name for pods: http://www.theregister.co.uk/2010/09/24/apple_pod_row/

0:20 amalloy: technomancy: they're just jealous that facebook owns the word Book

0:22 jk_: is map destructuring supposed to work on function arguments? that's what i read in the docs but it doesn't seem to be working. doing it in a "let" inside the fn works though

0:23 bhenry: show us

0:23 it should work

0:24 jk_: (defn foo [{major :major minor :minor} m] (str major "." minor))

0:25 call it like: (foo (hash-map :major 8 :minor 13)) gives wrong number of args

0:25 lancepantz: the m is implicity

0:25 technomancy: jk_: where's m coming from?

0:26 lancepantz: s/y//

0:26 sexpbot: <lancepantz> the m is implicit

0:27 jk_: technomancy: m isn't the argument map that i pass on the call?

0:27 (defn foo [m] (let [{major :major minor :minor} m] (str major "." minor))) that works

0:27 technomancy: jk_: no, m is the second argument in the arg list, but when you're calling foo, you're only passing in one argument

0:28 right, because in that case m is the argument to foo

0:28 jk_: technomancy: doh! sorry. i see

0:28 i misunderstood the syntax

0:28 i see now

0:28 technomancy: yeah, it's not quite the same since in let you have both the form to bind to and the value next to each other

0:29 whereas in defn, the value is provided at the call site

0:29 jk_: technomancy: got it. glad the clojure community puts up well with newbies :)

0:29 technomancy: everyone starts at the beginning

0:30 amalloy: jk_: and if you don't care about performance, you can construct the map in the function instead of at the call site: (defn foo [& {m :major}]...) (foo :major 10)

0:32 jk_: amalloy: it has to be at the call site since i'm getting it from elsewhere. gonna call this from a map() that gets this hashmap from a separate function

0:33 amalloy: i mean foo() doesn't actually know what's in it. i was just doing a test, learning about destructuring

0:34 amalloy: sounds like a plan, then. i think it's neat that my form actually works, but if it's no good for you then don't use it :)

0:35 jk_: amalloy: believe me, i enjoy hearing about all input since i'm just learning. what i meant to say is in the actual program, i'm not building the map where foo is called, i just get that map from somewhere else entirely

0:43 amalloy: btw jk_, is there a reason you're using (hash-map :a 1 :b 2) instead of just {:a 1 :b 2}?

0:44 jk_: amalloy: nope. just didn't immediately see the doc for creating a hashmap literal so i used the function call

0:44 amalloy: well, there ya go

0:44 jk_: :)

0:51 technomancy: stubs! http://github.com/technomancy/rodney-leonard-stubbs

0:51 gotta love projects for which the readme is significantly longer than the code

0:52 "The Man with the Blood on his Hands"

0:54 jk_: rhickey: btw, thanks for creating this! i kept looking at lisp for a loooooong time but the immediate productivity by having access to java libs got me off my butt (though i understand that it's controversial among long-time lispters)

1:08 amalloy: jk_: i actually tried lisp out for a few weeks, and while it was very nice in theory i never really got the hang of it. picked up clojure a couple months ago and the honeymoon isn't over yet...

1:10 jk_: amalloy: i came from years and years of c/c++/java and then started playing with groovy, which i think makes java a lot more tolerable. but i figured i finally had to get serious and either learn haskell or clojure

1:10 technomancy: pet peeve: you mean Common Lisp?

1:10 amalloy: technomancy: i actually even meant to type CL!

1:11 but then some sort of demon got hold of my fingers or something

1:11 technomancy: well it doesn't help that CL isn't case-sensitive

1:11 (proper nouns at and all)

1:12 jk_: amalloy: i only read the theory on lisp and read some code but never actually tried writing it until clojure

1:13 amalloy: technomancy: sorry, can't parse that last message

1:14 technomancy: amalloy: well, Lisp is a proper noun referring to a specific language, while lisp is a family of languages. but CL doesn't distinguish between the two since like many things from the 80's, it's case-insensitive.

1:15 jk_: technomancy: you mean "Lisp" is synonymous with CL to the community?

1:16 hiredman: well, to the cl community

1:19 technomancy: I guess all that to say if you're going to use one word to refer to CL, it's less ambiguous if you capitalize it.

1:20 hiredman: or just refer to it as that thing those guys did that one time

1:21 jk_: lol

1:27 technomancy: "Common Lisp: some guys did it once, and so can you."

1:39 replaca_: technomancy: you make me feel like a grandpa!

1:43 amalloy: jk_: what editor are you using, if i may ask?

1:43 jk_: counterclockwise on eclipse

1:44 amalloy: how's that working? i tried it a few months ago but things didn't seem to work very well

1:44 jk_: amalloy: just because i already knew eclipse and didn't feel like learning emacs (being a vi guy)

1:44 amalloy: heh. i understand there are decent vim modes for clojure, but i confess i saw this as an opportunity to learn emacs

1:45 jk_: amalloy: it's working very well now. but it seems to have a problem wtih the repl hanging when a lazy seq gets returned, even if it's a short one that displays just fine on the cmd line repl

1:45 amalloy: that hangs teh entire eclipse environmetn

1:45 amalloy: weird. and a lot of things are lazy, so this must happen a lot?

1:46 jk_: amalloy: well normally i'm using them somehow rather than just typing random things into the repl in eclipse

1:46 amalloy: you'd be surprised how much you can learn just typing stuff into the repl to see what happens

1:47 jk_: amalloy: right. so i do that at the command line normally so i don't run into that ccw bug :)

1:47 amalloy: aha

1:48 jk_: amalloy: a lot of times, if i'm typing something longish and don't feel like starting eclipse, i edit it in kate (i'm using kde) and run it from the cmd line

1:49 amalloy: i'm sure it's vastly inferior to using emacs but oh well :)

1:49 amalloy: ccw is actually very nice when it doesn't hang :O

1:50 amalloy: i found an acronym for emacs that i quite like. i'm sure all the old-timers will have heard it, but i enjoy my Editor for Middle-Aged Computer Scientists

1:50 raek: you mean Escape-Meta-Alt-Control-Shift?

1:52 amalloy: raek: i saw a picture of a space cadet keyboard for the first time today. that's a lot of modifier keys

1:54 i knew about hyper/super/meta/alt/shift/control, but i didn't realize they also had Top/Front

2:16 replaca_: tolsen: if you're there. Autodoc is fixed now.

2:58 LauJensen: Good morning all

3:02 amalloy: heh. when LauJensen gets here, that's how i know i ought to be in bed

3:02 LauJensen: :[

3:07 tobiasraeder: What do i have to do if i want to parse the return value of a function into a macro? for example i want to call (gen-interface :name user.myinterface [(getter {:name "paramName" type:String})})

3:08 where getter is the function that i want to evalutate before passing it into the macro

3:14 amalloy: tobiasraeder: unless i'm misunderstanding you, you can't - macros happen at compile time

3:15 tobiasraeder: @amalloy makes sense. if i replaced the function with a macro that should do the trick tho?

3:15 amalloy: is the data all known at compile time?

3:16 tobiasraeder: yeah it is

3:16 and getter should just generate a vector with some symbols/class names

3:16 amalloy: then there's certainly *a* way to do it. i actually wouldn't suggest making getter into a macro

3:17 tobiasraeder: what would you suggest? im looking for a way to just supply a name and a class (value type) and generate an interface based on a list of those informations

3:17 amalloy: instead, make getter a function that *looks* like a macro in that it operates on code (which the macro will pass to it) and returns code, but it allows its parameters to be evaluated inline

3:17 one sec and i'll put together a gist

3:18 tobiasraeder: thank you :)

3:23 amalloy: tobiasraeder: http://gist.github.com/602399

3:24 not actually working, but you can see what i'm getting at, i hope?

3:24 tobiasraeder: yeah i see

3:24 and can i pass the make-gets into gen-interface?

3:26 amalloy: right, because it will expand into real code, still at compile time, which gen-interface will understand

3:26 tobiasraeder: alright

3:26 ill try that in a minute. thank you very much

3:29 amalloy: tobiasraeder: a version that actually works, in that it defines some variables: http://gist.github.com/602404

3:30 honestly i've written (defmacro foo [& args] `(do ~@(apply map somefn args))) enough times that i ought to make a macro for it :P

3:30 tobiasraeder: hehe

3:31 but i do have to def all the variables i want to pass to the macro this way?

3:31 maybe im just getting it wrong again tho

3:31 amalloy: not sure what you mean?

3:32 oh oh oh. no, my macro is an example of how you could write a macro that uses a function; there's no reason to actually (def) anything in your code

3:32 shachaf: amalloy: What's the point of doing that as a macro?

3:32 tobiasraeder: ah okay

3:33 amalloy: scgilardi: nothing really, for a simple def

3:33 but if it's something more complicated like gen-interface, which you need to call ten times on ten similar objects, it's silly to write gen-interface ten times

3:33 shachaf: Oh, I missed some context.

3:35 tobiasraeder: actually i want to define one interface with x times make-getter and make-setter

3:35 amalloy: shachaf: the exercise was to avoid needing *two* macros here, one for make-gets and one for make-getter; make-getter could afford to be a function

3:37 tobiasraeder: was that asking for more help, or just explaining to shachaf?

3:37 tobiasraeder: i wanted to start to explain it

3:43 @amalloy would you mind taking a look at http://gist.github.com/602418 ?

3:43 it evaluates, but doesn't create any new functions for the interface. maybe i'm just overlooking something

3:44 amalloy: well, now you don't have any macros at all. you still need one macro for the top-level entry point

3:45 tobiasraeder: well gen-interface is a macro

3:45 amalloy: something like: (defmacro make-gettable-iface [name type] `(gen-interface ...~(make-getter type)))

3:46 tobiasraeder: right! and that means it won't evaluate make-getter, because that's a run-time function that it can't know about

3:47 but if *you* write the outermost macro, you can evaluate whatever parts you want before passing it down to the "dumb" gen-interface

3:47 tobiasraeder: ah now i think i finally got it

3:47 amalloy: btw is there a reason you're using (vector), (list), and (hash-map) instead of [] '() and {}?

3:48 tobiasraeder: not really guess i should replace them

3:49 amalloy: well, do whatever you feel is most readable. if you're still getting the hang of the literal syntax and want a reminder of their names, feel free

3:55 tobiasraeder: actually i think im fine with the literals. just got really mixed up in my head with the macro/gen-interface stuff

3:56 and yay it is working now

3:56 amalloy: wooo

3:56 tobiasraeder: i got an interface with one getter now, yay me

3:56 amalloy: yes, macros are mind-bending no matter how much you do them

3:56 tobiasraeder: lol

4:00 amalloy: tobiasraeder: okay, just got my version working. compare notes?

4:01 tobiasraeder: @amalloy sure

4:01 Kaali: How can I import two Java classes which has the same name?

4:01 amalloy: Kaali: import one of them, and refer to the other with a fully-qualified name

4:02 tobiasraeder: doesnt import allow :as?

4:02 @amalloy http://gist.github.com/602418

4:02 Kaali: Doesn't seem like import allows :as

4:02 amalloy: i don't think it does, but i could be wrong

4:03 Kaali: amalloy: How do I refer to it, as I can't import it at all.

4:03 amalloy: java.util.Date

4:03 don't import it

4:03 tobiasraeder: yeah my bad.

4:03 amalloy: you don't have to import, just refer to it with its long name

4:04 Kaali: Thanks, just a foolish mistake. I tried to use java.lang.Date, not .util.

4:04 I wondered why other classes worked with full name and this one didn't.

4:04 amalloy: tobiasraeder: http://gist.github.com/602441

4:05 heh. and i guessed right. it's always Date :)

4:05 Kaali: Yup =)

4:06 tobiasraeder: @amalloy yours is obviously a bit further down the road and pretty much exactly what i was looking for ;)

4:06 amalloy: good! steal it, but obviously learn from it too

4:06 Kaali: Curses, I just rewrote a function which uses Date, and I referred it as java.lang.Date... again!

4:06 tobiasraeder: yeah i think i just learned quite a bit. Thanks alot.

4:07 amalloy: tobiasraeder: and maybe adjust the method-name generators: getname is kinda lame. otoh i guess the user should solve this by passing Name instead of Age

4:08 oog, LauJensen got here an hour ago and i'm still up. bedtime for me. have fun, Kaali & tobiasraeder

4:09 tobiasraeder: @amalloy thanks alot for the help and sleep well.

4:09 LauJensen: Good night :)

4:09 Kaali: Thanks again amalloy

5:08 akuzi: anyone know when the keynote/sessions start at clojure-conj on Oct 22. i'm thinking of flying down in the morning.

5:12 xkb: no idea yet, but my ticket is "in the bag" :)

5:12 looking forward to it

5:16 LauJensen: akuzi: Theres a contact email on the website

5:17 xkb: What's Durham like anyway?

5:20 LauJensen: xkb: Its Durable, but with ham

5:21 xkb: hehe

5:21 smells sweet ;)

5:23 esj: I'm deeply tempted to go over for it

5:23 akuzi: the site says 9am

5:25 akuzi: oh really?... thanks..

6:48 bobo_: didnt someone in here talk about doing an etl in clojure?

7:01 cemerick: etl?

7:01 extract transform load?

7:01 bobo_: yeh

7:01 data warehouse stuff

7:01 i found some utils att github, so i cant be alone in the thoughts atleast

7:01 cemerick: Lots of that going on, though people are quiet about it for the most part.

7:02 Not really the sort of thing that the open source folk are big into :-)

7:02 bobo_: indeed

7:02 cemerick: web framework v396 is *much* higher priority ;-)

7:02 bobo_: hehe, we need more frameworks

7:02 and fartapps

7:02 cemerick: heh

7:03 LauJensen: haha

7:03 cemerick: A friend of mine is using clojure for etl of medical data. Gnarly stuff.

7:03 Had to write the parsers and such from scratch, of course.

7:03 bobo_: i have everything in databases atleast

7:04 cemerick: lucky

7:04 bobo_: yes, if it where fever then about 100 databases it would be awesome =)

7:05 cemerick: flat files, as far as I've heard -- many gigs at a time, with fields and subfields and sub-subfields delimited by *, pipes, $'s, and god-knows what else

7:06 bobo_: fun fun :-)

7:09 LauJensen: cemerick: I have had at least one experience of looking at a file like that, which almost seemed encrypted and hand craft to be unparsable. So I asked Christophe how he would approach it and he almost immediately replied with a regex which did the job. O_o

7:09 cemerick: LauJensen: lucky you :-)

7:10 Apparently many such files have different delimiters depending on which sub-subfield you're in.

7:10 Making a regex impossible, of course.

7:10 Thank goodness, I've never had to do such stuff myself.

8:09 chouser: ping

8:17 AWizzArd: rhickey: is (biginteger 13178456923875639284562345789) supposed to throw #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for long: 13178456923875639284562345789> ?

8:18 rhickey: AWizzArd: 13178456923875639284562345789 is not a valid numeric literal

8:18 er, no

8:18 AWizzArd: (biginteger 13178456923875639284562345789N) also throws it.

8:19 or evaluating that number and then followed by (biginteger *1)

8:19 rhickey: right, it's that there isn't a case for bigint

8:19 AWizzArd: I tried it with the most recent clojure.jar

8:20 rhickey: AWizzArd: needs fixing, please enter a report, thanks

8:20 AWizzArd: k

8:20 rhickey: AWizzArd: you know there is bigint now too?

8:23 AWizzArd: rhickey: yes, I use both of them

8:24 Currently my BigInt serializer forwards a serialization task to java.math.BigInteger via (biginteger my-BigInt) while its deserializer deserializes a java.math.BigInteger and then (bigint it)

8:24 That's where I noticed the current issue #447.

8:31 chouser: cemerick: ack

8:31 cemerick: Morning :-)

8:31 chouser: Good morning sir

8:31 I dreamt of clojure conj

8:31 cemerick: chouser: I'm wondering about whether the "final value" of the code sent should really be privileged.

8:32 chouser: cemerick: ok

8:32 cemerick: e.g. if you send a string with 5 readable sexprs, I presume you'd want to highlight each "return value" separately from *out*

8:32 chouser: oh, not an input I had considered.

8:33 cemerick: right; the reader is not in control of the scope of code being eval'ed in this world

8:33 Or, it is, but the broader scope is client-defined.

8:33 chouser: hm, and what about writes to *out* that happen in other threads after the last expr's return value?

8:34 cemerick: Those are on different threads, and therefore aren't going to get shipped back as a response to the given request. It's a general problem I've been thinking about.

8:35 All of the other hosted repls have the same issue AFIAK -- swank, encojure, and ccw.

8:35 chouser: cemerick: I'm hopeful that whatever rhickey has cooking to improve on binding will allow handling of that kind of situation.

8:36 but until then, saying that *out*/*err* from other threads gets lost or logged elsewhere or something may be the only reasonable solution.

8:36 rhickey: what situation?

8:36 cemerick: chouser: perhaps it would help, but there would still need to be some separate policy. Response message can't keep flowing indefinitely just because someone's eval'ed some code that's tossed off a future or something.

8:36 chouser: rhickey: (magic-binding [*out* client-stream] (send-off (agent 42) prn))

8:37 cemerick: scary.

8:37 rhickey: chouser: well, it's not going to make multithreaded access to streams any better :)

8:37 cemerick: IMO, anyway.

8:37 chouser: cemerick: maybe the client doesn't have to be able to handle it, but if the code running on the server does exactly that, why not do our best to deliver it to the client?

8:38 rhickey: but it might at least make the binding visible to the agent

8:38 chouser: rhickey: that's all I mean.

8:42 cemerick: chouser: I'll keep thinking about it. There are others that want to get System/out and System/err streaming back as well.

8:43 rhickey: anyone here use FishEye? It looks like that is the best way to get Kira/Git integration

8:43 er Kira/Git

8:43 Jira/Git

8:43 cemerick: rhickey: Yeah, it works well. Somewhat more heavyweight in the UI department than I'd like, but it gets the job done.

8:44 rhickey: cemerick: have you connected it to git?

8:44 cemerick: rhickey: yup

8:45 chouser: I think I would be content with leaving that open in the spec (such as by not promising the server will mark a final response

8:46 rhickey: cemerick: great, also, is it a single user management db for Confluence/Jira/FishEye?

8:46 chouser: rhickey: we have fisheye connected to a git repo at work, but I don't know much about how it was set up.

8:46 cemerick: rhickey: it's called Crowd, I think. Never used that.

8:46 chouser: we've since moved the git repo to github:fi

8:46 cemerick: I presume there's LDAP support floating around everywhere though.

8:46 esj: chouser: i set it up recently, almost zero effort

8:46 cemerick: chouser: damn: deep pockets over there! :-P

8:48 rhickey: cemerick: wow, without crowd you have to admin users separately for Jira, FishEye and Confluence? yikes

8:48 esj: nothing like making a market for your own products.

8:48 rhickey: I could see something like Crowd for connecting externally

8:48 chouser: cemerick: yeah, github:fi is steep. Rather rougher around the edges than the price would imply, though it's gotten a lot better since we started sending in patches. :-)

8:49 cemerick: rhickey: apparently yes, though there's LDAP

8:49 We've never been large enough to care about the user admin "burden"

8:49 * cemerick isn't sure whether that deserves a :-) or a :-(

8:50 cemerick: chouser: Really. That's a surprising statement. If i shelled out that kind of cash, I'd be expecting perfection.

8:51 andyfingerhut: Expensive software can be and often is bug-ridden. But sometimes you get decent support.

8:52 * cemerick should raise our prices and cut back on QA efforts, apparently ;-)

8:52 chouser: cemerick: I know there were plans to renegotiate the price after how much bug-reporting effort we've done. Not sure how that ended up.

8:52 I also think we're using it more heavily than most of the other github:fi'ers

8:52 rhickey: no free open source license for crowd

8:53 LauJensen: I must say, Gitosis has never left me wanting when it comes to managing Git repos

8:53 rhickey: atlassian moving strongly towards Mercurial

8:53 cemerick: rhickey: I have to think they'd accommodate you if you shot an email their way

8:53 chouser: LauJensen: hosted by them or you?

8:54 LauJensen: chouser: them? I host my own repos, manage them with Gitosis

8:54 rhickey: cemerick: I simply wonder how the tools work together at all with separate user dbs

8:54 cemerick: chouser: gitosis is a tool, not a service

8:54 chouser: oh

8:54 cemerick: maybe you're thinking of gitorious

8:54 chouser: oh, indeed

8:54 cemerick: which is simply *impossible* to install locally

8:54 abrenk: rhickey: Central user management should be possible without Crowd using just LDAP, Crowd just adds single-sign on, I think.

8:56 rhickey: abrenk: makes sense

8:57 cemerick: rhickey: I'm *really* hoping that they keep their wits about them re: git vs. bitbucket. They seem smart enough to know doing anything silly will only hurt them.

8:58 rhickey: cemerick: they are adopting Mercurial internally, so I expect that will get more attention

8:59 LauJensen: cemerick: silly?

8:59 cemerick: as long as git support doesn't wither on the vine or otherwise lag significantly, I'll be happy

9:00 LauJensen: e.g. trying to funnel users of their tools into hosting via bitbucket/hg by letting support for other SCMs bit-rot, etc.

9:01 LauJensen: I wouldn't worry too much about that

9:02 cemerick: Companies do funny things when they get funded, start acquiring others, etc.

9:03 AWizzArd: What does this argument list from Java mean? 'public <T> T foo (Class<T> type)' specifically this 'Class<T> type' thing

9:04 LauJensen: Where is that project which found example-code of any clojure-fn you could think of?

9:04 clojurebot: project euler is http://ProjectEuler.net

9:05 chouser: LauJensen: http://getclojure.org:8080/examples/zipmap

9:05 LauJensen: thanks

9:08 AWizzArd: Aah, BitBucket was bought by Atlassian, cool :)

9:10 So maybe BitBucket users will soon get support for Jira, FishEye and such? Mama mia :)

9:10 rhickey: http://confluence.atlassian.com/display/DOC/Delegate+user+management+to+use+JIRA+logins

9:10 AWizzArd: It's a good day :)

9:10 rhickey: http://www.atlassian.com/summit/2010/presentations/development-speed/dvcs-systems-in-the-enterprise-git-mercurial.jsp

9:13 AWizzArd: Wow, unlimited private repos now

9:14 LauJensen: Hopefully Github will offer something similar :)

9:18 * shoover wonders what world he's in, where rhickey's in here starting conversations about tools

9:19 rhickey: shoover: we're trying to get a plan together for getting Clojure on Confluence+Jira, since we now have a host to run them on

9:20 shoover: rhickey: cool

9:20 LauJensen: Assembla is leaving something to be desired?

9:20 abrenk: rhickey: directly using the JIRA database from Confluence without LDAP is another possibility. although if you're starting from scratch I'd still recommend an LDAP server in case you want to integrate other tools in the future.

9:20 rhickey: abrenk: it seems like LDAP only does the logins, not groups etc

9:20 * cemerick has grown to strongly dislike assembla

9:21 abrenk: rhickey: There are groups in LDAP. Although not all tools support looking them up.

9:21 rhickey: abrenk: afaict Jira/Confluence use their own groups even with LDAP, but Confluence can use Jira's

9:22 shoover: the atlassian presentation is worth it for slide 10

9:22 AWizzArd: Everyone who not joins to BitBucket really misses a lot of dev comfort ;)

9:22 -to

9:22 abrenk: rhickey: at least Confluence supports LDAP groups: http://confluence.atlassian.com/display/DOC/LDAP+User+Management

9:22 bartj: silly question, distinguish the use-cases between "for" and "map"

9:23 , (for [i (range 10)] (* i i))

9:23 clojurebot: (0 1 4 9 16 25 36 49 64 81)

9:23 AWizzArd: One can losslessly convert a git repo into a hg repo (and back).

9:23 bartj: , (map #(* % %) (range 10))

9:23 clojurebot: (0 1 4 9 16 25 36 49 64 81)

9:23 bartj: same result :)

9:23 rhickey: abrenk: then it's Jira that doesn't

9:23 no_mind: atlassian is lanning to buy bit bucket

9:23 AWizzArd: no_mind: the BB website is already updated.

9:23 Atlassian logos everywhere.

9:23 no_mind: oh kool

9:23 so they already bought it

9:23 AWizzArd: It is so great, I can now have a million private repos.

9:24 LauJensen: AWizzArd: yes! One for each line of code!

9:24 AWizzArd: LauJensen: exactly what I thought!

9:24 LauJensen: AWizzArd: We can make a chat program which logs each line in a repo of its own, like twitter!

9:24 AWizzArd: twitbucket.org

9:24 abrenk: rhickey: that's a pity

9:25 bartj: ah, never mind

9:27 chouser: bartj: right, there is a fair number of cases that work approximately as well in 'for' and in 'map'

9:28 bartj: chouser, I was just thrown aback, they could be used inter-changeably sometimes

9:28 is there a *light-bulb* moment I am missing here :)

9:30 chouser: the differences start to show up when you want to do something more complex. map supports walking multiple seqs in-step, for does not. Nested loops are simple in a single for, more complex-looking with multiple maps.

9:30 andyfingerhut: bartj: for can do nested "loops", whereas that is not as trivial using map.

9:32 abrenk: rhickey: LDAP (in most scenarios) leaves the tool-specific stuff like fine-grained rights management etc. to the tools themselves. You still get central user/password/email management. Even with Crowd you still have to manage groups in JIRA itself.

9:33 rhickey: abrenk: yes, I just want to do groups once, I don't care where

9:36 abrenk: rhickey: then I guess you can only use tools from one vendor or use a cron job that syncs groups from LDAP into the tool-specific databases or using their API if there is one.

9:37 rhickey: abrenk: Confuelnce using Jira users/groups might be sufficient

9:37 abrenk: because that's the "just one vendor" scenario...

9:38 rhickey: abrenk: yes

9:38 abrenk: ...the pain then starts if you want to integrate another tool.

9:38 rhickey: abrenk: we have limited resources to apply to this

9:39 abrenk: got a recommendation for a free (for open source projects at least) ldap server?

9:40 abrenk: rhickey: I use OpenLDAP

9:41 OpenLDAP was there in the beginning and I didn't have the resources to look at the alternatives that came up in recent years.

9:41 msappler: is there a macro for letting & coercing multiple numbers ; or am I doing it the right way ... Part of my code looks like this : (let [xlight (float xlight) ylight (float ylight) x (float x) y (float y) max-range (float max-range)]

9:41 (and

9:41 (< (Math/abs (- xlight x)) (+ half-w max-range))

9:41 (< (Math/abs (- ylight y)) (+ half-h max-range))))

9:44 abrenk: it's like managing apache: just config files, no fancy web interface

9:44 LauJensen: msappler: [[xlight ylight x y] (map float [xlight ylight x y]) ?

9:45 msappler: oh thanks

9:46 why didnt i think of this simple solution? 0_o

9:46 andyfingerhut: If part of the goal is for the compiler to get type hints, I'd test to see if it notices them with that method.

9:46 chouser: it won't.

9:47 LauJensen: andyfingerhut: you just ran it through the chouser-test :)

10:03 AWizzArd: From the FAQ: "Will you continue to offer support for other version control systems?" ==> Yes! We are committed to offering support for additional version control systems such as Subversion (SVN), CVS, Perforce, ClearCase and Git.

10:03 So, maybe BitBucket will soon also support Git repos.

10:04 bartj: andyfingerhut, chouser thanks!

10:07 mrBliss: is wikipedia slow at the moment or is it just me? (I know http://downforeveryoneorjustme.com/ but it's just slow, not down)

10:09 * aav can imagine that atlassian with hold version control services under BitBucket brand. And all the rest under JIRA Studio brand. Right now it markets SVN hosting as a part of JIRA studio, and it is slightly confusing.

10:19 cemerick: mmm, git BitBucket repos. That's a fine idea.

10:20 AWizzArd: cemerick: for now there is a lossless converter

10:21 cemerick: AWizzArd: I don't do hg. :-P

10:21 klang: GitBucket .. heh

10:21 cemerick: klang: nice

10:24 klang: cemerick: too easy

10:34 cemerick: it's too bad clojure.test only reports test results. Knowing when they've started, what their runtime is, etc. would be very handy.

10:35 w/o writing one's own test runners, that is

10:36 esj: cemerick: Bamboo ?

10:36 cemerick: esj: Hudson, but that's besides the point. Bamboo has its own clojure.test test runner?

10:38 esj: cemerick: I was being a bit cheeky. But using by running the tests through maven and having the results reported in the right format Bamboo integrates clojure.test very nicely.

10:38 cemerick: esj: I figured there was cheek involved. ;-) But, what I'd like to know is per-test-var stats, not stats for the entire run across a project.

10:44 esj: I think it should be able to give you that: run-time for each test etc

10:44 * _fogus_ this discussion reminds me to dig out my Clojure-Confluence plugin framework

10:47 cemerick: esj: Not sure how that's possible without adding something on top of clojure.test. There are :begin-test-var and :end-test-var dispatches for clojure.test/report, but they're no-ops (as of 1.2.0 anyway).

10:47 Anyway, getting it done isn't a big deal -- just a shame that it's not baked in already.

10:47 Anyone know what the status of clojure.test is (perhaps vis a vis lazytest, etc)?

10:48 abrenk: cemerick: i have code lying around to write the test run time to the JUnit XML output

10:48 cemerick: wanted to contact stuart about contributing it tomorrow

10:48 esj: Hmm.... Certainly the Bamboo end of things thinks it should be able to do so. Probably it needs to be reported in the junit.xml output file, but isn't yet. Maybe ? Dunno.

10:49 cemerick: abrenk: that'd be a great addition.

10:49 abrenk: cemerick: I also wrote a wrapper around multiple test reporters

10:49 chouser: cemerick: any thoughts on how to have nREPL server support websockets without an external dep?

10:50 is it sane to consider a pure-clojure websocket server impl?

10:50 abrenk: I wanted the standard report to go to *out* in addition to the junit report to target/surefire-reports to show up in hudson

10:50 esj: abrenk: awesome !

10:51 cemerick: chouser: I *think* so, but I haven't gotten into it deeply yet. AFAICT, it's just a plain old socket after one conjures up the not-really-HTTP headers, etc. I can't imagine it'd be difficult?

10:51 chouser: ok

10:51 * cemerick will live to regret that one, for sure

10:51 abrenk: I still have an hour or two before i need to leave what would be the best way to have somebody take a look?

10:51 fork clojure at github and publish there?

10:51 chouser: I have visions of a pretty web-based nREPL client.

10:51 cemerick: indeed, I'd say many do :-)

10:52 esj: abrenk: yes.

10:52 cemerick: I've love to have someone that knows websockets (at least better than I) take a crack at an nREPL websockets adapter.

10:52 abrenk: esj: okay!

10:52 cemerick: Should be able to run on the same port, even.

10:55 sexpbot: help

10:55 sexpbot: You're going to need to tell me what you want help with.

10:56 cemerick: do we have a bot with mailboxes?

10:56 Raynes: Define 'mailbox'?

10:57 cemerick: Raynes: leaving messages for other handles for delivery upon their next arrival?

10:57 Raynes: sexpbot has a relatively crude mail plugin. You send somebody a message with $mail nickname message, and they get a notice later on when they're active, and they can retrieve their messages by typing $mail. All of this works in PMs to the bot, of course, as to not interrupt activity.

10:58 $mail Raynes Message

10:58 sexpbot: Message saved.

10:58 Raynes: $mail

10:58 Like that.

10:58 cemerick: ok, thanks, I'll give it a whirl

10:59 phenom_: cemerick, i've got a websockets implementation in erlang

10:59 rhickey: hrm, what if condp didn't capture the pred expr in a let? e.g. currently:

10:59 (macroexpand '(condp = x 42 43))

10:59 (let* [pred__79 = expr__80 x] (if (pred__79 42 expr__80) 43 (throw ...)))

10:59 but could be:

10:59 (let* [expr__80 x] (if (= 42 expr__80) 43 (throw ...)))

10:59 cemerick: phenom_: nifty, though I wouldn't really know what to do with it :-)

11:00 was it difficult to impl?

11:00 phenom_: cemerick: :P, it wasn't difficult at all, though it doesn't have security enabled yet ... i haven't touched in a few months and though you wanted an example to look at :P

11:00 *thought

11:00 cemerick: phenom_: thanks, good to know. Link?

11:01 Raynes: esj: Yes, it does. ;)

11:01 esj: *gasp*

11:01 cemerick: I'm hoping to bait someone else into doing the websockets support for nREPL.

11:01 rhickey: cemerick: trying to avoid netty?

11:01 phenom_: cemerick: github.com/djunforgetable

11:01 neotyk: cemerick: have you seen sample of aleph websockets?

11:01 phenom_: check thor_websockets.erl

11:01 cemerick: rhickey: yes, nREPL should have no dependencies other than clojure

11:01 neotyk: hrm, nope

11:02 I didn't really know what websockets were until rhickey mentioned them last week :-P

11:02 djpowell: Hmm. Anyone encountered "gc overhead limit exceeded" in clojure apps?

11:02 neotyk: cemerick: good luck implementing your own http server with websocket support

11:02 * cemerick is apparently the anti-web curmudgeon these days

11:02 cemerick: neotyk: I don't need an HTTP server, AFAICT?

11:02 phenom_: if i was a pro with clojure, id certainly help but im a beginner :P

11:03 djpowell: It is a server app on a virtual server that does lots of churn, but shouldn't be using much memory overall

11:03 neotyk: cemerick: well, websocket uses http extension mechanics

11:04 AWizzArd: cemerick: Netty is not specifically a http server. It only happens to support that protocol.

11:04 Can be used to implement an echo server, a time server, etc.

11:04 abrenk: esj: the code is currently on the 1.2.x branch but it applies cleanly to master. on which branch should I commit?

11:04 cemerick: neotyk: ok, but that's just a matter of reading and writing HTTP-esque headers, no? i.e. only the initial handshake looks like HTTP.

11:04 djpowell: Wonder if I'm getting some weird gc behaviour on that environment

11:05 * djpowell has disdain for html5

11:05 neotyk: cemerick: yes, client asks to upgrade protocol to websocket

11:05 esj: abrenk: i'd go with 1.2, but that could be just me.

11:06 abrenk: djpowell: the error means that gc is leaving no time to the app itself. heap is completely used up by non-gc-able objects.

11:06 AWizzArd: cemerick: Jetty also supports this Ajo thing instead of HTTP

11:06 cemerick: neotyk: which is just delimited UTF-8 "frames"? Certainly doesn't seem to involve an HTTP server.

11:06 AWizzArd: AJP13

11:07 cemerick: In any case, I'm trying to not get sucked into websockets yet

11:07 AWizzArd: Sure; don't want the 12MB dependency or whatever is though

11:07 djpowell: Yeah. It usually means you are just scraping asking the memory limit, but when I run the app it never uses more than about 20meg, whilst probably creating gigabytes of gc churn

11:07 AWizzArd: cemerick: exactly, that is true

11:07 neotyk: cemerick: if you would still like to leverage support offered by other libs: check http://github.com/maacl/aleph-ws-test

11:12 rhickey: cemerick: so you'd write something directly on TCP?

11:13 netty jar 768k

11:13 AWizzArd: That could be acceptable.

11:14 djpowell: Does doing repl stuff over a http persistent connection suck?

11:14 neotyk: netty is very clean in it's deps

11:14 rhickey: cemerick: abstracting away the transport is very valuable but non-trivial

11:14 cemerick: rhickey: if it's going to be in nREPL proper, then yes. It needs to stay as lightweight as possible, as one use case is embedding within deployed apps, etc.

11:15 If websockets aren't doable without external deps, then it should be no problem to have a separate nrepl-websockets artifact, etc.

11:16 rhickey: cemerick: it's not the websockets, its the burning in of TCP that will hurt long-term. Using something like netty will be much more flexible.

11:17 chouser: rhickey: you're expecting TCP to go away?

11:17 rhickey: chouser: no tunneling, no SSL, no in vm without much wheel reinventing, free from netty

11:18 cemerick: rhickey: the protocol is entirely text-based. Should work over any transport AFAIK.

11:18 rhickey: cemerick: it's not the bodies, it's the coordination

11:19 ohpauleez: just for the record, I have a version of repl-server (mostly) running on netty/aleph

11:19 I did it to learn aleph, pretty sweet

11:20 cemerick: rhickey: I'll need some education, then.

11:20 rhickey: cemerick: you could write it to netty then swap in your dependency-less tcp stack, letting others use netty

11:21 cemerick: rhickey: if I had hair, that would've brushed the top of it

11:21 rhickey: ?

11:22 cemerick: I've never even looked at netty's project page or whatever.

11:22 rhickey: http://www.jboss.org/netty

11:22 cemerick: heh

11:22 AWizzArd: I think it would be really useful for that use-case.

11:22 ohpauleez: cemerick: You can also use netty, which is 80% just wrapped netty

11:22 AWizzArd: hmm

11:22 ohpauleez: gah, aleph

11:23 KirinDave: netty is pretty neat.

11:23 rhickey: what I am advocating is - get away from custom transport and protocol. Use netty + websockets. Concentrate on value add (clojure repl stuff) get on with our lives

11:23 neotyk: cemerick: look at this impl: http://github.com/maacl/aleph-ws-test/blob/master/src/aleph_ws_test/core.clj

11:23 cemerick: rhickey: so one has to learn websockets and have appropriate libraries to write a REPL client?

11:24 neotyk: and it already solves problem of old browsers that doesn't have WS support

11:24 rhickey: cemerick: learn websockets or learn your custom protocol?

11:24 KirinDave: neotyk: That's pretty clever.

11:24 abrenk: cemerick, esj: http://github.com/abrenk/clojure/tree/abrenk-clojure.test

11:24 rhickey: cemerick: because the existing repl can work over sockets

11:24 abrenk: any idea when stuart sierra will be around?

11:25 chouser: websockets isn't a sufficient protocol for the feature set nREPL is targetting. needs something on top

11:25 cemerick: rhickey: not with tools, and not asynchronously

11:25 rhickey: cemerick: right, I'm not saying it's adequate, just that there will be a protocol

11:25 yours or some standard, e.g. stomp

11:26 chouser: json

11:26 rhickey: or wesockets

11:26 KirinDave: No one in this community likes BERT, huh? :)

11:26 rhickey: json is just a (bad) data format

11:27 not a communication protocol

11:27 chouser: json over websockets

11:27 KirinDave: json-rpc is the protocol, and almost no one ive met actually likes json-rpc 1.1

11:27 Most people change it subtly to take some of the insanity out.

11:27 chouser: as opposed to clojure-string-pairs-over-websockets

11:28 rhickey: repl is somewhat more messaging-ish than rpc ish

11:28 KirinDave: rhickey: Both bert and json-rpc make allowances for that.

11:28 cemerick: rhickey: nREPL's protocol is hardly deserving of a name. Roughly json, minus the braces. Even if I didn't write it, I'd prefer to "learn" it than learn websockets and the attendant libs.

11:29 s/a name/the name

11:29 or term, whatever

11:30 neotyk: cemerick: do you think your users will share same opinion ?

11:30 cmiles74: Would something like XMPP be better fit?

11:30 chouser: KirinDave: after a quick glance at json-rpc I don't see that it helps nREPL over a custom json protocol

11:30 KirinDave: cemerick: fwiw, I think your protocol is straight forawrd.

11:30 chouser: I am not advocating it at all.

11:30 cemerick: neotyk: insofar as my users are clojure toolmakers, yes

11:30 chouser: cmiles74: I'm have a newfound dislike of XMPP

11:31 KirinDave: chouser: I was just clearing up a gap in the conversation.

11:31 chouser: turns out XMPP has weaknesses as a transport protocol.

11:31 KirinDave: chouser: JSON being "bad" though, I'd take big exception to. :)

11:31 chouser: er

11:31 turns out XML has weaknesses as a transport protocol.

11:31 KirinDave: I have not generally thought of json as bad either, but I'm loathe to contradict rhickey on something like that.

11:32 KirinDave: Lol.

11:32 I'll take a shot.

11:32 cemerick: I guess I'm asking for a reason for why I should rope in any of these other networking toolkits/stacks. If it's just because it'll make a websockets endpoint easier to implement, that's not good enough.

11:33 KirinDave: rhickey: JSON is one of the few data formats that has a good compromise for everyone on data storage, and plays very nice with traditionally under-tooled web developers.

11:33 * KirinDave wipes the sweat from his brow.

11:33 KirinDave: I'm in for it now. Probably not, actually. :)

11:33 chouser: cemerick: I was imagining optionally swapping a websocket layer between the message protocol and the raw socket.

11:33 cemerick: KirinDave: nah, I don't think json has much to apologize for.

11:33 KirinDave: So no one's mentioned Avro in this conversation

11:33 http://avro.apache.org/docs/current/

11:33 chouser: cemerick: while secretly hoping we'd end up with something a little less ... odd ... for the message encoding layer. :-)

11:34 cmiles74: You can use Netty to build a TCP-based client/server, it might save you some time.

11:34 KirinDave: We're considering using it.

11:34 cemerick: chouser: indeed -- that's what I meant by "they could run on the same port". Sniff for HTTP header, switch as necessary.

11:34 KirinDave: For those of us writing APIs, Avro seems like a good call for internal stuff.

11:34 cemerick: cmiles74: Not sure about that -- that was the easy part :-) I don't want to have the extra dependency for the base case, though.

11:35 rhickey: I've to run, here's my 2 cents:

11:35 cmiles74: cemerick: gotcha.

11:35 KirinDave: cemerick: Oh by the way, I'm curious what you'll say about the first project I am working on for BankSimple. Have I told you about it yet?

11:35 cemerick: KirinDave: you've not :-)

11:35 rhickey: please use a transport abstracting API like netty. I think it is quite likely we will need this more than once and accept the dep

11:35 please use a standard protocol like websockets or stomp

11:36 please do not use json, it is inadequate, and you can always downgrade to json

11:36 but representing richer things in json means more work in reconstructing them than a simple js read for clojure data

11:36 reader

11:37 since that reader doesn't need to do many things like backquote

11:37 ohpauleez: is there a short hand for busting a vectors into subvectors of n-length

11:37 ?

11:37 KirinDave: cemerick: It's a port of webmachine to clojure.

11:37 rhickey: back later...

11:37 KirinDave: cemerick: For the prototype, on top of ring. I haven't decided if I'd ditch ring in the future.

11:37 cemerick: rhickey: it's not *actually* json, but OK. I'll have to educated as to the use-cases though. That's a big pile of added complexity for what-I-don't-know.

11:38 KirinDave: Ugh, the java stomp library is hosted in mercurial. Deeply disappointed.

11:38 cemerick: KirinDave: Nice :-D

11:38 KirinDave: You've seen http://github.com/ordnungswidrig/compojure-rest ?

11:38 KirinDave: Yes.

11:38 I think Webmachine is a better model.

11:39 cemerick: that's the best prior art I've seen in that vicinity

11:40 KirinDave: yeah, and it was the inspiration for my plan, actually

11:41 cemerick: I was looking for some advice tho

11:42 So I've got this implemented as a protocol with a default hash: http://bitbucket.org/justin/webmachine/wiki/WebmachineResources

11:42 And I'll start building functions and macros to make construction of such a responder trivial.

11:43 (and probably one to invert the hash-based (extend...) syntax to a (defresource ...) for maximum performance later.

11:43 edw: Is there a preferred #clojure pastebin?

11:43 KirinDave: Today I'm starting on http://bitbucket.org/justin/webmachine/wiki/BigHTTPGraph

11:43 edw: Gist.github.com is great

11:43 chouser: cemerick: could use websocket-style framing so you don't need the leading "entry count" on nREPL messages.

11:43 edw: Thanks.

11:43 KirinDave: And so my question is, should I represent the graph functionally or should I make the states as objects in a graph that are traversed?

11:44 The functional approach is, in my mind, much more straightforward.

11:44 chouser: KirinDave: both? a graph of functions?

11:44 KirinDave: But, the introspectability (if there is such a word) of the object graph that is consumed

11:44 chouser: Well of course things like tests would use graphs.

11:44 clojurebot: Who??

11:44 KirinDave: err, would use funs

11:45 cemerick: KirinDave: functional is a hard default to override, even here

11:45 chouser: the thing about functions for something like this is that they're opaque

11:46 chouser: they can now carry metadata

11:46 cemerick: (hrm, maybe that's what KirinDave was responding to re: introspectability)

11:46 KirinDave: But for example, a simple node like the "known_method" check? That could be just a function or it could be a record with {:test (fn...) :success-transition :b11 :failure-transition {:status 501 :message "Not Implemented"}

11:46 cemerick: Indeed.

11:46 cemerick: true, but if you need the same bits in the metadata as in the fn body, that's not so hot

11:47 KirinDave: Both seem very clojure-y and very lisp-y.

11:47 Both are amenable to helpful macros.

11:47 edw: This call to Incanter's `dataset` procedure seems a bit...fugly. Am I missing some obvious idiom here? http://gist.github.com/602986

11:47 cemerick: KirinDave: I think it's a winner

11:47 KirinDave: cemerick: Which?

11:48 cemerick: KirinDave: functional graph approach. fn's are either opaque, or require repetition of the representation.

11:48 KirinDave: chouser: So your gut reaction is a bit of syntax that fills out metadata on a function and populates it?

11:48 Yeah

11:49 cemerick: The repetition may not be so bad so long as it's a macro doing the work, but I imagine that macro would be slightly hairy.

11:49 chouser: KirinDave: no, my gut reaction is "ick"

11:49 KirinDave: chouser: At the whole project concept?

11:50 cemerick: KirinDave: I'd much prefer a fn that produced a fn from the node representation, then attached the repr as metadata

11:50 cgrand: you can avoid the repetition by making the record implements IFn... not sure it's a goog idea though...

11:50 chouser: trying to overcome that, what about writing sexprs that contain all the needed info from the graph in the most natural way

11:50 KirinDave: cgrand: Ha.

11:50 chouser: I agree that syntactically this decision should be concealed at the earliest opportunity. You don't need to sell me on that. :D

11:50 chouser: then either walk the s-exprs or define macros to turn that into code

11:51 cemerick: I've been avoiding macros more and more of late. *shrug8

11:51 chouser: the specific code it gets turned into could then be changed later if you don't like what you chose first.

11:52 KirinDave: I'm just wondering if there'd be benefit either way that I can't think of.

11:52 I suppose debugging and testing.

11:52 chouser: I'm liking this more and more. ignore the implementation and capture that graphs complexity as simply and succinctly as possible

11:53 KirinDave: I 100% agree. I'm just trying to think about what the pros and cons are for the various outputs of the macro.

11:53 Implementing a graph like this is a slam dunk for lisp, which is one of the reasons I was not afraid of it.

11:53 chouser: don't worry abuot it

11:53 you can do both

11:54 KirinDave: cgrand: Actually that suggestion raises a lingering question I've had.

11:54 amalloy: barging in late here; this discussion sounds interesting but i'm not sure what it's about. anyone mind filling me in?

11:54 KirinDave: amalloy: I'm implementing WebMachine in clojure.

11:54 chouser: once you've got the graph (including s-exprs that define the code to do state tests or whatever), write code to traslate it into whatever makes sense first

11:55 that probably would be something very compact and fuctional

11:55 KirinDave: amalloy: The discussion is on implementing http://bitbucket.org/justin/webmachine/wiki/BigHTTPGraph

11:55 chouser: if you need introspection later, you'll know exactly what kind you need and can decide to add metadata to the fns or build a separate data structure, or whatever makes sense then.

11:55 KirinDave: Ah.

11:56 cgrand: cemerick: can I comment on the OSGI doc?

11:56 cemerick: cgrand: sure, msg me your gdocs email?

11:58 cgrand: KirinDave: which lingering question? Why records do not implement IFn?

11:58 KirinDave: cgrand: No.

11:59 I was curious what ever happened to repl-utils that made show such a hassle to get into your namespace

11:59 Err, not yours

11:59 the proverbial your. :)

12:01 amalloy: KirinDave: i think the issue is that (source) got promoted an auto-included ns, and *also* left in c.contrib, so they conflict before it gets to show

12:05 KirinDave: yeah

12:06 ohpauleez: Show should just promoted

12:06 I use it a lot

12:06 abrenk: esj: an example how to use multiple test reporters with my code is at http://gist.github.com/603009

12:10 DeusExPikachu: anyone here use incanter?

12:14 amalloy: ohpauleez: seconded

12:15 i would use it a lot, if i could remember how to :require it

12:16 jlr: ,(let [crazy-hashmap {() [], #() {}}] (get crazy-hashmap ()))

12:16 clojurebot: []

12:17 chouser: ohpauleez, amalloy: I concur, but have communication (that I only just now realized was private) from Important People suggesting it's not likely to happen.

12:18 ohpauleez: to be replaced by anything similar?

12:18 or just deprecated?

12:18 or you can't say

12:23 chouser: I doubt show in contrib would be deprecated (though I've been wrong about such things before), but unlikely to be included in clojure.repl

12:32 hm, dir is there -- I wonder if a patch that makes it work with classes would be acceptable?

12:35 AWizzArd: rhickey: will (keys my-record) *always* first return the fields of the slots and only *then* the __extmap

13:01 ohpauleez: chouser: I'd ideally like dir to work like show when done on classes

13:02 I also like the separation, ns vs class

13:03 anonymouse89: is there a way to do something in a namespace from another? for example def a var for configuration purposes?

13:04 ohpauleez: anonymouse89: take a look at in-ns, it might be what you're looking for

13:05 anonymouse89: also take a look at clojure.contrib.ns-utils

13:05 anonymouse89: ohpauleez: so I could temporarily change my namespace using in-ns def something and then switch back?

13:06 ohpauleez: ah, immigrate from clojure.contrib.ns-utils may be what I'm looking for, thanks

13:07 ohpauleez: cool, happy to help anonymouse89

13:11 cemerick: chouser: FYI, nREPL's :value is no longer included in :out

13:20 dakrone: chouser, question about your book, Manning says the ebook is only available 5 days after the date or purchase, so does that mean I wouldn't get the final version of the book, only the most recent in 5 days?

13:30 jlr: dakrone: As long as you save your order number, re-entering email + order number allows you to access it at any time

13:31 I think they kill the direct link after 5 days just to prevent an url from circulating out there online. They must generate a new one when you reenter your info. I have dled it a couple times long after the 5 days

13:32 You get the final version with it of course lol

13:32 They email you each time it's been updated.

13:34 dakrone: jlr, gotcha, thanks

13:34 also, _fogus_ & chouser, do you accept bug reports? If so, where to send them?

13:34 chouser: dakrone: the manning forum is best

13:35 dakrone: cool, thanks

13:35 chouser: dakrone: not sure how much longer we can still get changes in before they starting pulping trees

13:36 ztellman: cemerick: if you'd like any help using aleph to provide websocket support, just let me know

13:36 cemerick: ztellman: Thanks. The protocol / transport stuff is somewhat up in the air now, unfortunately. I'm sure I'll holler when we get to that point :-)

13:37 ztellman: for what it's worth, aleph treats websockets like pretty much like any socket protocol

13:38 you could do your base TCP communication using aleph, and that would transfer pretty seamlessly over to websockets

13:38 cemerick: Yeah, that's my general impression of websockets in general

13:39 I think there's some requirements mismatch or simple miscommunication at the root of the current uncertainty.

13:39 chouser: http://jmesnil.net/stomp-websocket/doc/

13:39 ztellman: how so?

13:40 sproust: chouser: do you know when the paper print is going into production?

13:40 (I bought MEAP, but I prefer to read pulp, I've stopped myself from reading the PDF so far...)

13:40 chouser: sproust: just got email today "The book has a December release date which means that we need to go to press in about 8 weeks."

13:41 sproust: Thx.

13:41 Raynes: I only bought the PDF version. I don't have any programming-related dead-tree books.

13:42 ztellman: cemerick: I've got to run, actually. We can talk more at the conj, if you have time. If you have any questions in the mean time, check out the aleph mailing list.

13:42 cemerick: ztellman: there's this (http://bit.ly/nreplnotes), but rhickey has some different ideas that I don't grok yet, either in specifics or motivation

13:44 sproust: cemerick: reading your doc; surprised, I thought over environments also used swank.

13:46 cemerick: nope; there's no clojure client, and the protocol isn't super-friendly (or particularly well-documented)

13:46 chouser: cemerick: I'm liking stomp for this

13:47 cemerick: custom headers seem widely supported and would suffice for id, timeout, ns, and status

13:47 cemerick: add a bodytype to indicate if the payload is code (in a request) or out/err/value (in a reply)

13:48 this buys you well-defined transport and quoting rules, along with code that implements them including over raw or web-socket

13:49 and would be nearly as simple as what you've already got for a custom pure-clojure impl that might not supported more advanced features (like encryption, proxies, etc.)

13:50 cemerick: How did I get to the position of being the old fart for whom TCP and ssh tunnels were sufficient?

13:50 Clearly, retirement is nigh.

13:52 chouser: cemerick: I am rather amused that you're the one pulling for a dep-less new implementation of something. :-)

13:52 cemerick: ha

13:53 I go where the requirements lead me. *shrug*

13:53 rickmode: silly question: I'm using pprint to print out a nested structure of defrecords, however it doesn't print the type name. Is there a nice way to do this? Perhaps add my own metadata?

13:53 chouser: and equally that I'm the one pasting this link: http://jmesnil.net/weblog/2010/01/14/using-stomp-with-hornetq/

13:53 cemerick: chouser: yeah, we've got a bizarro-world role reversal going on

13:55 It doesn't seem like a pure-clojure, no deps implementation of stomp is worth bothering with.

13:56 Chousuke: Factory factories. yay :P

13:56 chouser: It wouldn't be a general-purpose stomp server, just one that can handle nREPL messages.

13:58 if read-stomp-message were more than twice the size of nrepl's current read-message, we did something wrong.

14:02 cemerick: I really don't care what the protocol is, as long as it can be easily implemented. I'll certainly investigate stomp more though.

14:02 kotarak: nrepl?

14:02 chouser: kotarak: http://github.com/cemerick/nREPL

14:03 kotarak: chouser: I know :) Already clone locally. I mean this stomp thing. I just read "cemerick" and "protocol".

14:03 cemerick: kotarak: There are some protocol rumblings. Not sure what to make of it all, yet.

14:04 kotarak: other feedback?

14:04 cemerick: yeah

14:04 chouser: of the rhickey kind

14:04 kotarak: ui

14:04 cemerick: kotarak: http://clojure-log.n01se.net/#11:35

14:05 * kotarak reads

14:05 cemerick: I've been hermeneutic-ing all day now

14:05 :-D

14:05 LauJensen: Nice, Rich hates JSON as well :)

14:07 cemerick: odd that we've gotten to a place where json is disliked by so many?

14:08 LauJensen: cemerick: I understand why you consider Rich and I to be an army, but we're really just two people

14:09 cemerick: LauJensen: you guys are hardly the first I've heard :-

14:09 :-)

14:09 LauJensen: oh... :]

14:10 kotarak: cemerick: for stomp I'll need an external non-Java program to handle the protocol. bleh.

14:10 cemerick: yeah, I know :-)

14:11 kotarak: Don't worry. I'm not sold on the complexification, at least not yet.

14:12 If I am, then we'll be sure to have another path in that won't bind you in knots.

14:12 rhickey: cemerick: what complexification?

14:12 cemerick: tongue-in-cheek, there (at least partially)

14:12 LauJensen: rhickey: Shouldn't you be half-way in Aarhus by now?

14:13 cemerick: rhickey: standard protocols, netty et al., etc etc.

14:13 rhickey: have you read http://bit.ly/nreplnotes ?

14:14 rhickey: if you weren't going to have any deps, you'd deliver a clojure lib that wrapped your protocol. If your use stomp/websockets, you can have a clojure lib that wraps that and looks identical, but if someone wants to play from, e.g. a browser, they have the stomp/websocket api, rather than a spec for your protocol

14:14 kotarak: cemerick: I please don't feel to bound. My requirements are quite tough.

14:14 s/I/Oh/

14:14 sexpbot: <kotarak> cemerOhck: Oh please don't feel to bound. My requOhrements are quOhte tough.

14:15 LauJensen: hehe

14:15 rhickey: cemerick: skimmed those. they call for a message based procol and I'm saying why invent a new one?

14:16 cemerick: rhickey: how is that different than what I said earlier, e.g. base an nrepl-websockets or nrepl-netty, etc lib on top of the base

14:16 chouser: kotarak: surely you'll need an external program anyway -- you're not going to talk to a socket straight from vim, were you?

14:16 rhickey: cemerick: because it leaves the base doing all the work instead of little of it

14:16 cemerick: rhickey: because I want to avoid external deps and non-clojure/java clients shouldn't have to jump through the protocol library raffle to get something working IMO

14:17 scottj: Wanting to add parameter names to Java static methods in slime. Anyone know 1) if reflection on normal compiled classes includes actual name (looks to me like it just includes type) 2) whether java IDE's can tell you it 3) how they do it?

14:17 rhickey: cemerick: you are making them definitely lose the raffle by supplying a protocol for which they definitely can;t get a free impl

14:18 cemerick: ...but for which they can write one in ~10 min?

14:18 rhickey: new protocols == bad

14:18 kotarak: chouser: right, but read something like netcat vs. something understanding stomp

14:18 rhickey: existing protocols = free clients, free servers, free specs, choince of impls, choice of langs ...

14:19 cemerick: rhickey: let's ignore the protocol question for now. What about external dependencies?

14:19 (funny enough, I was aiming for an HTTP impl before various people impressed upon me the importance of the dependency issue)

14:20 rhickey: cemerick: you are only looking at the positives - look no deps! vs the tradeoffs - look we re-implemented 16 wheels!

14:20 http is unsuitably disconnected

14:21 we don't want rpc, we want async messages

14:21 cemerick: another reason why I dropped it :-)

14:21 rhickey: I'm very aware of the tradeoffs, but there are practical considerations for a library that one would like to be generally usable. Deployment footprint and dependency version conflicts are a real consideration.

14:21 chouser: kotarak: there's a stmp client in perl -- could just use that in vim. :-)

14:21 rhickey: cemerick: agreed

14:22 cemerick: and yet, we're on the jvm for a reason, as you often say

14:23 kotarak: chouser: the "foreign" interfaces in vim suck terribly. + Windows user have then "download this 10k zip and this 30MB perl/python/ruby/lua thingy...."

14:23 rhickey: cemerick: I am telling you that, should Clojure e.g. ever take on queues, it is likely to pull in netty as a dep, and possible hornetq

14:23 cemerick: rhickey: but faced with wanting to interop in this case with a host of hosts, as it were. Other langs, emacs/SLIME potentially, etc.

14:23 chouser: I think nrepl would only need stomp's SEND message, nothing else

14:23 cemerick: rhickey: :-O

14:23 rhickey: cemerick: you completely lose me on why your personal protocol is better for people than a standard one

14:24 chouser: this would allow for re-implementation approximately as simple as implementing cemerick's proposed protocol but also allow use of existing libs

14:24 kotarak: chouser: + connect and (if politeness is of interest) disconnect.

14:24 cemerick: rhickey: it's not better, just simpler, and guaranteed to be implementable regardless of client platform/lang

14:24 chouser: kotarak: sorry, yes

14:25 rhickey: cemerick: websockets and stomp are sufficiently simple and have bountiful implementations

14:25 kotarak: There seems to be a simple C client, though. Then I just have to someone with a C compiler which is not Cygwin on Windows

14:25 cemerick: chouser: noted, I'm arguing with rhickey at the moment, tho :-D

14:25 rhickey: I think kotarak and technomancy might disagree with that.

14:26 (e.g. vimclojure & SLIME et al.)

14:26 rhickey: cemerick: well, they are no worse of then with a custom protocol, for which no one gets a free impl

14:26 than

14:27 cemerick: again, I think implementation simplicity is a factor

14:27 chouser: unles the custom protocol is enough simpler than any available standard protocol

14:27 rhickey: cemerick: I'd flip it around, your description of a protocol sounds like, e.g. stomp, but because you don't want deps you don't want to be bothered with writing stomp server. But if stomp came with Java, would you not choose it?

14:27 chouser: which is why I keep talking about a subset of something like stomp.

14:28 cemerick: rhickey: not if that means that other langs and environments are less likely to be able to interop

14:28 rhickey: cemerick: than with what? stomp is everywhere

14:28 custom comm protocols stink

14:29 however simple

14:29 hanging your message handler off a stock stomp/websocket client rules

14:29 cemerick: I'm certain that it does.

14:30 rhickey: if you don't have one, well, they are not much more complex than the custom one, if at all, with plenty of example implementations

14:31 cemerick: What has the world come to, where I'm here, and rhickey is suggesting putting hornetq in clojure core?! ;-)

14:31 rhickey: I find it really difficult to buy 'a custom protocol is prefereable to a standard one', and think we need to be honest this is about deps and server implementation difficulty

14:32 cemerick: rhickey: That's always been the primary motivation for me. But, talk to someone who might need to get stomp working in elisp, and you might get a different answer.

14:32 rhickey: cemerick: I'm certainly not going to re-implement message queues in order to avoid a dep

14:33 cemerick: but elisp people already have slime etc, and may be the only people who won't have stomp et al

14:33 cemerick: rhickey: don't worry, I've saved you the hassle :-P

14:34 rhickey: though I have a great deal of faith in the inevitability of eclipse in the clojure world, saying that w.r.t. nREPL is a bit off the point today

14:34 lpetit: Hello all

14:34 rhickey: cemerick: I have to imagine stomp is simpler than swank/slime

14:35 swank/slime btw being poster children of custom protocols

14:35 cemerick: rhickey: swank is *absolutely* more complicated, but that doesn't mean that I want to ask whoever's interested in working on SLIME/nREPL interop to write a stomp client.

14:36 dnolen: cemerick: rhickey: http://code.google.com/p/wave-client-for-emacs/source/browse/lisp/wave-client-websocket.el?r=b9619eaac2687be674fd4c680d276960735dac63

14:36 websocket for elisp

14:36 chouser: rhickey: do you have any comment regarding using a subset of stomp, or is that not acceptable?

14:36 rhickey: dnolen: yes, websocket even simpler

14:36 * cemerick is entirely uninterested in fighting protocol architecture wars -- only interested in maximum uniform uptake of a common repl across clojure environments/apps

14:36 chouser: websocket isn't sufficient though

14:36 cemerick: what chouser said

14:37 rhickey: cemerick: than pick a standard protocol, it directly impacts that goal

14:37 lpetit: rhickey: I give up with my dirty hacks concerning OSGi, I acknowledge that aav's approach is more interesting in the long term, and I now will join him and we hopefully will find a common solution to this important problem.

14:37 rhickey: then

14:37 cemerick: rhickey: for whom, and how? There's those that will be using the nREPL client, and those that aren't in java/clojure -- and may not have a stomp client available.

14:38 rhickey: chouser: I don't know exactly what you were saying, why would that be a question, i.e. wouldn't we aren't offering a full message queue? not clear to me

14:39 chouser: rhickey: to fully implement stomp appears to me to be drastically more complex then cemerick's protocol.

14:39 rhickey: cemerick: we are going in circles here - it is possible for people to find impls of e.g. stomp, and impossible to find impls of your-protocol

14:40 dnolen: chouser: how so? what feature is missing?

14:41 ztellman: chouser: syntactically, STOMP seems pretty simple; are you talking about the semantics?

14:41 cemerick: rhickey: unless someone is using stomp already, I guarantee that implementing the protocol that's there will take less time than finding and using an existing library. And regardless, there is the dependency issue.

14:42 rhickey: chouser: but the vast majority of people can just grab an impl of stomp for their lang off the internets

14:43 so, we're basically afraind that elisp users, who have embraced the complexity of swank, will balk at stomp?

14:43 http://www.hccp.org/erlang/stomp.erl

14:43 cemerick: rhickey: That was just an example, of course. :-/

14:44 chouser: dnolen: what feature is missing from what?

14:44 dnolen: swank is epitome of what's wrong a custom protocol no? :)

14:44 chouser: from websockets

14:44 chouser: ztellman: yes, I'm talking about subscribe/unsubscribe/commit/ack, etc. things we don't need

14:44 rhickey: stomp clinets for c.c++,c#, delphi,erlang,flash,haxe,java, objective c, perl, php, pike, python, ruby, smalltalk

14:45 cemerick: dnolen: nREPL is message-based, not just synchronous streams

14:45 rhickey: plus stomp can transparently ride on all message queues

14:45 cmiles74: I was just reading that webpage!

14:45 http://stomp.codehaus.org/Clients

14:46 ztellman: chouser: ok, so you only use SEND, and have the canonical client and server ignore everything else

14:46 will that break existing implementations?

14:46 chouser: ztellman: that's essentially what I've been suggesting -- was hoping someone who knew stomp better to confirm that that's workable

14:46 though that language list may make it moot

14:47 rhickey: chouser: how do you receive?

14:47 ztellman: chouser: I can't be that person, unfortunately, but I don't see what could break if subscribe/unsubscribe/etc. were noops

14:48 s450r1: ure

14:49 drewr: I can't imagine any swank user would care about using a different protocol, as long as it works; and if it's improved, then even better

14:49 rhickey: stomp may be more than we need, but the point remains, try to find a widley-implemented standard protocol that fits ok

14:51 scottj: drewr: I think the concern is for the implementer.

14:51 ztellman: according to http://stomp.codehaus.org/Protocol, it seems like we could get away with the client SENDING everything to the server, and the server replying only with MESSAGE and ERROR frames

14:52 that would probably break existing clients, though

14:52 rhickey: cemerick: and there's no saying, e.g. that you couldn't do a no deps impl of stomp on the server side

14:52 scottj: though porting slime to nrepl sounds like so much work if someone's not deterred I don't think implementing stomp would do it

14:52 cemerick: scottj: I'm hopeful. Not being able to use the tools you want with REPLs running in deployed apps is frustrating.

14:53 cmiles74: If the client uses SUBSCRIBE, there could be support for multiple sessions to the same running process.

14:53 dnolen: scottj: clojure uses such a tiny portion of slime tho from what I can tell.

14:53 compared to the CL experience, Clojure SLIME is fairly anemic

14:53 cemerick: rhickey: that seems ludicrous to me

14:54 cmiles74: COMMIT and ABORT look like the only two that really don't fit with my idea of what the REPL does.

14:54 scottj: dnolen: repl inspector debugger autodoc etc

14:54 rhickey: cemerick: I bet you could implement stomp in a couple of pages of clojure, tops

14:54 cmiles74: Er, and BEGIN.

14:54 chouser: cmiles74: yeah, I don't think we'd need transactions

14:55 dnolen: scottj: debugger doesn't work and swank-clojure has custom implementations of most of those. just the commands are bound to familiar things.

14:55 cemerick: rhickey: to save client implementors from figuring out how to write > 2\n"id"\n"blah"\n"code"\n"(println 5)"

14:56 and rather, have them go find a stomp client lib?

14:56 scottj: dnolen: stacktraces and breakpoints and continues work. well yeah swank-clojure has to define the foundation for all those things.

14:56 rhickey: cemerick: it's not the sending, it's the receiving, sockets, error handling etc

14:56 if you have a stomp client, you basically connect and set up a handler function

14:57 dnolen: scottj: breakpoints? that's never worked in SLIME w/ Clojure. stacktrace sure, but that's trivial.

14:57 LauJensen: dnolen: ? break-points work fine

14:57 scottj: dnolen: there's probably stuff inslime w/ clojure you're unaware of :)

14:58 rhickey: one of us could have written a stomp server in the time we've spent arguing about them :)

14:58 dnolen: LauJensen: setting breakpoints in Clojure with SLIME?

14:58 * dnolen did not know that if true

14:58 LauJensen: dnolen: You set the breakpoints with swank.core/break

14:59 dnolen: LauJensen: oh yeah, that doesn't work very well

14:59 LauJensen: dnolen: works fine for non-multithreaded stuff

14:59 rhickey: in fact, looking at the protocol I think merely choosing it delivers most of the desired benefits and won't require a dep

14:59 dnolen: LauJensen: or lazy stuff if I recall?

15:00 scottj: with a few lines of code works fine with multithreaded too.

15:00 rhickey: chouser: it seems to me that avoiding some of the protocol saves little, it's so simple

15:00 LauJensen: dnolen: possibly

15:00 dnolen: LauJensen: so I rest my case, not useful :D

15:00 LauJensen: hater

15:00 scottj: I have an emacs key that inserts and removes breakpoints that work with multithreaded and I use it all the time.

15:01 LauJensen: scottj: demo or it didnt happen

15:03 rhickey: chouser: we can ignore things semantically not meaningful to us as long as we do the protocol dance correctly

15:03 chouser: ok, sure

15:05 rhickey: actually what you might want to do is make the repl server not a stomp server at all but just another client, then stick a simple proxy in between. That let's you substitute a real mq if you want

15:06 cemerick: rhickey has gone enterprisey on us all! :-P

15:06 wdouglas: X(

15:06 rhickey: cemerick: it's a flexibility that falls out of a little indirection and standards

15:07 cmiles74: I'm all enterprisey, I've never read the stomp docs until today. It looks like most MQ servers already support stomp.

15:07 rhickey: stomp is widely supported

15:07 clients and servers, lots of bridges

15:08 cemerick: rhickey: Q: are you viewing nREPL (conceptually) as a networked/hosted REPL, or as the basis for a clojure MQ or somesuch?

15:08 rhickey: cemerick: lot's of people are independently reinventing distributed clojure execution, it caould fall out of doing nrepl right and combining with a message queue

15:08 duncanm: la la la

15:08 kotarak: ahem, how would a repl interaction look like with stomp?

15:08 rhickey: cemerick: are they different?

15:09 wdouglas: rhickey: Wouldn't one be more of a programmer interface to running/debugging code as it is being written and the other more of an administrative interface to production code (though surely most of the features should/could be the same)

15:10 kotarak: If I transport code to be executed in the body, how can I specify *in*?

15:10 rhickey: cemerick: I just think with a slightly broader view of the world you could get a lot more bang for the same effort

15:10 kotarak: If I transport *in* in the body, where do I specify the code?

15:10 cemerick: kotarak: presumably, each k/v pair would be written out in a SEND

15:10 rhickey: I *really* wish you had stated that, oh, 4 hours ago.

15:10 duncanm: i'm learning Incanter - I don't understand how 'incanter.core/group-by' works

15:11 kotarak: cemerick: and everthing in one transaction and COMMIT would finally trigger the evaluation?

15:11 cemerick: kotarak: mmm, maybe. I only first heard of stomp earlier this afternoon, so I'm in no position to be advising.

15:12 kotarak: cemerick: yeah. sorry. was actually asking more into the open. (But you answered. ;P)

15:12 rhickey: cemerick: I think it falls out of first principles - indirection, opacity, standards, orthogonality, generalization

15:13 what is a repl but a remote execution system?

15:13 chouser: kotarak: I'll write up an example of what I was thinking. probably wrong, but may help as a starting point

15:13 kotarak: chouser: yes, please. To get a feeling how stomp would work.

15:14 hugod: cemerick: I have a version of swank-clojure running with futures similarly to your nrepl :)

15:14 the rpc protocol is factored out too

15:16 cemerick: rhickey: but recasting it in terms of MQs, brokers, and endpoints is a non sequitur for all currently-practiced use-cases. That reinforces my thinking that things should stay as they are, and we can stack MQ-related adapters on top as desired.

15:16 There's no reason why MQ concerns should push their way into simple point-to-point operation.

15:17 rhickey: cemerick: exactly the opposite, if you use stomp you can slide them _under_ later

15:17 cemerick: rhickey: I never said the wire protocol had to be carried along. Quite the opposite.

15:18 This is exactly what multimethods are for, etc.

15:18 rhickey: stomp has very little mq-ness, no brokers etc, mostly connect/send/receive/deal-with-erros

15:18 we can ignore transactions

15:19 cemerick: That's fine, and we can use stomp, but it doesn't need to be baked into the thing for the simplest use-cases.

15:20 cmiles74: Looking at the docs, stomp seems very simple.

15:21 rhickey: I think you are wrong about being able to do everything 'over'. You will get low-level clients that depend on, e.g. there being a socket there

15:21 chouser: kotarak: http://gist.github.com/603361

15:21 rhickey: your 'simple' protocol will be a ball-and-chain

15:21 chouser: oops, hang on already see a mistake

15:22 cmiles74: Stomp looks very close to the "simplest" protocol.

15:22 chouser: there

15:23 rhickey: cemerick: basing it on something like stomp (at the lowest level promised) will keep people from writing socket code

15:24 and thus enabling swapping transports _under_

15:25 cemerick: rhickey: and this is where you start pitching netty to me again ;-)

15:25 rhickey: cemerick: no, as I said, I think simply offering something like stomp as the lowest-level promise will enable swapping things _under_ it

15:26 and I think stomp in clojure sans deps is very tractable. ditto elisp

15:26 chouser's probably halfway done :)

15:28 chouser: I found this webserver.clj I last touched in April 2008...

15:29 rhickey: cemerick: the main objectives are standard protocol and transport independence, not deps :)

15:31 going client -> proxy -> client instead of repl server == stomp server is just a forward-looking way of implementing

15:33 in fact, when you think about it that way you see that a lot of the transactional etc semantics are properties of the pipe/proxy, not the server. On bothe ends it just looks like async send/receive

15:34 to be clear, repl-client -> stomp-client -> stomp-[proxy]-server -> stomp-client -> repl-server

15:34 hiredman: getting hornetq is a drag

15:34 rhickey: hiredman: how so?

15:34 hiredman: I am using it to get irc notifications as growls (irssi on a remote machine)

15:35 if I recall it was a pain to get matching jars of hornetq and netty

15:35 and hornetq only had javadocs up for a released version that wasn't in maven yet

15:35 and they didn't build javadocs for the embedded server stuff

15:36 rhickey: hiredman: I just grabbed the zip and it has hornetq and netty jars...

15:36 hiredman: but I still kind of wish we used it at work over rabbitmq

15:36 rhickey: but to pull it in via project.clj

15:36 which I guess if it comes with clojure it's no big deal

15:36 rhickey: hiredman: oh, that

15:37 :)

15:37 cemerick: goodness, hopefully optional

15:37 rhickey: I'll take a closer look at stomp and see if there are other alternatives floating about.

15:37 rhickey: cemerick: sounds fair

15:37 cemerick: It's all yak-shaving AFAIC so far, though.

15:37 rhickey: cemerick: thanks for listening

15:38 hiredman: the only machine that I do dev on I got the latest hornetq into my local .m2 some how and just do uberjars and run those elsewhere

15:38 cemerick: rhickey: If you could do a full reading of the design notes that are up there, that'd be good, so you at least know the full backstory of where nREPL is coming from.

15:40 * cemerick gone to handball

15:41 rhickey: cemerick: did that

15:43 chouser: so taking this approach:

15:43 kotarak: chouser: how do handle *in*?

15:43 rhickey: to be clear, repl-client -> stomp-client -> stomp-[proxy]-server -> stomp-client -> repl-server

15:43 brings it substantially towards what you asked for. Effectivel, read the stomp protocol as if both repl-client and repl-server are stomp _clients_

15:44 and the other stuff will be dummied by the proxy or supplied by a real mq

15:44 kotarak: chouser: one probably needs a transaction. SEND type input, SEND type code, COMMIT something like this...

15:47 chouser: or input is another destination, where data can be streamed to.

15:48 chouser: rhickey: I'm not sure that a no-dep repl-server is really no-dep if it needs a proxy running somewhere

15:48 rhickey: so the repl server does not accept subscriptions, nor ack nor receipt

15:48 chouser: rhickey: I like the flexibility of that topology, but ...

15:48 rhickey: the proxy is another page of clojure code in the same vm as the repl server

15:48 chouser: ah, ok

15:48 rhickey: indirection!

15:49 kotarak: rhickey: subscriptions could be used for a running repl session to carry over state between connections.

15:49 chouser: kotarak: *in* is a great question. I don't think any of the nREPL docs cover that yet, do they?

15:49 kotarak: rhickey: for vim it will be connect, send stuff, receive answer, disconnect, connect, ...

15:49 chouser: it accepts now an "in" key with data which is provided as *in*

15:49 rhickey: kotarak: let's not go there now, but the idea of separate subscriptions for out and err is possibly useful

15:50 also in

15:50 chouser: kotarak: my tendency would be to do *in* async like *out*

15:50 kotarak: rhickey: I have to go there now. If you propose stomp, i have to think how a repl can work across stomp.

15:50 chouser: kotarak: could you work with named fifos? periodically reading from them to append to a buffer?

15:50 hiredman: rhickey: while you are here, I am trying to load multiple verions of clojure at once via isolated classloaders, but while I can use the RT loaded from each classloader to grab vars and see that I have different versions of clojure loaded, I cannot seem to get load to work

15:50 rhickey: so a repl could have twon in-queue, input an *in*, and 3 out queues, output. *out* and *err*

15:51 kotarak: chouser: on windows?

15:51 chouser: kotarak: :-(

15:51 kotarak: chouser: I'd like to drop win support, but I need it myself. :/

15:51 would make things a hell easier...

15:51 chouser: kotarak: the problem is that repls aren't really transactional at all

15:52 expr->return value is, but in/out/err are not

15:52 rhickey: transactionality in stomp is about the message to the mq, not the repl-server

15:52 chouser: hm... maybe in is a bit

15:52 kotarak: chouser: well. Mine works quite well. With know limitations, like blocking while a command runs and no streaming in.

15:52 chouser: sorry, shouldn't have used that word.

15:53 rhickey: actually taking the mq approach of stomp greatly simplifies the design, since a repl server really has 5 endpoints

15:53 all could be addressed inside a single connection

15:53 kotarak: vim sucks really hard with outside world interop. :(

15:54 rhickey: hiredman: that's kind of general, but I could easily see problems. There is no visibility of classes between loaders

15:55 chouser: kotarak: ok, so ought to be able to send in and expr as seperate messages.

15:55 the expr you send will presumably block on *in* which will be satisfied by a subsequent message.

15:56 hiredman: rhickey: thats what I want, I want the classloader to be it's own little universe

15:56 rhickey: chouser: did you see above? a repl serve is 5 queues

15:56 kotarak: rhickey: that doesn

15:56 rhickey: hiredman: then you'll have to tell me more about load not working

15:56 chouser: kotarak: your blocking client can then accept msgs until it gets a return value and then disconnect, losing any *out* or *err* that would have come afterward (from some other thread)

15:56 kotarak: oops

15:57 rhickey: that doesn't help me. I have to cut things down.

15:57 rhickey: kotarak: a stomp client can do that over a single connection

15:57 chouser: rhickey: yep, makes sense. destinations named like /sessionname/out or /sessionname/expr ?

15:57 rhickey: chouser: right

15:57 2 inbound, 3 outbound

15:58 hiredman: rhickey: well I guess I will do more digging then

15:58 rhickey: clients can send input, or *in*, get output, *out* and *err* cleanly

15:58 kotarak: chouser: I can live with that. Someone wanting more has to use an external repl anyway. More is not possible with vim.

15:58 chouser: my example gist's use of SEND and MESSAGE is still valid from the point of view of the client, right? it doesn't know there's a proxy in-between

15:58 shoover: does stomp SUBSCRIBE mean two clients can receive messages from one REPL?

15:58 rhickey: chouser: both repl server and repl client use send/message

15:58 the repl server is not a stomp server

15:59 chouser: yes, but the client will see MESSAGE for responses

15:59 kotarak: shoover: I would think so.

15:59 chouser: and the repl server will see MESSAGE for expr and in

15:59 rhickey: chouser: yes, as will the server for input

15:59 right

15:59 chouser: good

15:59 rhickey: I'm finding this very clean compared to repls over sockets

16:00 interleaving in/out and the streams usually being gross

16:01 chouser: client has to subscribe to all three channels

16:01 rhickey: you'll need some flushing policy for output

16:01 chouser: if they want

16:01 kotarak: rhickey: I don't do that in vimclojure even today. You'll get out and err not intermingled. But I cannot use long lasting connections.

16:02 rhickey: timeout + amount-driven

16:02 chouser: and has to send something to the server to tell it to subscribe to /my-new-repl/in and /my-new-repl/expr

16:03 rhickey: chouser: no, server establishes all five queues

16:03 chouser: when?

16:03 dmiller2718: rhickey: time for ClojureCLR question?

16:03 rhickey: chouser: when it comes up

16:03 chouser: so only one session per server?

16:04 rhickey: chouser: dunno, could be multiplexed or yes, then client will need to tell server to listen to queues it establishes

16:04 dmiller2718: shoot

16:04 actually, I have to run, bbl

16:05 sorry

16:05 dmiller2718: rhickey: too bad. Later.

16:06 shoover: dmiller2718: I put up some binaries. No promise to maintain, but it exists: http://clojure.bighugh.com/releases/clojure-clr-1.2.0-binary.zip

16:06 dmiller2718: rhickey: Later for me will be in a day or two. Heading to the airport now.

16:07 ninjudd: i've just been reading along to catch up on the discussion, but using stomp sounds very promising to me. i think it will address the issues with nREPL that would keep me from using it with cake, namely streaming support for *in* and *out*

16:09 chouser: you aren't already working on a clojure stomp library, are you?

16:09 shoover: I don't get why async is so good for the repl expr. Isn't that part of this problem essentially RPC?

16:09 chouser: ninjudd: who, me?

16:09 why would you think such a thing?

16:10 ninjudd: just because i was thinking of doing the same thing...

16:10 chouser: ninjudd: you should do it. I definitely shouldn't.

16:10 ninjudd: neither should i

16:10 chouser: ninjudd: note what rhickey said about separate repl-server-as-client and stomp proxy

16:11 wdouglas: How would that work having the proxy on the same vm as the repl server?

16:11 chouser: I do have a few lines of code that listen on a port and parse http-like headers

16:11 ninjudd: chouser: yeah. if i understand stomp correctly, wouldn't that be the only *right* way to do it?

16:12 chouser: ok, http://gist.github.com/603361 is updated

16:13 ztellman: I don't know if most of what a messaging queue can do is necessary

16:13 should each client have to ACK every line from *out*?

16:13 do we want to journal output if no one's listening?

16:13 chouser: ztellman: stomp doesn't require acks

16:14 ztellman: chouser: there is an ACK message I saw, did I misunderstand?

16:14 ah, never mind

16:14 ninjudd: ztellman: is that what ack auto is for? to not require acking every message?

16:14 chouser: yes, but servers aren't expected to send that unless the client has asked for it

16:14 ztellman: ack is not the default

16:14 chouser: ninjudd: I think so, yes.

16:15 ztellman: anyways, it seems rather trivial to create a message router in nREPL rather than proxying it

16:15 chouser: wdouglas: that's a good question. I think best would be for the repl-server code to use an API that could be supplied by either an in-process stomp server (acting as a sort of proxy) or by a real external stomp server.

16:17 wdouglas: chouser: Okay, in process stomp server makes sense for local. It seems like there needs to be a "master" stomp server if you wanted to do a mq setup from how you wrote the gist, is that how I should read "destination:/main-repl/"

16:17 chouser: so nrepl-server would say (subscribe stomp-server "/main-repl") and either the internal "proxy" would note that itself or the internal client would send that as a message to a real server

16:19 wdouglas: Ah great. Would stomp allow for a group of real stomp servers to process requests (can we build it on stomp at least)

16:19 ohpauleez: ztellman: Love the new docs you've been putting up. Let me know anytime I can help

16:20 chouser: wdouglas: hm, maybe we need another level of name in the destination? I meant /main-repl/expr only as a way to communicate to "the" repl-server before an individual session has been started

16:20 ztellman: ohpauleez: glad you're finding them helpful, they're still very much in-progress

16:20 chouser: how siloed would these individual sessions be?

16:20 chouser: maybe when you start a nrepl-server you give it a stomp server address (or tell it to start it's own proxy) and give it it's name, like "webserver-repl"

16:21 ohpauleez: ztellman: It was more than enough to push me up the learning curve. I've already happily used aleph in two systems now

16:21 chouser: ztellman: not at all

16:21 hm

16:21 ztellman: chouser: what's the point, then?

16:21 chouser: actually, that's a good point

16:22 ztellman: yeah, there should be 5 channels, period

16:22 everyone shares *out*, everyone's *in* is mingled, etc.

16:22 chouser: the jvm only has one real out/in/err for the process

16:22 kotarak: chouser: you can do tricks to split that, see nailgun

16:23 ninjudd: chouser: yeah, i was thinking that a single stomp broker could handle all repls on a given machine (or cluster) on a known port, and each one would have a unique queue path to identify it

16:23 kotarak: yeah, i wrote a simple proxy to split System/out and err for cake too

16:23 ztellman: ohpauleez: glad to hear it. please don't hesitate to tell me if you run into any obstacles, I'm hungry for feedback

16:23 ohpauleez: will do

16:24 ztellman: ninjudd: how does that handle new threads?

16:24 kotarak: nailgun basically provides per thread ins and outs which are inherited across new threads

16:24 a given thread might choose to override the one it got from its parent

16:25 sharing in/out/err between repl session is a no-go

16:25 ztellman: I'd argue sharing classloaders between repl sessions is a no-go

16:25 so start a new server if you want something different

16:26 ninjudd: ztellman: yeah, new threads would need separate queues beneath the repl's path

16:26 lpetit: All in all, I hardly see clients heavily use *in*

16:26 kotarak: lpetit: I do

16:26 heavily

16:26 ztellman: if you can't perfectly silo multiple repl sessions in a single process, then don't create some leaky abstraction that makes them seem separate

16:26 KirinDave: Hum

16:26 http://idisk.me.com/dfayram/Public/Pictures/Skitch/This_Morning_s_Git_Protocol_Outage_-_GitHub-20100929-132219.png

16:27 Reminder to everyone: Never be this guy.

16:27 LauJensen: haha

16:27 kotarak: ztellman: I can silo multiple repl session on a single vm today. We should I choose something less than that?

16:27 lpetit: kotarak: can you explain?

16:27 KirinDave: LauJensen: Even funnier; he's french.

16:27 LauJensen: KirinDave: I figured, either French, German or Danish :)

16:28 ninjudd: kotarak: here's the code from cake for splitting System/out https://gist.github.com/8ff63cbfe153c1d382e3

16:28 chouser: could you subscribe to someone else's /expr and /in and watch what they're doing?

16:28 kotarak: lpetit: I send data to a "repl" if you want to call it like that, which is then crunched by a clojure function and a result is returned.

16:28 lpetit: not using *in* means escape hell

16:29 ztellman: kotarak: cake seems to use a process-per-project approach

16:29 are you saying that's not necessary?

16:29 chouser: ninjudd: so if you print from an agent or future, that output gets lost?

16:29 kotarak: ztellman: no. But I want multiple independent repl sessions in parallel which do not interfere with each other on one single vm.

16:30 chouser: kotarak: how do you handle print or read-line from agents or futures?

16:30 lpetit: kotarak: but maybe not anymore if nREPL uses stomp, though ?

16:31 kotarak: chouser: it gets lost. This is a limitation of vim I have to live with. There is no constant connection. And no clean way to do polling as far as I can tell.

16:31 lpetit: anyway

16:31 ztellman: kotarak: so isn't that a deal breaker?

16:31 ninjudd: chouser: only if the atom at the root binding of *outs* is empty. in cake i add a FileOutputStream there, and then each new thread adds itself to the atom so that the most recent thread will get the output

16:31 kotarak: ztellman: what?

16:31 ztellman: kotarak: the loss of output

16:31 ninjudd: that's what the with-outstream macro is for

16:32 kotarak: ztellman: as I said: it's a limitation of vim. It's no dealbreaker for me because I know about that. If I want that I start repl in a console see all the output and can still connect to a nailgun server in that vm.

16:33 ztellman: If you I want everything from inside my IDE I must use something different from vim.

16:33 ninjudd: chouser: added a simple example to the gist

16:34 chouser: ok, what if there was an api for tying new stomp destinations to java streams.

16:34 then you could send code that would do that for the duration of one "session", whatever that means to you (one connection for vim, etc.)

16:35 ninjudd: chouser: that would be awesome

16:35 kotarak: chouser: isn't that trivial? /repl/1/out, /repl/1/in, /repl/1/err, /repl/1/eval, /repl/1/result, /repl/2/in, etc...

16:35 subscribing to /repl/1 would make that keep state between connections.

16:36 not subscribing would be one-shot repl

16:36 for a single command, eg. completion request or something

16:36 unsubscribing would basically stop that repl.

16:36 ninjudd: don't you have to subscribe to receive any messages at all?

16:36 kotarak: hmm... bit subscriptions work only will we are connected?

16:37 ninjudd: hmm... you are right.

16:38 lpetit: out of curiosity: when you both have a local git clone of someone else's repository, and a public github clone, how do you "locally" name those remotes in your local configuration ? And to which do you connect your local master branch ?

16:38 chouser: my point is that the handling of repl "sessions" could be kept largely out of the protocol

16:38 kotarak: I think it is possible to get this easily running over stomp, properly separate for separate repl sessions.

16:39 chouser: I think it has to be.

16:39 ztellman: kotarak: what sort of classloader trickery is necessary to make that work? I'm not particularly familiar with nailgun

16:39 chouser: if we admit to the possibility of clients asking the server (via regular clojure code) to create a now in or out stream and attach that to a stomp dest, then the actual mechanics of that can be left to higher-level code

16:40 lpetit: I guess it's easier to get up to date if the remote named "origin" points to the original clone of the project you're tracking ? How do you name the remote which points to your public fork of the project ? Is there an established convention for that ?

16:40 chouser: s/now/new/

16:40 kotarak: ztellman: It does no classloader trickery at all.

16:40 ztellman: but I get the impression we are talking about different things.

16:40 ztellman: kotarak: so how does my #'user/a not shadow your #'user/a?

16:40 in our separate repl sessions

16:41 ninjudd: ztellman: they would be the same

16:42 that is currently what happens with cake if you open two repls in the same project

16:42 kotarak: ztellman: there is only one #'user/a. I'm not concerned about this separation. In fact this wouldn't help me at all, because I want to define maybe #'foo/a in one connection from the editor and access it in another session from the interactive repl.

16:43 ztellman: that feels like a leaky abstraction to me

16:43 kotarak: ztellman: that's how the IDEs work

16:43 ztellman: cake's process-per-project seems reasonable

16:43 kotarak: ztellman: ok. rowing back. That

16:43 That's how VC works

16:44 chouser: the easy problem to solve, and worth solving, is two clients sending at the same time (+ 1 2) and (+ 2 3) respectively and making sure they don't get the other's response

16:44 rhickey: *in* isn't stdin, it can be rebound per-session

16:45 kotarak: chouser: bingo.

16:45 rhickey: chouser: messages are tagged with ids

16:45 chouser: somewhat harder is sending (prn :hi) and (prn :lo) at the same time and separating the responses

16:45 harder than that (future (prn :x)) and (future (prn :y))

16:45 kotarak: chouser: why? Have different repl "sessions" with different ids.

16:45 rhickey: wow, this is way out. we need to determine what "session" means

16:46 chouser: right

16:46 rhickey: a session could have its own set of 5 queues

16:46 chouser: rhickey: that's what http://gist.github.com/603361 now demos, but I'm not sure if it makes sense

16:47 because of the future :x/:y case above

16:47 ninjudd: but should you be able to connect to someone else's 5 queues? like tmux or screen

16:47 kotarak: For VC I can start a repl and get back a session id. Further connections with this id get its state (*1 and such) and the i/o from this repl gets sent back. A request "-1" is basically a one-shot thing. This works quite well.

16:47 chouser: ninjudd: that's a different question. sounds like fun to me.

16:48 kotarak: but doesn't handle future :x/:y, right?

16:48 kotarak: even if you block waiting for the future to complete?

16:48 kotarak: chouser: It could if the connection was long lasting, but it can't because vim is too limited for that.

16:48 astoddard: Would someone please clue me in on a string API question? Looks like all of c.c.str-utils2? is deprecated, as is c.c.string/split. Does that mean java's String split method is preferred?

16:48 lpetit: chouser: w/regards to separating things that come from printing simultaneously, there's simply no solution I guess.

16:48 rhickey: or a server could multiplex its input queues and have 3 output queues per client/session, providing clients identify their identity in the message

16:48 kotarak: chouser: but there is not technical reason it could not do that.

16:49 chouser: kotarak: sure there is. how does the thread in the pool know which session to write to?

16:49 ninjudd: i couldn't figure out a way to solve future :x/:y, which is why that output just goes to the most recent registered thread

16:50 if you really want to be sure where a future prints, you can rebind *out* inside it

16:50 kotarak: chouser: the thread inherits that from its spawning thread. nailgun does that. It works. Now. Maybe it's not the best solution. (Probably it's even bad) But it works.

16:50 ohpauleez: astoddard: clojure.string

16:50 all the util methods got promoted

16:50 astoddard: http://clojuredocs.org/Clojure%20Core/clojure.string

16:50 chouser: kotarak: but calling future may not spawn a thread, it may use an existing one. nailgun really does this?

16:51 ohpauleez: except the ones that got deleted. :-P

16:51 rhickey: you probably want a gatekeeper which will only accept requests to establish sessions, sets up queues, fires up repl server thread and tells client what queues to use

16:51 ohpauleez: chouser: Yes, except all the ones that got deleted :)

16:51 kotarak: chouser: ah. Ok. That's bad. No. It uses ThreadInheritableLocal or something similar cryptic. So it probably doesn't work with futures.

16:51 rhickey: one gatekeeper per JVM

16:52 chouser: kotarak: similar issue of course with agents and their pools

16:52 astoddard: ohpauleez: Thanks, don't know how I missed clojure.string

16:52 ninjudd: rhickey: the session-id in the CONNECTED message could be used for that

16:52 though i suppose you would need a way to tell the repl server about new session ids

16:53 chouser: rhickey: but we still don't have a solution for futures and agents, do we? promising *out* separation in the protocol requires one, doesn't it?

16:53 rhickey: ninjudd: the connected stuff is for the mq, you can't use it for app logic like that

16:53 ninjudd: rhickey: why not?

16:53 chouser: ninjudd: I imagine it doesn't get proxied

16:54 ztellman: rhickey: when you're advocating for websockets, do you mean that they should be native to nREPL? Why not just have another proxy?

16:54 chouser: ztellman: definitely another proxy

16:54 rhickey: chouser: other than with-bindingds et al?

16:54 bound-fn

16:55 ninjudd: chouser: i'm just saying you can use that as a unique id and add it to your queue paths

16:55 ztellman: chouser: okay, so why all the angst about dependencies?

16:55 kotarak: Don't forget System/in and friends.

16:55 I mean System/out.

16:56 chouser: rhickey: hm. I guess that's what existing repl servers have to do now anyway.

16:56 rhickey: ninjudd: that sessoin is the id between the client and the mq, not the client and the repl-server

16:56 chouser: ninjudd: the repl-client and repl-server each connect to a proxy. each gets their own session id and neither sees the other's

16:57 ztellman: stomp itself is also a dependency, server and client

16:57 ninjudd: rhickey: i realize that, i was just suggesting reusing it. but you would still have to communicate it to the repl-server, so that doesn't really buy you anything

16:57 rhickey: chouser: aren't we implementing stomp ourselves? so no deps?

16:57 chouser: ztellman: as much or more angst is there as with websockets

16:58 rhickey: yep, ninjudd's probably half done already.

16:58 ztellman: yeah, I thought this was going to be a cleanroom version of stomp

16:58 ninjudd: haha

16:58 chouser: ztellman: same for websockets I hope

16:59 ztellman: chouser: I could get a websocket -> stomp proxy done in a very small amount of time, it would just use a bunch of stuff that doesn't belong in core

16:59 rhickey: the easiest way to do this correctly is to use a real mq in between while writing the repl client/server

16:59 polypus: is contrib 1.3.0-alpha1 up yet?

16:59 ninjudd: i've created a repo and typed about 10 lines of code, so yeah... half done http://github.com/ninjudd/clj-stomp

16:59 rhickey: then, sub in a proxy

16:59 that way you know it will work over a real mq

16:59 and you haven't conflated the roles

17:00 chouser: rhickey: did you see the discussion about in-process proxy? would you actually want threads in the process talking to each other over a socket?

17:00 rhickey: chouser: what socket? client and server don't know about sockets

17:01 polypus: is [org.clojure/clojure-contrib "1.3.0-alpha1"] available through lein?

17:01 chouser: streams?

17:01 clojurebot: duck-streams is now clojure.contrib.io

17:01 ztellman: chouser: wait, I may have misread that; are you saying there should be a cleanroom version of websockets as well?

17:01 rhickey: chouser: but no, a queue data structure could be used in proc

17:02 chouser: rhickey: right, ok.

17:02 rhickey: more indirection

17:02 chouser: that's not quite what I was thinking, so I see what you mean.

17:02 ztellman: that's what I'm saying, yes.

17:02 ztellman: chouser: why?

17:02 if you want a web frontend, just run a different process against the message broker

17:03 chouser: ztellman: so I can add an nrepl thread to some process and point my web browser at it.

17:03 s/thread/lib/

17:03 ninjudd: ztellman: right clojure shouldn't have to use websockets at all as long as the broker supports it

17:03 rhickey: in fact, you should write the repl client and server with stock java stomp clients, then sub in our stomp

17:03 polypus: never mind, found new form [org.clojure.contrib/datalog "1.3.0-alpha1"]


17:04 ztellman: chouser: so the message broker will be in-process?

17:05 ninjudd: ztellman: it can be, or not. shouldn't matter

17:05 chouser: right

17:06 ztellman: ok, I agree with that, I just don't understand why if we're willing to have one degree of indirection, we need to make the nREPL proxy such a swiss army knife

17:06 chouser: the idea being, if you don't mind deps and want all the features (ssl, proxying, tunneling, etc.) use a real stomp server (probably with websockets support built in) and even a real stomp client and tell nrepl to use that

17:06 rhickey: ztellman: how so? the in/out/err etc are inherent complexities of remote repl

17:07 chouser: but if you don't want deps you get some minimal but fully interoperable subset: a standalone stomp server, which I'd like to have websocket support.

17:07 rhickey: mq style logic allows you to multiplex them sensibly

17:07 ztellman: rhickey: if I understand this correctly, in/out/err/eval/response are all going through the message broker

17:07 rhickey: ztellman: yes, and?

17:08 ztellman: rhickey: so why can't a separate web-facing process forward messages to it through the message broker

17:08 rhickey: ztellman: I don't see where the web comes into it

17:09 ztellman: rhickey: this conversation started re: websockets

17:09 kotarak: I'm I right in the assumption, that the stomp stuff is just envelope?

17:09 chouser: ztellman: it absolutely could. but I'd like that particular feature without requiring a separate process out there

17:10 kotarak: yes, though I'm tucking a few custom headers in there just for nrepl

17:10 rhickey: http://jmesnil.net/stomp-websocket/doc/

17:12 so, one simplification would be to just have in and out queues and use message body formatting to multiplex messages related to input/*in*/output/*out*/*err*

17:12 chouser: or custom headers

17:12 type: in, type: err

17:12 rhickey: chouser: yes, fine, didn't see that support

17:13 chouser: that was my original thought with stomp, before someone mentioned multiple destinations

17:14 that means you only have to subscribe once. *shrug*

17:14 rhickey: chouser: just wondering if it makes the server/client easier or harder to write, or more or less responsive

17:15 one subscription sounds easier

17:15 chouser: I wonder if it changes promises about order of messages at all

17:15 ninjudd: one other benefit is that is may assure that the relative ordering is correct

17:16 chouser: ninjudd: jinx!

17:16 ninjudd: hehe

17:16 rhickey: chouser: I hope not, who can tell the interleaving of e.g. *out* and output anyway?

17:16 ztellman: *err*'s position relative to *out* might be useful information, though

17:17 chouser: ztellman: can't bet on that -- those flush inconsistently

17:17 rhickey: right

17:17 chouser: I guess that's true of *out* and return value too.

17:17 rhickey: right

17:18 chouser: though for the latter the server could promise to flush *out* before sending return-value

17:18 and then if the mq swapped them everyone would be sad.

17:18 rhickey: but if, e.g. accessing a queue or connection must be single threaded, then these things will have to block each other

17:18 chouser: or queue up

17:18 rhickey: chouser: still contention at the queue

17:19 chouser: yeah

17:19 rhickey: but not much

17:19 clients will likely be happier with one subscription

17:19 but who knows

17:19 lpetit: hmm

17:20 probably depends on the API of stomp impls, and the out of the box facilities to plug hook functions in both scenarios

17:20 s/stomp impls/stomp client impls/

17:21 sexpbot: <lpetit> probably depends on the API of stomp client impls, and the out of the box facilities to plug hook functions in both scenarios

17:21 rhickey: lpetit: I doubt any have the ability to route to separate functions based on our custom headers

17:21 but all will allow separate functions per subscription

17:21 lpetit: so enter the multimethod world

17:21 ok

17:21 (at least ! :-) )

17:22 ninjudd: there is the selector header for subscribe, but it has to be supported by the broker

17:23 lpetit: chouser: you can also provision a place for an additional header meta data, for cases where nREPL will play in OSGi-like land :)

17:23 ataggart: rhickey: I was going to try to write a patch for ticket #445 (since I opened it and it affects me). Am I missing some deeper reasoning behind that functionality not already being present?

17:23 rhickey: ataggart: links are good

17:23 ataggart: https://www.assembla.com/spaces/clojure/tickets/445

17:23 rhickey: thanks

17:24 lpetit: chouser: probably named *bundle* (after *ns* naming convention). *bundle* being bound to either a keyword or string representing the "current bundle"'s symbolic name whose classloader to use for eval'ing from

17:24 #445

17:25 chouser: lpetit: can probably handle that in the code you send, can't you?

17:25 lpetit: doesn't sexpbot or clojurebot have a facility for generating clojure links

17:25 chouser: hm. maybe your idea is better.

17:26 lpetit: chouser: it's a fresh idea, though.

17:27 rhickey: ataggart: it will just make overload resolution more complex. Also, makes you more dependent on representation, so I decided to make you specify

17:27 lpetit: chouser: but as far as I can think about it, makes perfect sense in an OSGi environment. And things like (in-bundle) (named after (in-ns), and even (someday !) (bundle) (to create a bundle in memory on the fly !)

17:28 may be used to change *bundle* in the repl session

17:28 jjido: what are the allowed characters in identifiers? I need to name a "private" var

17:29 rhickey: ataggart: you can try it, but your chances of not breaking something are slim

17:29 ataggart: seems like something to do differently in cinc

17:30 ataggart: rhickey: Very well, I'll give it a try. At least I'll get familiar with the internals. Also, could you clarify what you mean by "dependent on representation"?

17:32 rhickey: ataggart: 42 was an int, now it is a long.

17:37 cpfr: Hey, what ballpark is clojure's speed in?

17:37 faster than python, slower than java?

17:39 lancepantz: yes, and sometimes :)

17:39 or arguable, and arguable

17:39 cpfr: thanks

17:40 just trying to reason about where it makes sense to use it

17:40 ataggart: It can be as fast as java. It depends on what you're doing and how you're doing it.

17:40 cpfr: since right now I am just using it as nicer glue for lucene and hadoop

17:41 kotarak: cpfr: got code which is on par with Java, but ugly

17:42 cpfr: kotarak, anything macros can't clean up?

17:42 kotarak: Then the macros are ugly

17:42 jjido: How to? Unroll optional named arguments. Callers should not have to wrap optional named arguments in a map literal:

17:42 (release-sharks 2 :laser-beams true)

17:43 lancepantz: jjido: (apply hash-map opts)

17:43 ataggart: (defn release-sharks [n {:keys laser-beams other-key etc}] ...)

17:43 amalloy: jjido: http://tinyurl.com/2caflx5 for a description of legal symbols

17:43 jjido: lancepantz: that works on a list of :key value?

17:44 lancepantz: -> (apply hash-map '(:foo "a" :bar "b"))

17:44 sexpbot: ⟹ {:foo "a", :bar "b"}

17:44 ztellman: jjido: (fn [x y & opts] (let [opt-map (apply hash-map opts)] .... ))

17:44 amalloy: jjido: (defn release-sharks [& {:keys [laser-beams]}])

17:44 ztellman: to fill out lancepantz's answer

17:44 ataggart: you don't need to do that. the :keys destructuring was added precisely to handle this situation.

17:45 amalloy: ataggart: jjido is asking how to avoid having the caller construct a map

17:45 jjido: ztellman: thanks

17:45 ztellman: attagart: it wasn't clear if he wanted to enumerate all the optional keys

17:45 ataggart: yes. I'm agreeing with your reply

17:45 I was just late ;)

17:45 and incorrect in the format

17:46 that's what I get for not yet installing clojure on this new machine.

17:46 amalloy: ztellman: my destructuring version is shorter and clearer, isn't it? and as of 1.2 it's identical

17:46 jkkramer: (defn release-sharks [n & {:as opt-map}]) is also shorter

17:47 ztellman: jkkramer's is identical and better

17:47 ataggart: but missing the binding of the relevant values

17:47 ztellman: I was just trying to clarify what lancepantz wrote

17:47 amalloy: ah

17:48 yes, mine requires enumerating the keys; a plus or a minus depending on what you want to do

17:49 jjido: all right, but if there are additional (unnamed) arguments can I extract that too?

17:50 jkkramer: (defn release-sharks [n & {:keys [laser-beams] :as opts}] ...) would bind laser-beams and put the entire map (including laser-beams and anything else) in opts

17:51 amalloy: jkkramer: oh, sexy. didn't realize you could combine :keys and :as

17:53 jkkramer: amalloy: ya. :as, too

17:54 ,(let [{:keys [a b z] :or {z 10} :as opts} {:a 1 :b 2 :c 3}] [a b z opts])

17:54 clojurebot: [1 2 10 {:a 1, :b 2, :c 3}]

17:55 jkkramer: er, :or too

18:08 jjido: that does what I want: (defn sharky [& more] (let [{:as opts} (drop-last 2 more)] (opts more)))

18:13 ossareh: is there a room for Ring specific questions?

18:14 lancepantz: ossareh: #clojure-web

18:14 ossareh: nice, cheers!

18:16 cemerick: Well, the channel was certainly busy while I was gone. :-)

18:17 jweiss_: if I want to apply the regex #".at" to "dog cat bat" and get back ("cat" "bat") how do i do that.

18:18 ninjudd: cemerick: welcome back!

18:18 lancepantz: cemerick: lol

18:19 lpetit: cemerick: chouser has almost finished the stomp deps-free impl !

18:20 jweiss_: ah re-seq

18:20 lpetit: no, just kidding

18:20 cemerick: Yeah, i was disappointed to not find nrepl entirely finished when I got back!

18:20 lpetit: :)

18:20 cemerick: ready to add osgi support backed in ?

18:20 :)

18:45 jjido: are we not allowed varargs in a protocol?

18:48 This protocol signature: (copy [self & bindings]) matches the following function: (fn [self foo bindings] nil)

18:48 :(

18:51 ztellman: jjido: no, it's an unfortunate limitation

18:51 however, it's easy to create a non-variadic function in the protocol called function-name-

18:52 and then (defn function-name [x y & rest] (function-name- x y rest))

18:52 cemerick: jjido: rest args turn into an array argument, since defprotocol defines a Java interface

18:52 jjido: ztellman: I see

18:53 cemerick: you'd call copy via (copy obj (into-array [rest args here]))

18:53 Hardly an ideal situation for sure.

18:55 jjido: cemerick: I don't really understand

18:55 cemerick: defprotocol creates a hosty (thus Java) interface

18:55 ztellman: cemerick: websocket->nREPL bridge looks something like this: git://gist.github.com/603718.git

18:56 just in case you were wondering

18:56 ninjudd: chouser, cemerick, ztellman, rhickey: done with a very rough stomp client implementation. feedback is welcome. http://github.com/ninjudd/clj-stomp

18:56 cemerick: jjido: and Java implements variadics with a trailing Object[] argument

18:57 Thus, you have to satisfy that (at least currently)

18:57 ninjudd: i'm somewhat new to protocols, so don't be to hard on me ;)

18:57 jjido: cemerick: yeah, but how do you declare Java variadics with defprotocol?

18:58 cemerick: (defprotocol Foo (bar [a & rest]))

18:58 jjido: cemerick: does not work (Clojure 1.2)

18:58 ztellman: cemerick: that doesn't work, rhickey implied that it never would

19:02 cemerick: damn, I could have sworn I had done that before :-/

19:02 jjido: sorry, my bad :-(

19:03 jjido: cemerick: np

19:04 cemerick: ninjudd: FWIW, nREPL has been targeting clojure 1.1.0

19:05 ninjudd: cemerick: why?

19:05 cemerick: ninjudd: because it's still used widely, and probably will be for at least some time to come

19:06 as it is, lpetit may be peeved at me for not targeting 1.0.0

19:07 ninjudd: cemerick: well it would be easy to modify my code to not use protocols

19:07 cemerick: yeah, I just wanted to let you know

19:07 ztellman: cemerick: never mind about the aleph stuff, then, unless that can go in a separate process

19:08 ninjudd: cemerick: now that you mention it, i would like cake to still support 1.1 as well

19:08 cemerick: ninjudd: I think it's a must, at least as long as Stuart's book is around

19:09 ninjudd: forever?

19:09 cemerick: I mean, selling in significant numbers

19:09 ztellman: is his book actively misleading w.r.t. 1.2?

19:09 or does it just not explain the new features

19:10 cemerick: no, but it's reasonable that people will actively seek out the version specified in it

19:10 Still the highest sales rank among clojure book, actually.

19:10 ninjudd: cemerick: honestly, the worst part about making it work on 1.1 is that i don't get to use (reader ) and (writer ) with a Socket

19:10 ztellman: cemerick: it's an excellent book, no surprise there

19:11 ninjudd: added a short example to the readme.. should have done that before i posted it

19:15 cemerick: presumably it'd be ideal if the java broker impl were used to automate testing against a live beast

19:17 ninjudd: cemerick: yeah, i agress. i just spun up stompserver before running the tests because i wanted to get to running the tests quickly

19:17 s/agress/agree/

19:17 sexpbot: <ninjudd> cemerick: yeah, i agree. i just spun up stompserver before running the tests because i wanted to get to running the tests quickly

19:17 cemerick: sure

19:18 ninjudd: rhickey was talking about having a clojure broker implementation too

19:19 jjido: do I need to repeat 'bindings' here: (new LinkedListClass (:head bindings) (:tail bindings) (:empty bindings)) or is there a short form?

19:21 cemerick: ninjudd: yeah, it'd be necessary for the everyones-a-client architecture he has in mind

19:23 ninjudd: that piece will be considerably more complicated, but not necessary to get started

19:24 scottj: jjido: not necessarily better: (let [{:keys [head tail empty]} bindings] (LinkedListClass. head tail empty)) (apply #(LinkedListClass. %&) (select-keys [:head :tail :empty] bindings))

19:28 jjido: scottj: in the first solution, what happens if the keys are out-of-order?

19:29 scottj: jjido: in the :keys ... the order doesn't matter

19:29 jjido: select-keys should work

19:30 ,(let [{:keys [foo bar]} {:bar 22 :foo 1}] foo)

19:30 clojurebot: 1

19:31 scottj: there might be a function somewhere that's like let-keys or with-keys where you can just pass the map without explicitly binding the keys. then you could to (with-keys bindings (LinkedListClass. head tail empty)). compojure used to have something like that but it got removed

19:32 [foo bar] refers to the key names, not order.

19:33 jjido: ok

19:49 ninjudd: cemerick: thinking about rewriting this without protocols. protocols don't really buy much in terms of performance anyway, right? because it still has to dispatch the call to send-frame for each method...

19:56 SirNick: So why is it that ''(1 2) becomes (quote (1 2)) but '`(1 2) turns into something like (seq (concat (list 1) (list 2))) instead of (syntax-quote (1 2))?

20:18 rhickey: cemerick: any further thoughts on stomp?

20:23 ninjudd: rhickey: i threw together a quick implementation http://github.com/ninjudd/clj-stomp. working on making it not use protocols now after talking to cemerick

20:24 rhickey: ninjudd: seems pretty simple

20:26 Raynes: cemerick: It's widely used? By whom?

20:28 ninjudd: rhickey: yeah. i'm not sure there is really much performance benefit from using protocols in this case anyway, right? there is still the cost of dispatching the call to send-frame or receive-frame either way.

20:29 rhickey: ninjudd: performance is not a reason to choose (or not choose) protocols

20:31 ninjudd: rhickey: fair enough. i was imagining that the protocol could be extended to other classes besides Socket, but that probably isn't very likely either

20:33 rhickey: ninjudd: well, one likely other extender is to use an existing client

20:34 ninjudd: thats a good point

20:35 lancepantz: isn't the discussion moot with the req of nrepl supporting 1.1

20:47 chouser: because ` is not '

20:48 oh, sorry, was scrolled up. SirNick ^^^

20:49 SirNick: chouser: Yea I'm just confused how ` is handled by clojure. Is it transformed by the reader into the (seq) expression?

20:50 dreish: You can use (read-string "`(...)") to find out.

20:50 But yes.

20:50 rhickey: no interactive repl takes input from other than *in*, is there a reason to distinguish?

20:51 chouser: ,'`(1 x ~x)

20:51 clojurebot: (clojure.core/seq (clojure.core/concat (clojure.core/list 1) (clojure.core/list (quote sandbox/x)) (clojure.core/list x)))

20:51 rhickey: we had talked about input distinct from *in*, but I'm trying to talk myself out of it

20:51 chouser: SirNick: contrast the result of x with ~x

20:52 rhickey: you mean using *in* for the expression to evaluate as well?

20:52 rhickey: of course a repl outputs to *out* , but for some reason I still want them separate

20:52 chouser: yes

20:53 SirNick: chouser: Yea I think I get the idea of ` vs ', but why does ` need to be transformed by the reader into another form whereas 'f is turned into (quote f)?

20:54 rhickey: I guess intermingled input and *in* makes it harder to pair request/response

20:54 chouser: output is separate because it means something different -- I want it colored differently

20:54 rhickey: but then I wonder about *in* in general

20:55 ninjudd: rhickey: i think it makes sense to keep them separate. in the context of cake, you will run into Readline weirdness if they are combined

20:55 chouser: for input I guess I'm less sure. I think I'd like to be able to tell the server "this is the whole input -- read and eval it now, throw an error if it's incomplete"

20:55 rhickey: imagining an interactive app, how could the client know that the user input isn't being eaten by read on the other end, e.g. not considered a command?

20:56 chouser: SirNick: '`[(+ 1 2) ~(+ 3 4)] and `[(+ 1 2) ~(+ 3 4)]

20:56 rhickey: e.g. (do (prn "what is your name?") (println "Hi " (read)))

20:57 chouser: is that an argument for mixed or separate input expr?

20:57 rhickey: how will the clinet know the next thing it sends is not a command?

20:58 chouser: mixed I think

20:58 ninjudd: rhickey: hehe, that is exactly the kind of issue that made me think separate would work better

20:58 rhickey: ninjudd: how could it work separate?

20:59 all human typing needs to go to the same place

20:59 or no interactive apps

21:00 some of that typing will be commands, some potentially read from *in*

21:00 ninjudd: i was thinking that the repl would have two modes. command entry mode and read mode. it starts out in command entry mode (with history, tab-completion, etc.) once a form has been sent, it goes into input mode and anything typed will go to *in*

21:00 SirNick: chuser: yea I see the difference, but I'm just trying to figure out why ` seems to be the only thing that doesn't have a matching expression. ~@ has (unquote-splicing ...), ~ has (unquote ...), but ` doesn't seem to have anything similar from what I can tell

21:00 rhickey: ninjudd: how do you enter two commands in a row?

21:01 ninjudd: don't end a line with a complete form, i suppose

21:01 yeah. it presents a problem for pasting

21:01 rhickey: ninjudd: I don't think that works

21:02 ninjudd: yeah, the way cake works currently is with interspersed input, but i mulling over changing it. but pasting is important

21:02 rhickey: i think you're right

21:03 * ninjudd is always wrong when he argues with rhickey.

21:04 ninjudd: i suppose most people are :)

21:04 chouser: ninjudd: indeed

21:05 other solutions seem convoluted

21:06 or maybe just broken

21:08 rhickey: so, if interleaved, clients can still, e.g. number messages sent, and the server can associate output with those numbers, but they need not be 1:1

21:08 since some read calls may eat some sends

21:08 also I presume send on newline, even if incomplete form?

21:08 client send

21:09 chouser: that's not how my clojurescript client worked, but I don't think I handled interactive reading at all

21:09 ninjudd: rhickey: cake does not send until it has a complete form

21:09 rhickey: we're not imagining dribblling characters are we?

21:11 ninjudd: seems to me it should be optional how many lines are in a message, so some clients can wait to send a complete form, and some can send right away

21:12 chouser: the terminal today does tricky things to avoid repeating a prompt when multiple forms are sent at once

21:13 rhickey: chouser: that's perhaps a bit too fancy, but right now I'm more concerned about not needing to support dribbling

21:13 chouser: if the server supports incomplete forms line-at-a-time, how is it any harder to support dribbling?

21:14 rhickey: chouser: maybe not, but seems wasteful, also how does one backspace/delete?

21:15 chouser: I don't see why a client would choose to do that, I'm just not sure to have to be explicit in the protocol.

21:16 ninjudd: cemerick: checked in a version of clj-stomp that works with 1.1 in a branch http://github.com/ninjudd/clj-stomp/tree/1.1

21:16 chouser: and you're right about skipping prompts -- that's up to the client UI I think.

21:16 rhickey: printing the result of eval goes to output, all other *out* separate?

21:17 chouser: the server knows when it's doing that printing that it's different, why not retain that info?

21:17 ninjudd: you need to support incomplete forms anyway if you want stdin between forms to be streamed

21:18 rhickey: chouser: I'm just confirming what we had talked about, but the interleaving question remains - we talked about that being a benefit of using a single subscription, but separating on the server might ruin it

21:19 I definitely want them separate, even if many clients will merge

21:19 cemerick: Raynes: what's widely used?

21:22 rhickey: stomp seems like the best option

21:23 rhickey: cemerick: did you see above about input commands and *in* needed to be the same?

21:24 cemerick: Yes, though I was skimming the log.

21:26 ninjudd: it would also be useful for the repl-server to send a form-complete message after reading but before eval so the client knows whether to print a prompt or not

21:27 cemerick: rhickey: Right this moment, I'm inclined to step away though. The design and requirements have shifted outside of my expertise, and what I was aiming for.

21:28 rhickey: cemerick: that's bad

21:30 cemerick: and certainly not what I want

21:31 cemerick: how can we reconcile this with your initial vision?

21:31 esp. - do you feel this will no longer satisfy it?

21:33 cemerick: rhickey: Same here -- but I've never used stomp or hornetq (which will be necessary as a stopgap until a clojure broker is available), and (I think, a.t.m) that the current impl would need a significant refactoring based on the shift (e.g. tracking multiple queues, etc).

21:34 hiredman: speaking of queues … http://intensivesystems.net/tutorials/stream_proc.html

21:34 cemerick: I think what's being designed will eventually be better -- but, you understand, I felt like I had a very workable solution, at least for the near term, and had turned towards integrating it with ccw.

21:35 I'm not sure I have the time to redesign from the ground up.

21:35 not right now, anyway

21:36 I suppose I may feel differently in a bit. I'm fairly frustrated with the status quo though.

21:38 rhickey: cemerick: I wasn't aware you had so much implemented already, still thought you were brainstorming

21:39 cemerick: rhickey: really?

21:39 the http://github.com/cemerick/nREPL link has been out there a bunch

21:41 jjido: can I set a record attribute after creating it?

21:41 cemerick: jjido: records are maps; use assoc

21:41 Anniepoo_: anybody have wise words on unit testing agents?

21:41 rhickey: cemerick: I didn't know there was code, thought you were just starting when you advertised the repo

21:41 jjido: or, can I declare a record before giving its definition

21:43 cemerick: not just maps and assoc just returns a new map -- doesn't change the original

21:43 cemerick: ah

21:43 jjido: that's generally considered to be a good thing :-)

21:44 rhickey: Not sure what to say. That there's an impl has been at the top of the design notes for a bit too.

21:44 Anyway, it's moot now -- I just wish I had gotten your perspective last week, or before. I didn't think you were particularly interested in the topic. *shrug*

21:45 jjido: alternatively, you can either put an atom in one of the slots, or use the metadata to indicate that certain slots are mutable, and/or volatile

21:46 jjido: I have this: (def a (new recordtype 1 2 (new b))) (defrecord b [] protocolname (what [_] a))

21:46 rhickey: cemerick: not knowing is certainly on me, I didn't mean to imply otherwise, but it was the case that I did not know you were so far along when I suggested doing it completely differently today :(

21:47 yayitswei: Anniepoo_: haven't done that before- is this related to your Second Life library by any chance?

21:47 cemerick: jjido: well, you have to define 'b' before creating a new instance of it

21:47 rhickey: I've got to go now, but let's see if we can't make the best of it tomorrow

21:47 jjido: cemerick: but b uses 'a' in its definition

21:48 Anniepoo_: I'm having trouble figuring out good ways to make unit tests for the

21:48 cemerick: jjido: yeah, that's not going to work

21:48 rhickey: sure; have a good night :-)

21:48 Anniepoo_: blackboard/broadcasting thing, so if that's what you mean, yes

21:50 not sure how it's related.

21:51 airolson: has anyone encountered the repl in slime apparently not evaluating anything?

21:52 when I hit return, the cursor moves to the next line and that's it

21:53 jjido: I used alter-var-root cemerick

21:54 cemerick: jjido: that's sort of a function of last resort

22:02 amalloy: airolson: one of the reasons it does that is if you have an unclosed paren

22:02 ossareh: or an unterminated string

22:03 airolson: amalloy: (System/getProperty "java.class.path") exhibits the behaviour

22:03 jjido: cemerick: would not be needed if I could tell Clojure that a will be defined later

22:04 cemerick: jjido: 'b' seems fairly wrong though -- shouldn't the 'a' instance be a field of 'b', rather than a top-level var?

22:06 jjido: no I need 'a' at top-level

22:06 airolson: aha, my problem was using slime-fancy instead of slime-repl

22:07 amalloy, ossareh: thanks anyway :)

22:10 jjido: what if I just do (def a) (defrecord b [] protocolname (what [_] a)) (def a (new recordtype 1 2 (new b)))?

22:10 cemerick: jjido: yeah, that will work -- though I doubt that you really need a at the top-level.

22:11 If you're just setting up a var for a forward reference, better to use (declare a) though.

22:11 jjido: cemerick: I didn't know about declare, thanks!

22:19 sproust`: Is there an equivalent to CL's (disassemble) in Clojure?

22:21 cemerick: sproust`: at the moment, AOT-compile the code in question, then use javap

22:21 Eclipse has a bytecode viewer baked in, which is nice.

22:32 sproust`: That's neat.

22:33 Eclispe, huh.

22:34 cemerick: sproust`: yup -- since 3.3, it looks like http://archive.eclipse.org/eclipse/downloads/drops/R-3.3-200706251500/whatsnew/eclipse-news-all.html

22:35 There's a jad plugin for eclipse too, but I've never used it

22:35 It'd be killer to have single-action views per function, of course. I'd say that's perfectly within reach of ccw already.

22:43 lambdalion: I'm have some questions about clojurescript...

22:43 err- I habe some

22:44 chouser: lambdalion: :-(

22:44 lambdalion: I'm wondering if 1) it is still being developed

22:45 why the sad face chouser? clojurescript, or my revision fail ;)?

22:46 chouser: clojurescript questions

22:46 lambdalion: aha...

22:46 chouser: it's badly out of date

22:46 lambdalion: I'm a pretty big fan of the CL lib "parenscript"

22:47 yes, that is one of my questions- I notice that the last commit was quite a while ago...

22:47 hiredman: technomancy: I think I've got lein using a in project classloader working

22:47 chouser: but I'm not interested in putting effort into it until clojure-in-clojure is further along

22:47 lambdalion: and it seems like the lib relies on some earmuff vars that are no longer around in the compiler

22:48 hiredman: technomancy: tests fail, but they are all looking for files written in /tmp that no longer get written

22:48 lambdalion: I see...

22:48 chouser: lambdalion: clojurescript is about getting clojure semantics into javascript. If you only want clojure syntax on javascript semantics, there are options

22:50 scriptjure is one, I think

22:50 lambdalion: well, I don't know the parenscript internals very well, but my impression is that they don't need to generate auxiliary js files, and that they don't need to know about the compiler/interpreter...

22:50 cemerick: The most popular, I think.

22:50 hiredman: last I looked scriptjure didn't have a LICENSE

22:50 lambdalion: ah- is that more analogous to parenscript?

22:51 cemerick: hiredman: EPL according to its only source file *shrug*

22:51 lambdalion: yes

22:51 lambdalion: I guess I was wondering.. if I wanted something like parenscript in clojure, would clojurescripy be something I could start from...

22:51 cemerick: or, at least insofar as I'm familiar with parenscript

22:52 hiredman: cemerick: no kidding, well that is good to know

22:52 lambdalion: but I read through the source and.. seemed very much about the Java bits

22:52 which makes sense, I guess, if you want to preserve the semantics

22:53 cemerick: lambdalion: clojurescript is clojure-in-javascript. scriptjure is writing javascript in parens. http://github.com/arohner/scriptjure

22:53 Might not be exactly what you want, but I'd start there.

22:54 lambdalion: OK, thanks... I have always been really impressed by parenscript...

22:54 the two macro namespaces are confusing, but...

22:55 once you get the hang of it it is a pretty amazing way to do js, particularly since a bit of macrology can integrate it into something like cl-who, and other libs for css, etc...

22:55 Vut I hadn;t seen sriptjure- I will look at that. Thanks.

22:56 * dnolen is waiting for someone to port parenscript

22:57 lambdalion: Hmm- well that is what I have been thinking about...

22:57 dnolen: lambadalion: I've used scriptjure, it's ok, from what I can tell not as robust as parenscript.

22:57 lambdalion: I was just wondering if there was anything like a start on it already.

22:57 arohner: lambdalion: dnolen can you guys go into more detail about what is possible with parenscript?

22:57 I haven't used it

22:59 dnolen: parenscript: it translates CL -> Javascript

22:59 lambdalion: hmm...

23:00 arohner: a better way to phrase that question: "what advantages does parenscript have that scriptjure lacks?"

23:00 lambdalion: parenscript is actually surprisingly difficult to completely explain... the reference manual is here: http://common-lisp.net/project/parenscript/reference.html

23:01 dnolen: arohner: probably just maturity, it may have a sophisticated compiler as well - I haven't looked to closely at the source.

23:01 lambdalion: and the tutorial is here: http://common-lisp.net/project/parenscript/tutorial.html

23:01 but...

23:01 parenscript has two macro-spaces...

23:01 and the implications of that are not immediately obvious.

23:02 arohner: lambdalion: so that you can have "clojure macros" and also "javascript macros"?

23:02 lambdalion: yes, zactly

23:02 but- that's hard to fathom.

23:03 but even wiothout that generating parenscript from CL is really nice...

23:03 arohner: lambdalion, dnolen : well if you have any suggestions on scriptjure, I'd love to hear them

23:04 sproust`: I want to transform a (doseq) to accumulte and return the values. That's (map), really, but I have to transform my expression. Thinking of building a macro instead for an accumulating (doseq). Bad idea?

23:04 lambdalion: with enough libraries you can basically do all your html/css/logic/etc in CL- add hunchentoot and the webserver is CL tooo- you never have to leave your coccoon ;)

23:05 chouser: lambdalion: clojurescript is two main parts. A compiler (written in JVM Clojure) which is very java-y, and a javascript library that provides persistent vector, hash-map, etc.

23:05 lambdalion: I will def look at scriptjure- am not at all familiar with it. I am fairly new to clojure so I am still figuring out which libs are which. Seems like I misunderstood what clojurescript was, even...

23:06 Did learn a bit about the compiler circa then from reading the code though, so not a loss.

23:07 yeah- I sis figure out that it was very different int intent from parenscript, which has almost the opposite philosophy

23:07 err- did fugure out

23:07 dnolen: arohner: will do, I used it briefly - I'm working on a CouchDB front-end that modeled after python-couchdb - type checked mappings.

23:08 arohner: for view definition I wanted to be able to emit JS from Clojure code w/o writing JS on multi-line strings, I don't recall the exact problem, when I have time to get back to that I will bug you.

23:10 chouser: sproust`: that doesn't sound good. reduce won't work?

23:11 sproust`: (defmacro doseq* [seq-exprs & body] `(doall (map (fn ~(first seq-exprs) ~@body) ~(second seq-exprs))))

23:11 lambdalion: I think a straightforward port from CL's parenscript can't be done in anything llike what I imagine idiomatic clojure to be...

23:12 sproust`: chouser: I just wanted to temporarily accumulate the result of my doseq's body.

23:12 chouser: rather than edit, I made a version that accumulates...

23:12 lambdalion: but I imagine something like it could be made for clojure.

23:12 cemerick: sproust`: see for?

23:13 sproust`: cemerick: of course. Reinventing the wheel. Thanks,

23:13 dnolen: lambdalion: I think you would be surprised. I didn't think I'd be able to port cl-cont from CL - uses CLOS etc. I was able to make a fairly faithful port.

23:13 lambdalion: metadata is magical thing.

23:13 ,(meta (with-meta (fn []) {:foo 'bar}))

23:13 clojurebot: {:foo bar}

23:16 lambdalion: I am following that code, but failing to follow the implication...

23:16 sproust`: When I use (pmap) instead of (map) in my program, it doesn't exit. Probably something to do with the thread-pool? Is this a known side-effect of using the p-* functions?

23:17 Basically, I have a single (pmap), when I replace it with (map) I get a clean exit from the command-line.

23:17 chouser: sproust`: you just need (shutdown-agents) when your program is all done

23:18 dnolen: lambdalion: you can store data for latter reflection on core datastructures as well as fn.

23:18 s/fn/fns

23:18 sproust`: chouser: thx.

23:18 cemerick: chouser: do you remember what the issue was with switching the pools to use daemons?

23:18 sproust`: re. Agents: is there any fundamental reason that agents aren't put in a library, and are part of the core?

23:18 * cemerick just won't let this one go, I guess :-P

23:19 chouser: cemerick: probably just programs that worked fine in the repl quitting too soon when run as scripts

23:19 cemerick: sproust`: same could be said of any of the concurrency primitives.

23:19 sproust`: Seems to me a smaller Clojure is a more portable one, and thus stuff like agents would be better segregated into a module...

23:19 Yes indeed.

23:19 dnolen: lambdalion: for example, CLOS has a cool feature where an Object can be callable as a fun. Clojure not having objects, I needed to work around this with metadata. That was the only thing I couldn't port faithfully - but there was an elegant workaround.

23:20 lambdalion: alright, well thanks- I've been reading through parenscript lately, but I guess I need to look at scriptjure and see where that stands. Thanks for the counsel.

23:20 cemerick: sproust`: There's not a lot you could slice out and make it worth your while in terms of deployment footprint, etc.

23:21 sproust`: cemerick: as per our discussion, I know that persistent DS and concurrency is the heart of the Clojure deal, but it seems to me very useful as a "better lisp" as well, and the idea of just a cleaner LISP (without even the JVM) in its own right is very appealing I think.

23:21 hiredman: sproust`: rhickey just mentioned possibly pulling in a whole message queue implementation into clojure

23:21 cemerick: chouser: I guess I don't see why an await is worse than (shutdown-agents)

23:22 lambdalion: sproiust: I agree- the concurrency bits are actually not at all the most compelling bits of Clojure, to me...

23:22 cemerick: sproust`: there's certainly no requirement that other impls carry a full boat

23:22 dnolen: lambdalion: np. and I meant "Clojure not having objects-like-things at the time". Things have changed in 2 years.

23:22 cemerick: hiredman: That seems absolutely crazy to me.

23:22 hiredman: a little

23:23 lambdalion: dnolen: ah, I see- well I wasn't thinking about OO there- frankly I do OO only under duress ;)

23:23 cemerick: I can see the maven shade exclusion config already :-/

23:23 hiredman: but since I like queues, and have hornetq setup already..

23:23 sproust`: cemerick: it's rather neat if a language has had some thought about dependencies. For example, I like how in Python regular expressions are entirely segregated to a single module (not part of the language at all).

23:23 chouser: cemerick: Yeah, I don't remember how it was decided to switch. I'm sure it's in the logs, IRC or ggroup. :-P

23:23 lambdalion: CLOS is more than OO though... at least the way that term is usually used.

23:23 chouser: sproust`: except regex in python is painful. but other than that I agree with you.

23:24 cemerick: hiredman: feh. If we're to go by usage, then clojure should have jetty bolted in by now.

23:24 sproust`: chouser: why is it painful? Because of the absence of an aif-like idiom?

23:24 mo = re.match(... ) ; if mo: ...

23:24 lambdalion: Hmm- I think Python is a bit schizophrenic in this regard.

23:25 hiredman: cemerick: :)

23:25 * cemerick seems to get more curmudgeonly by the month or something

23:25 chouser: sproust`: no literal regex syntax means more words, and then the lib in messy as far as which methods take regex flags and which don't.

23:25 lambdalion: It falls somewhere between a good shell language and a good general purpose language a lot of the time.

23:26 arohner: cemerick: I thought the definition of curmudgeony was monotonic increasing?

23:26 sproust`: lambdalion: Well now you have Jython, PyPy, IronPython, Stackless, and a bunch of others... if clojure.core becomes huge, you can almost be guaranteed that ports (e.g. LLVM one day?) will result in incompatible programs. But maybe that's not part of Rich's plan. I DK.

23:26 cemerick: arohner: I'm on a log trend of late, it seems.

23:26 sproust`: Every host will have a different mix of features. js is the penultimate example guaranteeing that.

23:27 sproust`: Urg.

23:27 lambdalion: Sure- but at the moment my choices are c++ and CPython, at work, because Python is used as an embedded language in the program i want to extend

23:27 chouser: though now with workers, I wonder how much of the concurrency stuff we can get

23:27 cemerick: or down to a more fine-grained level, ClojureCLR's regex impl won't be identical to the JVM's.

23:27 chouser: lambdalion: compile clojure to python!

23:27 any day now

23:28 lambdalion: hmm- well Python would work OK for us except that we just can;t get enough speed here-

23:28 sproust`: chouser: with Python's

23:28 hiredman: there is a lisp -> python opcodes already

23:28 chouser: compile clojure to C++!

23:28 lambdalion: our algorithm takes about a second to run in Python...

23:28 sproust`: chouser: with Python's AST you could go straight to bytecode.

23:29 lambdalion: it must ecentually run in about 20=40 milliseconds

23:29 err- 20-40

23:29 cemerick: lambdalion: tried psyco?

23:29 (which is semi-deprecated these days, IIRC? Still works, last I knew)

23:29 lambdalion: I must say though that if we had tried to develop it in C from the start we would bever have developed it.

23:29 *never

23:30 sproust`: lambdalion: when I have this (awfully common) problem with Python I just profile and replace just the inner loop in C. Usually good enough.

23:30 lambdalion: Yep- I agree.

23:30 chouser: bedtime. have fun, all.

23:30 sproust`: Nighty night.

23:30 lambdalion: In pour case performance is so important that we wil rewrite in C entirely...

23:31 hiredman: ugh, can't you just generate llvm ir and then compile that?

23:31 lambdalion: But my last two months would have been a lot easier if python could be made to do reasonably fast FP calcs without involving a C compiler.

23:32 sproust`: lambdalion: What kind of problem are you solving?

23:33 lambdalion: hmm- a few parts, but basically automatic deformation of meshes bound to spline curves for people doing 3d character animation.

23:34 It can't be too fast, and will never be fast enough....

23:34 the python is for prototyping, but...

23:35 it wpul be nice if it were only 10 times as slow as our optimized code will eventualy be, instead of hundreds of times as slow

23:35 sproust`: /?

23:35 clojurebot: make a note of http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php it is yet another article about picking c or c++ for performance being naive

23:36 lambdalion: on the other hand developing the algorithm in C++ would be even worse.

23:36 hiredman: clojurebot: botsnack

23:36 clojurebot: thanks; that was delicious. (nom nom nom)

23:36 sproust`: lambdalion: is this for a post house?

23:36 lambdalion: well we have two choices- cPython or c++

23:37 it is meant for a commercial Maya plugin

23:37 * sproust` mesmerized by the clojurebot's actions.

23:37 lambdalion: I imagine that clojure 1.3 or 1.4 might be close to fast enough- that is Java might be close.

23:39 but we wouldn;t be able to use it without undue work...

23:39 the lot of plugin developers is living with the dicisions of the software you write plugins for.

23:39 *decisions

23:41 cemerick: lambdalion: IMO, compiling clojure down to C via chicken or gambit scheme is probably not stupendously hard. Certainly easier than C++, I'd think. It'd be a fun project for you. ;-)

23:44 lambdalion: hmm- to be honest, compiling clojure to C had not even occurred to me...

23:47 I'm not sure how I would go about that, actually...

23:47 hiredman: lambdalion: http://gist.github.com/223246

23:47 cemerick: lambdalion: well, you don't have to worry about compiling to C, just with translating to scheme

23:48 lambdalion: I guess if the scheme compiler compiles to C you just need to compile Clojure to scheme, but...

23:48 * hiredman wonders where that code went

23:48 hiredman: the previous gist http://gist.github.com/222974

23:48 lambdalion: if the point of using C is performance you would need to have quite a bit of control over _two_ stages of compilation.

23:51 The point here is not to be able to use a C compiler to produce an executable or library- it is to hand-code ridiculously fast C... I know modern C compilers are smart, but there are limits.

23:51 Gotta say though that that clojure->scheme->->C idea is very interesting...

23:52 maybe not applicable for what I am doing now, but...

23:55 dnolen: clojure->javascript->V8 ?

23:56 lambdalion: Actually I do recall that my favorite programming assignment in school was one that asked us to write a scheme program that translated a subset of scheme to Pascal...

23:56 first time I was introduced to the idea of functions that returned functions...

23:58 Not sure about the V8 stage though...

23:59 sproust`: If you're gonna bother writing out Scheme, why bother with Clojure in the first place.

Logging service provided by n01se.net