2010-09-29
| 00:16 | technomancy | time to find a new name for pods: http://www.theregister.co.uk/2010/09/24/apple_pod_row/ |
| 00:20 | amalloy | technomancy: they're just jealous that facebook owns the word Book |
| 00: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 |
| 00:23 | bhenry | show us |
| 00:23 | bhenry | it should work |
| 00:24 | jk_ | (defn foo [{major :major minor :minor} m] (str major "." minor)) |
| 00:25 | jk_ | call it like: (foo (hash-map :major 8 :minor 13)) gives wrong number of args |
| 00:25 | lancepantz | the m is implicity |
| 00:25 | technomancy | jk_: where's m coming from? |
| 00:26 | lancepantz | s/y// |
| 00:26 | sexpbot | <lancepantz> the m is implicit |
| 00:27 | jk_ | technomancy: m isn't the argument map that i pass on the call? |
| 00:27 | jk_ | (defn foo [m] (let [{major :major minor :minor} m] (str major "." minor))) that works |
| 00: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 |
| 00:28 | technomancy | right, because in that case m is the argument to foo |
| 00:28 | jk_ | technomancy: doh! sorry. i see |
| 00:28 | jk_ | i misunderstood the syntax |
| 00:28 | jk_ | i see now |
| 00: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 |
| 00:29 | technomancy | whereas in defn, the value is provided at the call site |
| 00:29 | jk_ | technomancy: got it. glad the clojure community puts up well with newbies :) |
| 00:29 | technomancy | everyone starts at the beginning |
| 00: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) |
| 00: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 |
| 00:33 | jk_ | amalloy: i mean foo() doesn't actually know what's in it. i was just doing a test, learning about destructuring |
| 00: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 :) |
| 00: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 |
| 00:43 | amalloy | btw jk_, is there a reason you're using (hash-map :a 1 :b 2) instead of just {:a 1 :b 2}? |
| 00:44 | jk_ | amalloy: nope. just didn't immediately see the doc for creating a hashmap literal so i used the function call |
| 00:44 | amalloy | well, there ya go |
| 00:44 | jk_ | :) |
| 00:51 | technomancy | stubs! http://github.com/technomancy/rodney-leonard-stubbs |
| 00:51 | technomancy | gotta love projects for which the readme is significantly longer than the code |
| 00:52 | technomancy | "The Man with the Blood on his Hands" |
| 00: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) |
| 01: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... |
| 01: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 |
| 01:10 | technomancy | pet peeve: you mean Common Lisp? |
| 01:10 | amalloy | technomancy: i actually even meant to type CL! |
| 01:11 | amalloy | but then some sort of demon got hold of my fingers or something |
| 01:11 | technomancy | well it doesn't help that CL isn't case-sensitive |
| 01:11 | technomancy | (proper nouns at and all) |
| 01:12 | jk_ | amalloy: i only read the theory on lisp and read some code but never actually tried writing it until clojure |
| 01:13 | amalloy | technomancy: sorry, can't parse that last message |
| 01: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. |
| 01:15 | jk_ | technomancy: you mean "Lisp" is synonymous with CL to the community? |
| 01:16 | hiredman | well, to the cl community |
| 01: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. |
| 01:20 | hiredman | or just refer to it as that thing those guys did that one time |
| 01:21 | jk_ | lol |
| 01:27 | technomancy | "Common Lisp: some guys did it once, and so can you." |
| 01:39 | replaca_ | technomancy: you make me feel like a grandpa! |
| 01:43 | amalloy | jk_: what editor are you using, if i may ask? |
| 01:43 | jk_ | counterclockwise on eclipse |
| 01:44 | amalloy | how's that working? i tried it a few months ago but things didn't seem to work very well |
| 01:44 | jk_ | amalloy: just because i already knew eclipse and didn't feel like learning emacs (being a vi guy) |
| 01:44 | amalloy | heh. i understand there are decent vim modes for clojure, but i confess i saw this as an opportunity to learn emacs |
| 01: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 |
| 01:45 | jk_ | amalloy: that hangs teh entire eclipse environmetn |
| 01:45 | amalloy | weird. and a lot of things are lazy, so this must happen a lot? |
| 01:46 | jk_ | amalloy: well normally i'm using them somehow rather than just typing random things into the repl in eclipse |
| 01:46 | amalloy | you'd be surprised how much you can learn just typing stuff into the repl to see what happens |
| 01:47 | jk_ | amalloy: right. so i do that at the command line normally so i don't run into that ccw bug :) |
| 01:47 | amalloy | aha |
| 01: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 |
| 01:49 | jk_ | amalloy: i'm sure it's vastly inferior to using emacs but oh well :) |
| 01:49 | jk_ | amalloy: ccw is actually very nice when it doesn't hang :O |
| 01: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 |
| 01:50 | raek | you mean Escape-Meta-Alt-Control-Shift? |
| 01:52 | amalloy | raek: i saw a picture of a space cadet keyboard for the first time today. that's a lot of modifier keys |
| 01:54 | amalloy | i knew about hyper/super/meta/alt/shift/control, but i didn't realize they also had Top/Front |
| 02:16 | replaca_ | tolsen: if you're there. Autodoc is fixed now. |
| 02:58 | LauJensen | Good morning all |
| 03:02 | amalloy | heh. when LauJensen gets here, that's how i know i ought to be in bed |
| 03:02 | LauJensen | :[ |
| 03: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})}) |
| 03:08 | tobiasraeder | where getter is the function that i want to evalutate before passing it into the macro |
| 03:14 | amalloy | tobiasraeder: unless i'm misunderstanding you, you can't - macros happen at compile time |
| 03:15 | tobiasraeder | @amalloy makes sense. if i replaced the function with a macro that should do the trick tho? |
| 03:15 | amalloy | is the data all known at compile time? |
| 03:16 | tobiasraeder | yeah it is |
| 03:16 | tobiasraeder | and getter should just generate a vector with some symbols/class names |
| 03:16 | amalloy | then there's certainly *a* way to do it. i actually wouldn't suggest making getter into a macro |
| 03: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 |
| 03: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 |
| 03:17 | amalloy | one sec and i'll put together a gist |
| 03:18 | tobiasraeder | thank you :) |
| 03:23 | amalloy | tobiasraeder: http://gist.github.com/602399 |
| 03:24 | amalloy | not actually working, but you can see what i'm getting at, i hope? |
| 03:24 | tobiasraeder | yeah i see |
| 03:24 | tobiasraeder | and can i pass the make-gets into gen-interface? |
| 03:26 | amalloy | right, because it will expand into real code, still at compile time, which gen-interface will understand |
| 03:26 | tobiasraeder | alright |
| 03:26 | tobiasraeder | ill try that in a minute. thank you very much |
| 03:29 | amalloy | tobiasraeder: a version that actually works, in that it defines some variables: http://gist.github.com/602404 |
| 03:30 | amalloy | honestly i've written (defmacro foo [& args] `(do ~@(apply map somefn args))) enough times that i ought to make a macro for it :P |
| 03:30 | tobiasraeder | hehe |
| 03:31 | tobiasraeder | but i do have to def all the variables i want to pass to the macro this way? |
| 03:31 | tobiasraeder | maybe im just getting it wrong again tho |
| 03:31 | amalloy | not sure what you mean? |
| 03:32 | amalloy | 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 |
| 03:32 | shachaf | amalloy: What's the point of doing that as a macro? |
| 03:32 | tobiasraeder | ah okay |
| 03:33 | amalloy | scgilardi: nothing really, for a simple def |
| 03:33 | amalloy | 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 |
| 03:33 | shachaf | Oh, I missed some context. |
| 03:35 | tobiasraeder | actually i want to define one interface with x times make-getter and make-setter |
| 03: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 |
| 03:37 | amalloy | tobiasraeder: was that asking for more help, or just explaining to shachaf? |
| 03:37 | tobiasraeder | i wanted to start to explain it |
| 03:43 | tobiasraeder | @amalloy would you mind taking a look at http://gist.github.com/602418 ? |
| 03:43 | tobiasraeder | it evaluates, but doesn't create any new functions for the interface. maybe i'm just overlooking something |
| 03:44 | amalloy | well, now you don't have any macros at all. you still need one macro for the top-level entry point |
| 03:45 | tobiasraeder | well gen-interface is a macro |
| 03:45 | amalloy | something like: (defmacro make-gettable-iface [name type] `(gen-interface ...~(make-getter type))) |
| 03:46 | amalloy | tobiasraeder: right! and that means it won't evaluate make-getter, because that's a run-time function that it can't know about |
| 03:47 | amalloy | but if *you* write the outermost macro, you can evaluate whatever parts you want before passing it down to the "dumb" gen-interface |
| 03:47 | tobiasraeder | ah now i think i finally got it |
| 03:47 | amalloy | btw is there a reason you're using (vector), (list), and (hash-map) instead of [] '() and {}? |
| 03:48 | tobiasraeder | not really guess i should replace them |
| 03: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 |
| 03:55 | tobiasraeder | actually i think im fine with the literals. just got really mixed up in my head with the macro/gen-interface stuff |
| 03:56 | tobiasraeder | and yay it is working now |
| 03:56 | amalloy | wooo |
| 03:56 | tobiasraeder | i got an interface with one getter now, yay me |
| 03:56 | amalloy | yes, macros are mind-bending no matter how much you do them |
| 03:56 | tobiasraeder | lol |
| 04:00 | amalloy | tobiasraeder: okay, just got my version working. compare notes? |
| 04:01 | tobiasraeder | @amalloy sure |
| 04:01 | Kaali | How can I import two Java classes which has the same name? |
| 04:01 | amalloy | Kaali: import one of them, and refer to the other with a fully-qualified name |
| 04:02 | tobiasraeder | doesnt import allow :as? |
| 04:02 | tobiasraeder | @amalloy http://gist.github.com/602418 |
| 04:02 | Kaali | Doesn't seem like import allows :as |
| 04:02 | amalloy | i don't think it does, but i could be wrong |
| 04:03 | Kaali | amalloy: How do I refer to it, as I can't import it at all. |
| 04:03 | amalloy | java.util.Date |
| 04:03 | amalloy | don't import it |
| 04:03 | tobiasraeder | yeah my bad. |
| 04:03 | amalloy | you don't have to import, just refer to it with its long name |
| 04:04 | Kaali | Thanks, just a foolish mistake. I tried to use java.lang.Date, not .util. |
| 04:04 | Kaali | I wondered why other classes worked with full name and this one didn't. |
| 04:04 | amalloy | tobiasraeder: http://gist.github.com/602441 |
| 04:05 | amalloy | heh. and i guessed right. it's always Date :) |
| 04:05 | Kaali | Yup =) |
| 04:06 | tobiasraeder | @amalloy yours is obviously a bit further down the road and pretty much exactly what i was looking for ;) |
| 04:06 | amalloy | good! steal it, but obviously learn from it too |
| 04:06 | Kaali | Curses, I just rewrote a function which uses Date, and I referred it as java.lang.Date... again! |
| 04:06 | tobiasraeder | yeah i think i just learned quite a bit. Thanks alot. |
| 04: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 |
| 04:08 | amalloy | oog, LauJensen got here an hour ago and i'm still up. bedtime for me. have fun, Kaali & tobiasraeder |
| 04:09 | tobiasraeder | @amalloy thanks alot for the help and sleep well. |
| 04:09 | LauJensen | Good night :) |
| 04:09 | Kaali | Thanks again amalloy |
| 05:08 | akuzi | anyone know when the keynote/sessions start at clojure-conj on Oct 22. i'm thinking of flying down in the morning. |
| 05:12 | xkb | no idea yet, but my ticket is "in the bag" :) |
| 05:12 | xkb | looking forward to it |
| 05:16 | LauJensen | akuzi: Theres a contact email on the website |
| 05:17 | xkb | What's Durham like anyway? |
| 05:20 | LauJensen | xkb: Its Durable, but with ham |
| 05:21 | xkb | hehe |
| 05:21 | xkb | smells sweet ;) |
| 05:23 | esj | I'm deeply tempted to go over for it |
| 05:23 | esj | akuzi: the site says 9am |
| 05:25 | akuzi | oh really?... thanks.. |
| 06:48 | bobo_ | didnt someone in here talk about doing an etl in clojure? |
| 07:01 | cemerick | etl? |
| 07:01 | cemerick | extract transform load? |
| 07:01 | bobo_ | yeh |
| 07:01 | bobo_ | data warehouse stuff |
| 07:01 | bobo_ | i found some utils att github, so i cant be alone in the thoughts atleast |
| 07:01 | cemerick | Lots of that going on, though people are quiet about it for the most part. |
| 07:02 | cemerick | Not really the sort of thing that the open source folk are big into :-) |
| 07:02 | bobo_ | indeed |
| 07:02 | cemerick | web framework v396 is *much* higher priority ;-) |
| 07:02 | bobo_ | hehe, we need more frameworks |
| 07:02 | bobo_ | and fartapps |
| 07:02 | cemerick | heh |
| 07:03 | LauJensen | haha |
| 07:03 | cemerick | A friend of mine is using clojure for etl of medical data. Gnarly stuff. |
| 07:03 | cemerick | Had to write the parsers and such from scratch, of course. |
| 07:03 | bobo_ | i have everything in databases atleast |
| 07:04 | cemerick | lucky |
| 07:04 | bobo_ | yes, if it where fever then about 100 databases it would be awesome =) |
| 07: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 |
| 07:06 | bobo_ | fun fun :-) |
| 07: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 |
| 07:09 | cemerick | LauJensen: lucky you :-) |
| 07:10 | cemerick | Apparently many such files have different delimiters depending on which sub-subfield you're in. |
| 07:10 | cemerick | Making a regex impossible, of course. |
| 07:10 | cemerick | Thank goodness, I've never had to do such stuff myself. |
| 08:09 | cemerick | chouser: ping |
| 08:17 | AWizzArd | rhickey: is (biginteger 13178456923875639284562345789) supposed to throw #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for long: 13178456923875639284562345789> ? |
| 08:18 | @rhickey | AWizzArd: 13178456923875639284562345789 is not a valid numeric literal |
| 08:18 | @rhickey | er, no |
| 08:18 | AWizzArd | (biginteger 13178456923875639284562345789N) also throws it. |
| 08:19 | AWizzArd | or evaluating that number and then followed by (biginteger *1) |
| 08:19 | @rhickey | right, it's that there isn't a case for bigint |
| 08:19 | AWizzArd | I tried it with the most recent clojure.jar |
| 08:20 | @rhickey | AWizzArd: needs fixing, please enter a report, thanks |
| 08:20 | AWizzArd | k |
| 08:20 | @rhickey | AWizzArd: you know there is bigint now too? |
| 08:23 | AWizzArd | rhickey: yes, I use both of them |
| 08:24 | AWizzArd | 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) |
| 08:24 | AWizzArd | That's where I noticed the current issue #447. |
| 08:31 | chouser | cemerick: ack |
| 08:31 | cemerick | Morning :-) |
| 08:31 | chouser | Good morning sir |
| 08:31 | chouser | I dreamt of clojure conj |
| 08:31 | cemerick | chouser: I'm wondering about whether the "final value" of the code sent should really be privileged. |
| 08:32 | chouser | cemerick: ok |
| 08: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* |
| 08:32 | chouser | oh, not an input I had considered. |
| 08:33 | cemerick | right; the reader is not in control of the scope of code being eval'ed in this world |
| 08:33 | cemerick | Or, it is, but the broader scope is client-defined. |
| 08:33 | chouser | hm, and what about writes to *out* that happen in other threads after the last expr's return value? |
| 08: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. |
| 08:35 | cemerick | All of the other hosted repls have the same issue AFIAK -- swank, encojure, and ccw. |
| 08:35 | chouser | cemerick: I'm hopeful that whatever rhickey has cooking to improve on binding will allow handling of that kind of situation. |
| 08:36 | chouser | but until then, saying that *out*/*err* from other threads gets lost or logged elsewhere or something may be the only reasonable solution. |
| 08:36 | @rhickey | what situation? |
| 08: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. |
| 08:36 | chouser | rhickey: (magic-binding [*out* client-stream] (send-off (agent 42) prn)) |
| 08:37 | cemerick | scary. |
| 08:37 | @rhickey | chouser: well, it's not going to make multithreaded access to streams any better :) |
| 08:37 | cemerick | IMO, anyway. |
| 08: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? |
| 08:38 | @rhickey | but it might at least make the binding visible to the agent |
| 08:38 | chouser | rhickey: that's all I mean. |
| 08: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. |
| 08:43 | @rhickey | anyone here use FishEye? It looks like that is the best way to get Kira/Git integration |
| 08:43 | @rhickey | er Kira/Git |
| 08:43 | @rhickey | Jira/Git |
| 08:43 | cemerick | rhickey: Yeah, it works well. Somewhat more heavyweight in the UI department than I'd like, but it gets the job done. |
| 08:44 | @rhickey | cemerick: have you connected it to git? |
| 08:44 | cemerick | rhickey: yup |
| 08: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 |
| 08:46 | @rhickey | cemerick: great, also, is it a single user management db for Confluence/Jira/FishEye? |
| 08: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. |
| 08:46 | cemerick | rhickey: it's called Crowd, I think. Never used that. |
| 08:46 | chouser | we've since moved the git repo to github:fi |
| 08:46 | cemerick | I presume there's LDAP support floating around everywhere though. |
| 08:46 | esj | chouser: i set it up recently, almost zero effort |
| 08:46 | cemerick | chouser: damn: deep pockets over there! :-P |
| 08:48 | @rhickey | cemerick: wow, without crowd you have to admin users separately for Jira, FishEye and Confluence? yikes |
| 08:48 | esj | nothing like making a market for your own products. |
| 08:48 | @rhickey | I could see something like Crowd for connecting externally |
| 08: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. :-) |
| 08:49 | cemerick | rhickey: apparently yes, though there's LDAP |
| 08:49 | cemerick | We've never been large enough to care about the user admin "burden" |
| 08:50 | cemerick | chouser: Really. That's a surprising statement. If i shelled out that kind of cash, I'd be expecting perfection. |
| 08:51 | andyfingerhut | Expensive software can be and often is bug-ridden. But sometimes you get decent support. |
| 08: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. |
| 08:52 | chouser | I also think we're using it more heavily than most of the other github:fi'ers |
| 08:52 | @rhickey | no free open source license for crowd |
| 08:53 | LauJensen | I must say, Gitosis has never left me wanting when it comes to managing Git repos |
| 08:53 | @rhickey | atlassian moving strongly towards Mercurial |
| 08:53 | cemerick | rhickey: I have to think they'd accommodate you if you shot an email their way |
| 08:53 | chouser | LauJensen: hosted by them or you? |
| 08:54 | LauJensen | chouser: them? I host my own repos, manage them with Gitosis |
| 08:54 | @rhickey | cemerick: I simply wonder how the tools work together at all with separate user dbs |
| 08:54 | cemerick | chouser: gitosis is a tool, not a service |
| 08:54 | chouser | oh |
| 08:54 | cemerick | maybe you're thinking of gitorious |
| 08:54 | chouser | oh, indeed |
| 08:54 | cemerick | which is simply *impossible* to install locally |
| 08:54 | abrenk | rhickey: Central user management should be possible without Crowd using just LDAP, Crowd just adds single-sign on, I think. |
| 08:56 | @rhickey | abrenk: makes sense |
| 08: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. |
| 08:58 | @rhickey | cemerick: they are adopting Mercurial internally, so I expect that will get more attention |
| 08:59 | LauJensen | cemerick: silly? |
| 08:59 | cemerick | as long as git support doesn't wither on the vine or otherwise lag significantly, I'll be happy |
| 09:00 | cemerick | LauJensen: e.g. trying to funnel users of their tools into hosting via bitbucket/hg by letting support for other SCMs bit-rot, etc. |
| 09:01 | LauJensen | I wouldn't worry too much about that |
| 09:02 | cemerick | Companies do funny things when they get funded, start acquiring others, etc. |
| 09:03 | AWizzArd | What does this argument list from Java mean? 'public <T> T foo (Class<T> type)' specifically this 'Class<T> type' thing |
| 09:04 | LauJensen | Where is that project which found example-code of any clojure-fn you could think of? |
| 09:04 | clojurebot | project euler is http://ProjectEuler.net |
| 09:05 | chouser | LauJensen: http://getclojure.org:8080/examples/zipmap |
| 09:05 | LauJensen | thanks |
| 09:08 | AWizzArd | Aah, BitBucket was bought by Atlassian, cool :) |
| 09:10 | AWizzArd | So maybe BitBucket users will soon get support for Jira, FishEye and such? Mama mia :) |
| 09:10 | @rhickey | http://confluence.atlassian.com/display/DOC/Delegate+user+management+to+use+JIRA+logins |
| 09:10 | AWizzArd | It's a good day :) |
| 09:10 | @rhickey | http://www.atlassian.com/summit/2010/presentations/development-speed/dvcs-systems-in-the-enterprise-git-mercurial.jsp |
| 09:13 | AWizzArd | Wow, unlimited private repos now |
| 09:14 | LauJensen | Hopefully Github will offer something similar :) |
| 09: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 |
| 09:20 | shoover | rhickey: cool |
| 09:20 | LauJensen | Assembla is leaving something to be desired? |
| 09: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. |
| 09:20 | @rhickey | abrenk: it seems like LDAP only does the logins, not groups etc |
| 09:21 | abrenk | rhickey: There are groups in LDAP. Although not all tools support looking them up. |
| 09:21 | @rhickey | abrenk: afaict Jira/Confluence use their own groups even with LDAP, but Confluence can use Jira's |
| 09:22 | shoover | the atlassian presentation is worth it for slide 10 |
| 09:22 | AWizzArd | Everyone who not joins to BitBucket really misses a lot of dev comfort ;) |
| 09:22 | AWizzArd | -to |
| 09:22 | abrenk | rhickey: at least Confluence supports LDAP groups: http://confluence.atlassian.com/display/DOC/LDAP+User+Management |
| 09:22 | bartj | silly question, distinguish the use-cases between "for" and "map" |
| 09:23 | bartj | , (for [i (range 10)] (* i i)) |
| 09:23 | clojurebot | (0 1 4 9 16 25 36 49 64 81) |
| 09:23 | AWizzArd | One can losslessly convert a git repo into a hg repo (and back). |
| 09:23 | bartj | , (map #(* % %) (range 10)) |
| 09:23 | clojurebot | (0 1 4 9 16 25 36 49 64 81) |
| 09:23 | bartj | same result :) |
| 09:23 | @rhickey | abrenk: then it's Jira that doesn't |
| 09:23 | no_mind | atlassian is lanning to buy bit bucket |
| 09:23 | AWizzArd | no_mind: the BB website is already updated. |
| 09:23 | AWizzArd | Atlassian logos everywhere. |
| 09:23 | no_mind | oh kool |
| 09:23 | no_mind | so they already bought it |
| 09:23 | AWizzArd | It is so great, I can now have a million private repos. |
| 09:24 | LauJensen | AWizzArd: yes! One for each line of code! |
| 09:24 | AWizzArd | LauJensen: exactly what I thought! |
| 09:24 | LauJensen | AWizzArd: We can make a chat program which logs each line in a repo of its own, like twitter! |
| 09:24 | AWizzArd | twitbucket.org |
| 09:24 | abrenk | rhickey: that's a pity |
| 09:25 | bartj | ah, never mind |
| 09:27 | chouser | bartj: right, there is a fair number of cases that work approximately as well in 'for' and in 'map' |
| 09:28 | bartj | chouser, I was just thrown aback, they could be used inter-changeably sometimes |
| 09:28 | bartj | is there a *light-bulb* moment I am missing here :) |
| 09: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. |
| 09:30 | andyfingerhut | bartj: for can do nested "loops", whereas that is not as trivial using map. |
| 09: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. |
| 09:33 | @rhickey | abrenk: yes, I just want to do groups once, I don't care where |
| 09: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. |
| 09:37 | @rhickey | abrenk: Confuelnce using Jira users/groups might be sufficient |
| 09:37 | abrenk | because that's the "just one vendor" scenario... |
| 09:38 | @rhickey | abrenk: yes |
| 09:38 | abrenk | ...the pain then starts if you want to integrate another tool. |
| 09:38 | @rhickey | abrenk: we have limited resources to apply to this |
| 09:39 | @rhickey | abrenk: got a recommendation for a free (for open source projects at least) ldap server? |
| 09:40 | abrenk | rhickey: I use OpenLDAP |
| 09:41 | abrenk | OpenLDAP was there in the beginning and I didn't have the resources to look at the alternatives that came up in recent years. |
| 09: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)] |
| 09:41 | msappler | (and |
| 09:41 | msappler | (< (Math/abs (- xlight x)) (+ half-w max-range)) |
| 09:41 | msappler | (< (Math/abs (- ylight y)) (+ half-h max-range)))) |
| 09:44 | abrenk | it's like managing apache: just config files, no fancy web interface |
| 09:44 | LauJensen | msappler: [[xlight ylight x y] (map float [xlight ylight x y]) ? |
| 09:45 | msappler | oh thanks |
| 09:46 | msappler | why didnt i think of this simple solution? 0_o |
| 09: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. |
| 09:46 | chouser | it won't. |
| 09: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 | AWizzArd | 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: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 | cemerick | 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: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 | cemerick | Anyway, getting it done isn't a big deal -- just a shame that it's not baked in already. |
| 10:47 | cemerick | 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 | abrenk | 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 | chouser | 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 | 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 | abrenk | 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 | cemerick | 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 | Raynes | $mail Raynes Message |
| 10:58 | sexpbot | Message saved. |
| 10:58 | Raynes | |
| 10:58 | Raynes | 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 | @rhickey | (macroexpand '(condp = x 42 43)) |
| 10:59 | @rhickey | (let* [pred__79 = expr__80 x] (if (pred__79 42 expr__80) 43 (throw ...))) |
| 10:59 | @rhickey | but could be: |
| 10:59 | @rhickey | (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 | cemerick | 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 | phenom_ | *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 | cemerick | neotyk: hrm, nope |
| 11:02 | cemerick | 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 | 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 | AWizzArd | 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 | 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 | cemerick | 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 | @rhickey | 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 | cemerick | 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 | ohpauleez | 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 | @rhickey | 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 | @rhickey | 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 | KirinDave | 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 | cemerick | s/a name/the name |
| 11:29 | cemerick | 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 | KirinDave | 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 | chouser | turns out XML has weaknesses as a transport protocol. |
| 11:31 | chouser | 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 | KirinDave | 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 | 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 | KirinDave | 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 | @rhickey | please use a standard protocol like websockets or stomp |
| 11:36 | @rhickey | please do not use json, it is inadequate, and you can always downgrade to json |
| 11:36 | @rhickey | but representing richer things in json means more work in reconstructing them than a simple js read for clojure data |
| 11:36 | @rhickey | reader |
| 11:37 | @rhickey | 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 | ohpauleez | ? |
| 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 | cemerick | KirinDave: You've seen http://github.com/ordnungswidrig/compojure-rest ? |
| 11:38 | KirinDave | Yes. |
| 11:38 | KirinDave | 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 | KirinDave | cemerick: I was looking for some advice tho |
| 11:42 | KirinDave | So I've got this implemented as a protocol with a default hash: http://bitbucket.org/justin/webmachine/wiki/WebmachineResources |
| 11:42 | KirinDave | And I'll start building functions and macros to make construction of such a responder trivial. |
| 11:43 | KirinDave | (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 | KirinDave | 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 | KirinDave | 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 | KirinDave | 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 | cemerick | 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 | KirinDave | 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 | KirinDave | 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 | KirinDave | Yeah |
| 11:49 | KirinDave | 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 | KirinDave | 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 | KirinDave | 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 | KirinDave | 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 | chouser | 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 | chouser | 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 | KirinDave | I was curious what ever happened to repl-utils that made show such a hassle to get into your namespace |
| 11:59 | KirinDave | Err, not yours |
| 11:59 | KirinDave | 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 | ohpauleez | 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 | amalloy | 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 | ohpauleez | or just deprecated? |
| 12:18 | ohpauleez | 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 | chouser | 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 | ohpauleez | 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 | ohpauleez | 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 | anonymouse89 | 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 | jlr | 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 | jlr | You get the final version with it of course lol |
| 13:32 | jlr | They email you each time it's been updated. |
| 13:34 | dakrone | jlr, gotcha, thanks |
| 13:34 | dakrone | 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 | ztellman | 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 | cemerick | 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 | sproust | (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 | chouser | cemerick: custom headers seem widely supported and would suffice for id, timeout, ns, and status |
| 13:47 | chouser | cemerick: add a bodytype to indicate if the payload is code (in a request) or out/err/value (in a reply) |
| 13:48 | chouser | this buys you well-defined transport and quoting rules, along with code that implements them including over raw or web-socket |
| 13:49 | chouser | 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 | cemerick | 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 | cemerick | 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 | cemerick | 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 | chouser | 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 | cemerick | I've been hermeneutic-ing all day now |
| 14:05 | cemerick | :-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 | cemerick | :-) |
| 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 | cemerick | kotarak: Don't worry. I'm not sold on the complexification, at least not yet. |
| 14:12 | cemerick | 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 | cemerick | 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 | kotarak | 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 | cemerick | (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 | @rhickey | http is unsuitably disconnected |
| 14:21 | @rhickey | we don't want rpc, we want async messages |
| 14:21 | cemerick | another reason why I dropped it :-) |
| 14:21 | cemerick | 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 | @rhickey | 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 | cemerick | rhickey: I think kotarak and technomancy might disagree with that. |
| 14:26 | cemerick | (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 | @rhickey | 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 | @rhickey | custom comm protocols stink |
| 14:29 | @rhickey | however simple |
| 14:29 | @rhickey | 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 | @rhickey | 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 | cemerick | 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 | @rhickey | 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 | dnolen | 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 | 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 | @rhickey | so, we're basically afraind that elisp users, who have embraced the complexity of swank, will balk at stomp? |
| 14:43 | @rhickey | 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 | dnolen | 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 | cmiles74 | 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 | ztellman | 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 | chouser | 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 | ztellman | 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 | dnolen | 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 | cemerick | 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 | @rhickey | 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 | 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 | @rhickey | 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 | cemerick | 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 | @rhickey | 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 | hugod | 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 | cemerick | 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 | cemerick | 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 | @rhickey | 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 | @rhickey | 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 | @rhickey | and I think stomp in clojure sans deps is very tractable. ditto elisp |
| 15:26 | @rhickey | 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 | @rhickey | going client -> proxy -> client instead of repl server == stomp server is just a forward-looking way of implementing |
| 15:33 | @rhickey | 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 | @rhickey | 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 | hiredman | if I recall it was a pain to get matching jars of hornetq and netty |
| 15:35 | hiredman | and hornetq only had javadocs up for a released version that wasn't in maven yet |
| 15:35 | hiredman | 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 | hiredman | rhickey: but to pull it in via project.clj |
| 15:36 | hiredman | which I guess if it comes with clojure it's no big deal |
| 15:36 | @rhickey | hiredman: oh, that |
| 15:37 | @rhickey | :) |
| 15:37 | cemerick | goodness, hopefully optional |
| 15:37 | cemerick | 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:41 | @rhickey | cemerick: did that |
| 15:43 | @rhickey | 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 | @rhickey | 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 | @rhickey | 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 | kotarak | 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 | kotarak | 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 | @rhickey | 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 | kotarak | would make things a hell easier... |
| 15:51 | chouser | kotarak: the problem is that repls aren't really transactional at all |
| 15:52 | chouser | 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 | @rhickey | 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 | chouser | 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 | kotarak | 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 | @rhickey | 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 | @rhickey | 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 | @rhickey | right |
| 15:59 | chouser | good |
| 15:59 | @rhickey | I'm finding this very clean compared to repls over sockets |
| 16:00 | @rhickey | 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 | @rhickey | 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 | @rhickey | dmiller2718: shoot |
| 16:04 | @rhickey | actually, I have to run, bbl |
| 16:05 | @rhickey | 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 | ninjudd | 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 | chouser | 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 | ztellman | should each client have to ACK every line from *out*? |
| 16:13 | ztellman | 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 | ztellman | 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 | ztellman | 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 | chouser | 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 | ztellman | 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 | ninjudd | 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 | kotarak | a given thread might choose to override the one it got from its parent |
| 16:25 | kotarak | 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 | ztellman | 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 | kotarak | 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 | KirinDave | http://idisk.me.com/dfayram/Public/Pictures/Skitch/This_Morning_s_Git_Protocol_Outage_-_GitHub-20100929-132219.png |
| 16:27 | KirinDave | 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 | kotarak | lpetit: not using *in* means escape hell |
| 16:29 | ztellman | kotarak: cake seems to use a process-per-project approach |
| 16:29 | ztellman | 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 | kotarak | 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 | chouser | 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 | kotarak | subscribing to /repl/1 would make that keep state between connections. |
| 16:36 | kotarak | not subscribing would be one-shot repl |
| 16:36 | kotarak | for a single command, eg. completion request or something |
| 16:36 | kotarak | 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 | kotarak | 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 | kotarak | 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 | kotarak | 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 | ztellman | in our separate repl sessions |
| 16:41 | ninjudd | ztellman: they would be the same |
| 16:42 | ninjudd | 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 | kotarak | 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 | chouser | 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 | chouser | 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 | chouser | kotarak: but doesn't handle future :x/:y, right? |
| 16:48 | chouser | 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 | ninjudd | 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 | ohpauleez | all the util methods got promoted |
| 16:50 | ohpauleez | 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 | chouser | 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 | ninjudd | 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 | @rhickey | 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 | kotarak | 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 | chouser | 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 | chouser | 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 | @rhickey | that way you know it will work over a real mq |
| 16:59 | @rhickey | 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 | chouser | ztellman: that's what I'm saying, yes. |
| 17:02 | ztellman | chouser: why? |
| 17:02 | ztellman | 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 | chouser | 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:03 | polypus | |
| 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 | chouser | 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 | @rhickey | 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 | chouser | 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 | chouser | 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 | @rhickey | 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 | chouser | 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 | @rhickey | clients will likely be happier with one subscription |
| 17:19 | @rhickey | but who knows |
| 17:19 | lpetit | hmm |
| 17:20 | lpetit | probably depends on the API of stomp impls, and the out of the box facilities to plug hook functions in both scenarios |
| 17:20 | lpetit | 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 | @rhickey | but all will allow separate functions per subscription |
| 17:21 | lpetit | so enter the multimethod world |
| 17:21 | lpetit | ok |
| 17:21 | lpetit | (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 | lpetit | #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 | lpetit | 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 | @rhickey | 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 | cpfr | faster than python, slower than java? |
| 17:39 | lancepantz | yes, and sometimes :) |
| 17:39 | lancepantz | or arguable, and arguable |
| 17:39 | cpfr | thanks |
| 17:40 | cpfr | 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 | jjido | (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 | ataggart | I was just late ;) |
| 17:45 | ataggart | and incorrect in the format |
| 17:46 | ataggart | 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 | amalloy | 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 | jkkramer | ,(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 | lpetit | cemerick: ready to add osgi support backed in ? |
| 18:20 | lpetit | :) |
| 18:45 | jjido | are we not allowed varargs in a protocol? |
| 18:48 | jjido | This protocol signature: (copy [self & bindings]) matches the following function: (fn [self foo bindings] nil) |
| 18:48 | jjido | :( |
| 18:51 | ztellman | jjido: no, it's an unfortunate limitation |
| 18:51 | ztellman | however, it's easy to create a non-variadic function in the protocol called function-name- |
| 18:52 | ztellman | 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 | cemerick | 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 | ztellman | 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 | cemerick | 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 | cemerick | 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 | cemerick | 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 | ztellman | 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 | cemerick | 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 | ninjudd | 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 | jjido | ,(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 | scottj | [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 | chouser | 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 | dreish | 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 | chouser | 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 | @rhickey | 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 | @rhickey | 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 | @rhickey | all human typing needs to go to the same place |
| 20:59 | @rhickey | or no interactive apps |
| 21:00 | @rhickey | 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 | ninjudd | 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 | ninjudd | rhickey: i think you're right |
| 21:04 | ninjudd | i suppose most people are :) |
| 21:04 | chouser | ninjudd: indeed |
| 21:05 | chouser | other solutions seem convoluted |
| 21:06 | chouser | 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 | @rhickey | since some read calls may eat some sends |
| 21:08 | @rhickey | also I presume send on newline, even if incomplete form? |
| 21:08 | @rhickey | 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 | @rhickey | I definitely want them separate, even if many clients will merge |
| 21:19 | cemerick | Raynes: what's widely used? |
| 21:22 | cemerick | 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 | @rhickey | cemerick: and certainly not what I want |
| 21:31 | @rhickey | cemerick: how can we reconcile this with your initial vision? |
| 21:31 | @rhickey | 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 | cemerick | I'm not sure I have the time to redesign from the ground up. |
| 21:35 | cemerick | not right now, anyway |
| 21:36 | cemerick | 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 | cemerick | 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 | jjido | cemerick: not just maps and assoc just returns a new map -- doesn't change the original |
| 21:43 | cemerick | ah |
| 21:43 | cemerick | jjido: that's generally considered to be a good thing :-) |
| 21:44 | cemerick | 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 | cemerick | 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 | cemerick | 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 | cemerick | rhickey: sure; have a good night :-) |
| 21:48 | Anniepoo_ | blackboard/broadcasting thing, so if that's what you mean, yes |
| 21:50 | Anniepoo_ | not sure how it's related. |
| 21:51 | airolson | has anyone encountered the repl in slime apparently not evaluating anything? |
| 21:52 | airolson | 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 | airolson | 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 | cemerick | 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 | cemerick | Eclipse has a bytecode viewer baked in, which is nice. |
| 22:32 | sproust` | That's neat. |
| 22:33 | sproust` | 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 | cemerick | There's a jad plugin for eclipse too, but I've never used it |
| 22:35 | cemerick | 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 | lambdalion | err- I habe some |
| 22:44 | chouser | lambdalion: :-( |
| 22:44 | lambdalion | I'm wondering if 1) it is still being developed |
| 22:45 | lambdalion | 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 | lambdalion | 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 | chouser | 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 | cemerick | 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 | lambdalion | 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 | cemerick | 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 | lambdalion | the two macro namespaces are confusing, but... |
| 22:55 | lambdalion | 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 | lambdalion | Vut I hadn;t seen sriptjure- I will look at that. Thanks. |
| 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 | arohner | 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 | lambdalion | but... |
| 23:01 | lambdalion | parenscript has two macro-spaces... |
| 23:01 | lambdalion | 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 | lambdalion | but- that's hard to fathom. |
| 23:03 | lambdalion | 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 | lambdalion | Did learn a bit about the compiler circa then from reading the code though, so not a loss. |
| 23:07 | lambdalion | yeah- I sis figure out that it was very different int intent from parenscript, which has almost the opposite philosophy |
| 23:07 | lambdalion | 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 | dnolen | 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 | sproust` | 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 | dnolen | lambdalion: metadata is magical thing. |
| 23:13 | dnolen | ,(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 | sproust` | 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 | dnolen | 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: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 | sproust` | 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 | sproust` | 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 | 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 | cemerick | 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 | chouser | 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 | lambdalion | err- 20-40 |
| 23:29 | cemerick | lambdalion: tried psyco? |
| 23:29 | cemerick | (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 | lambdalion | *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 | lambdalion | It can't be too fast, and will never be fast enough.... |
| 23:34 | lambdalion | the python is for prototyping, but... |
| 23:35 | lambdalion | 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 | lambdalion | it is meant for a commercial Maya plugin |
| 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 | lambdalion | but we wouldn;t be able to use it without undue work... |
| 23:39 | lambdalion | the lot of plugin developers is living with the dicisions of the software you write plugins for. |
| 23:39 | lambdalion | *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 | lambdalion | 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 | 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 | lambdalion | 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 | lambdalion | Gotta say though that that clojure->scheme->->C idea is very interesting... |
| 23:52 | lambdalion | 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 | lambdalion | first time I was introduced to the idea of functions that returned functions... |
| 23:58 | lambdalion | 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. |