#clojure logs

2010-09-29

00:16technomancytime to find a new name for pods: http://www.theregister.co.uk/2010/09/24/apple_pod_row/
00:20amalloytechnomancy: they're just jealous that facebook owns the word Book
00:22jk_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:23bhenryshow us
00:23bhenryit should work
00:24jk_(defn foo [{major :major minor :minor} m] (str major "." minor))
00:25jk_call it like: (foo (hash-map :major 8 :minor 13)) gives wrong number of args
00:25lancepantzthe m is implicity
00:25technomancyjk_: where's m coming from?
00:26lancepantzs/y//
00:26sexpbot<lancepantz> the m is implicit
00:27jk_technomancy: m isn't the argument map that i pass on the call?
00:27jk_(defn foo [m] (let [{major :major minor :minor} m] (str major "." minor))) that works
00:27technomancyjk_: no, m is the second argument in the arg list, but when you're calling foo, you're only passing in one argument
00:28technomancyright, because in that case m is the argument to foo
00:28jk_technomancy: doh! sorry. i see
00:28jk_i misunderstood the syntax
00:28jk_i see now
00:28technomancyyeah, 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:29technomancywhereas in defn, the value is provided at the call site
00:29jk_technomancy: got it. glad the clojure community puts up well with newbies :)
00:29technomancyeveryone starts at the beginning
00:30amalloyjk_: 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:32jk_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:33jk_amalloy: i mean foo() doesn't actually know what's in it. i was just doing a test, learning about destructuring
00:34amalloysounds 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:35jk_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:43amalloybtw jk_, is there a reason you're using (hash-map :a 1 :b 2) instead of just {:a 1 :b 2}?
00:44jk_amalloy: nope. just didn't immediately see the doc for creating a hashmap literal so i used the function call
00:44amalloywell, there ya go
00:44jk_:)
00:51technomancystubs! http://github.com/technomancy/rodney-leonard-stubbs
00:51technomancygotta love projects for which the readme is significantly longer than the code
00:52technomancy"The Man with the Blood on his Hands"
00:54jk_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:08amalloyjk_: 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:10jk_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:10technomancypet peeve: you mean Common Lisp?
01:10amalloytechnomancy: i actually even meant to type CL!
01:11amalloybut then some sort of demon got hold of my fingers or something
01:11technomancywell it doesn't help that CL isn't case-sensitive
01:11technomancy(proper nouns at and all)
01:12jk_amalloy: i only read the theory on lisp and read some code but never actually tried writing it until clojure
01:13amalloytechnomancy: sorry, can't parse that last message
01:14technomancyamalloy: 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:15jk_technomancy: you mean "Lisp" is synonymous with CL to the community?
01:16hiredmanwell, to the cl community
01:19technomancyI 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:20hiredmanor just refer to it as that thing those guys did that one time
01:21jk_lol
01:27technomancy"Common Lisp: some guys did it once, and so can you."
01:39replaca_technomancy: you make me feel like a grandpa!
01:43amalloyjk_: what editor are you using, if i may ask?
01:43jk_counterclockwise on eclipse
01:44amalloyhow's that working? i tried it a few months ago but things didn't seem to work very well
01:44jk_amalloy: just because i already knew eclipse and didn't feel like learning emacs (being a vi guy)
01:44amalloyheh. i understand there are decent vim modes for clojure, but i confess i saw this as an opportunity to learn emacs
01:45jk_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:45jk_amalloy: that hangs teh entire eclipse environmetn
01:45amalloyweird. and a lot of things are lazy, so this must happen a lot?
01:46jk_amalloy: well normally i'm using them somehow rather than just typing random things into the repl in eclipse
01:46amalloyyou'd be surprised how much you can learn just typing stuff into the repl to see what happens
01:47jk_amalloy: right. so i do that at the command line normally so i don't run into that ccw bug :)
01:47amalloyaha
01:48jk_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:49jk_amalloy: i'm sure it's vastly inferior to using emacs but oh well :)
01:49jk_amalloy: ccw is actually very nice when it doesn't hang :O
01:50amalloyi 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:50raekyou mean Escape-Meta-Alt-Control-Shift?
01:52amalloyraek: i saw a picture of a space cadet keyboard for the first time today. that's a lot of modifier keys
01:54amalloyi knew about hyper/super/meta/alt/shift/control, but i didn't realize they also had Top/Front
02:16replaca_tolsen: if you're there. Autodoc is fixed now.
02:58LauJensenGood morning all
03:02amalloyheh. when LauJensen gets here, that's how i know i ought to be in bed
03:02LauJensen:[
03:07tobiasraederWhat 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:08tobiasraederwhere getter is the function that i want to evalutate before passing it into the macro
03:14amalloytobiasraeder: unless i'm misunderstanding you, you can't - macros happen at compile time
03:15tobiasraeder@amalloy makes sense. if i replaced the function with a macro that should do the trick tho?
03:15amalloyis the data all known at compile time?
03:16tobiasraederyeah it is
03:16tobiasraederand getter should just generate a vector with some symbols/class names
03:16amalloythen there's certainly *a* way to do it. i actually wouldn't suggest making getter into a macro
03:17tobiasraederwhat 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:17amalloyinstead, 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:17amalloyone sec and i'll put together a gist
03:18tobiasraederthank you :)
03:23amalloytobiasraeder: http://gist.github.com/602399
03:24amalloynot actually working, but you can see what i'm getting at, i hope?
03:24tobiasraederyeah i see
03:24tobiasraederand can i pass the make-gets into gen-interface?
03:26amalloyright, because it will expand into real code, still at compile time, which gen-interface will understand
03:26tobiasraederalright
03:26tobiasraederill try that in a minute. thank you very much
03:29amalloytobiasraeder: a version that actually works, in that it defines some variables: http://gist.github.com/602404
03:30amalloyhonestly i've written (defmacro foo [& args] `(do ~@(apply map somefn args))) enough times that i ought to make a macro for it :P
03:30tobiasraederhehe
03:31tobiasraederbut i do have to def all the variables i want to pass to the macro this way?
03:31tobiasraedermaybe im just getting it wrong again tho
03:31amalloynot sure what you mean?
03:32amalloyoh 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:32shachafamalloy: What's the point of doing that as a macro?
03:32tobiasraederah okay
03:33amalloyscgilardi: nothing really, for a simple def
03:33amalloybut 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:33shachafOh, I missed some context.
03:35tobiasraederactually i want to define one interface with x times make-getter and make-setter
03:35amalloyshachaf: 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:37amalloytobiasraeder: was that asking for more help, or just explaining to shachaf?
03:37tobiasraederi wanted to start to explain it
03:43tobiasraeder@amalloy would you mind taking a look at http://gist.github.com/602418 ?
03:43tobiasraederit evaluates, but doesn't create any new functions for the interface. maybe i'm just overlooking something
03:44amalloywell, now you don't have any macros at all. you still need one macro for the top-level entry point
03:45tobiasraederwell gen-interface is a macro
03:45amalloysomething like: (defmacro make-gettable-iface [name type] `(gen-interface ...~(make-getter type)))
03:46amalloytobiasraeder: right! and that means it won't evaluate make-getter, because that's a run-time function that it can't know about
03:47amalloybut if *you* write the outermost macro, you can evaluate whatever parts you want before passing it down to the "dumb" gen-interface
03:47tobiasraederah now i think i finally got it
03:47amalloybtw is there a reason you're using (vector), (list), and (hash-map) instead of [] '() and {}?
03:48tobiasraedernot really guess i should replace them
03:49amalloywell, 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:55tobiasraederactually i think im fine with the literals. just got really mixed up in my head with the macro/gen-interface stuff
03:56tobiasraederand yay it is working now
03:56amalloywooo
03:56tobiasraederi got an interface with one getter now, yay me
03:56amalloyyes, macros are mind-bending no matter how much you do them
03:56tobiasraederlol
04:00amalloytobiasraeder: okay, just got my version working. compare notes?
04:01tobiasraeder@amalloy sure
04:01KaaliHow can I import two Java classes which has the same name?
04:01amalloyKaali: import one of them, and refer to the other with a fully-qualified name
04:02tobiasraederdoesnt import allow :as?
04:02tobiasraeder@amalloy http://gist.github.com/602418
04:02KaaliDoesn't seem like import allows :as
04:02amalloyi don't think it does, but i could be wrong
04:03Kaaliamalloy: How do I refer to it, as I can't import it at all.
04:03amalloyjava.util.Date
04:03amalloydon't import it
04:03tobiasraederyeah my bad.
04:03amalloyyou don't have to import, just refer to it with its long name
04:04KaaliThanks, just a foolish mistake. I tried to use java.lang.Date, not .util.
04:04KaaliI wondered why other classes worked with full name and this one didn't.
04:04amalloytobiasraeder: http://gist.github.com/602441
04:05amalloyheh. and i guessed right. it's always Date :)
04:05KaaliYup =)
04:06tobiasraeder@amalloy yours is obviously a bit further down the road and pretty much exactly what i was looking for ;)
04:06amalloygood! steal it, but obviously learn from it too
04:06KaaliCurses, I just rewrote a function which uses Date, and I referred it as java.lang.Date... again!
04:06tobiasraederyeah i think i just learned quite a bit. Thanks alot.
04:07amalloytobiasraeder: 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:08amalloyoog, LauJensen got here an hour ago and i'm still up. bedtime for me. have fun, Kaali & tobiasraeder
04:09tobiasraeder@amalloy thanks alot for the help and sleep well.
04:09LauJensenGood night :)
04:09KaaliThanks again amalloy
05:08akuzianyone know when the keynote/sessions start at clojure-conj on Oct 22. i'm thinking of flying down in the morning.
05:12xkbno idea yet, but my ticket is "in the bag" :)
05:12xkblooking forward to it
05:16LauJensenakuzi: Theres a contact email on the website
05:17xkbWhat's Durham like anyway?
05:20LauJensenxkb: Its Durable, but with ham
05:21xkbhehe
05:21xkbsmells sweet ;)
05:23esjI'm deeply tempted to go over for it
05:23esjakuzi: the site says 9am
05:25akuzioh really?... thanks..
06:48bobo_didnt someone in here talk about doing an etl in clojure?
07:01cemericketl?
07:01cemerickextract transform load?
07:01bobo_yeh
07:01bobo_data warehouse stuff
07:01bobo_i found some utils att github, so i cant be alone in the thoughts atleast
07:01cemerickLots of that going on, though people are quiet about it for the most part.
07:02cemerickNot really the sort of thing that the open source folk are big into :-)
07:02bobo_indeed
07:02cemerickweb framework v396 is *much* higher priority ;-)
07:02bobo_hehe, we need more frameworks
07:02bobo_and fartapps
07:02cemerickheh
07:03LauJensenhaha
07:03cemerickA friend of mine is using clojure for etl of medical data. Gnarly stuff.
07:03cemerickHad to write the parsers and such from scratch, of course.
07:03bobo_i have everything in databases atleast
07:04cemericklucky
07:04bobo_yes, if it where fever then about 100 databases it would be awesome =)
07:05cemerickflat 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:06bobo_fun fun :-)
07:09LauJensencemerick: 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:09cemerickLauJensen: lucky you :-)
07:10cemerickApparently many such files have different delimiters depending on which sub-subfield you're in.
07:10cemerickMaking a regex impossible, of course.
07:10cemerickThank goodness, I've never had to do such stuff myself.
08:09cemerickchouser: ping
08:17AWizzArdrhickey: is (biginteger 13178456923875639284562345789) supposed to throw #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for long: 13178456923875639284562345789> ?
08:18@rhickeyAWizzArd: 13178456923875639284562345789 is not a valid numeric literal
08:18@rhickeyer, no
08:18AWizzArd(biginteger 13178456923875639284562345789N) also throws it.
08:19AWizzArdor evaluating that number and then followed by (biginteger *1)
08:19@rhickeyright, it's that there isn't a case for bigint
08:19AWizzArdI tried it with the most recent clojure.jar
08:20@rhickeyAWizzArd: needs fixing, please enter a report, thanks
08:20AWizzArdk
08:20@rhickeyAWizzArd: you know there is bigint now too?
08:23AWizzArdrhickey: yes, I use both of them
08:24AWizzArdCurrently 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:24AWizzArdThat's where I noticed the current issue #447.
08:31chousercemerick: ack
08:31cemerickMorning :-)
08:31chouserGood morning sir
08:31chouserI dreamt of clojure conj
08:31cemerickchouser: I'm wondering about whether the "final value" of the code sent should really be privileged.
08:32chousercemerick: ok
08:32cemericke.g. if you send a string with 5 readable sexprs, I presume you'd want to highlight each "return value" separately from *out*
08:32chouseroh, not an input I had considered.
08:33cemerickright; the reader is not in control of the scope of code being eval'ed in this world
08:33cemerickOr, it is, but the broader scope is client-defined.
08:33chouserhm, and what about writes to *out* that happen in other threads after the last expr's return value?
08:34cemerickThose 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:35cemerickAll of the other hosted repls have the same issue AFIAK -- swank, encojure, and ccw.
08:35chousercemerick: I'm hopeful that whatever rhickey has cooking to improve on binding will allow handling of that kind of situation.
08:36chouserbut until then, saying that *out*/*err* from other threads gets lost or logged elsewhere or something may be the only reasonable solution.
08:36@rhickeywhat situation?
08:36cemerickchouser: 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:36chouserrhickey: (magic-binding [*out* client-stream] (send-off (agent 42) prn))
08:37cemerickscary.
08:37@rhickeychouser: well, it's not going to make multithreaded access to streams any better :)
08:37cemerickIMO, anyway.
08:37chousercemerick: 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@rhickeybut it might at least make the binding visible to the agent
08:38chouserrhickey: that's all I mean.
08:42cemerickchouser: I'll keep thinking about it. There are others that want to get System/out and System/err streaming back as well.
08:43@rhickeyanyone here use FishEye? It looks like that is the best way to get Kira/Git integration
08:43@rhickeyer Kira/Git
08:43@rhickeyJira/Git
08:43cemerickrhickey: Yeah, it works well. Somewhat more heavyweight in the UI department than I'd like, but it gets the job done.
08:44@rhickeycemerick: have you connected it to git?
08:44cemerickrhickey: yup
08:45chouserI 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@rhickeycemerick: great, also, is it a single user management db for Confluence/Jira/FishEye?
08:46chouserrhickey: we have fisheye connected to a git repo at work, but I don't know much about how it was set up.
08:46cemerickrhickey: it's called Crowd, I think. Never used that.
08:46chouserwe've since moved the git repo to github:fi
08:46cemerickI presume there's LDAP support floating around everywhere though.
08:46esjchouser: i set it up recently, almost zero effort
08:46cemerickchouser: damn: deep pockets over there! :-P
08:48@rhickeycemerick: wow, without crowd you have to admin users separately for Jira, FishEye and Confluence? yikes
08:48esjnothing like making a market for your own products.
08:48@rhickeyI could see something like Crowd for connecting externally
08:48chousercemerick: 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:49cemerickrhickey: apparently yes, though there's LDAP
08:49cemerickWe've never been large enough to care about the user admin "burden"
08:50cemerickchouser: Really. That's a surprising statement. If i shelled out that kind of cash, I'd be expecting perfection.
08:51andyfingerhutExpensive software can be and often is bug-ridden. But sometimes you get decent support.
08:52chousercemerick: 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:52chouserI also think we're using it more heavily than most of the other github:fi'ers
08:52@rhickeyno free open source license for crowd
08:53LauJensenI must say, Gitosis has never left me wanting when it comes to managing Git repos
08:53@rhickeyatlassian moving strongly towards Mercurial
08:53cemerickrhickey: I have to think they'd accommodate you if you shot an email their way
08:53chouserLauJensen: hosted by them or you?
08:54LauJensenchouser: them? I host my own repos, manage them with Gitosis
08:54@rhickeycemerick: I simply wonder how the tools work together at all with separate user dbs
08:54cemerickchouser: gitosis is a tool, not a service
08:54chouseroh
08:54cemerickmaybe you're thinking of gitorious
08:54chouseroh, indeed
08:54cemerickwhich is simply *impossible* to install locally
08:54abrenkrhickey: Central user management should be possible without Crowd using just LDAP, Crowd just adds single-sign on, I think.
08:56@rhickeyabrenk: makes sense
08:57cemerickrhickey: 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@rhickeycemerick: they are adopting Mercurial internally, so I expect that will get more attention
08:59LauJensencemerick: silly?
08:59cemerickas long as git support doesn't wither on the vine or otherwise lag significantly, I'll be happy
09:00cemerickLauJensen: e.g. trying to funnel users of their tools into hosting via bitbucket/hg by letting support for other SCMs bit-rot, etc.
09:01LauJensenI wouldn't worry too much about that
09:02cemerickCompanies do funny things when they get funded, start acquiring others, etc.
09:03AWizzArdWhat does this argument list from Java mean? 'public <T> T foo (Class<T> type)' specifically this 'Class<T> type' thing
09:04LauJensenWhere is that project which found example-code of any clojure-fn you could think of?
09:04clojurebotproject euler is http://ProjectEuler.net
09:05chouserLauJensen: http://getclojure.org:8080/examples/zipmap
09:05LauJensenthanks
09:08AWizzArdAah, BitBucket was bought by Atlassian, cool :)
09:10AWizzArdSo maybe BitBucket users will soon get support for Jira, FishEye and such? Mama mia :)
09:10@rhickeyhttp://confluence.atlassian.com/display/DOC/Delegate+user+management+to+use+JIRA+logins
09:10AWizzArdIt's a good day :)
09:10@rhickeyhttp://www.atlassian.com/summit/2010/presentations/development-speed/dvcs-systems-in-the-enterprise-git-mercurial.jsp
09:13AWizzArdWow, unlimited private repos now
09:14LauJensenHopefully Github will offer something similar :)
09:19@rhickeyshoover: 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:20shooverrhickey: cool
09:20LauJensenAssembla is leaving something to be desired?
09:20abrenkrhickey: 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@rhickeyabrenk: it seems like LDAP only does the logins, not groups etc
09:21abrenkrhickey: There are groups in LDAP. Although not all tools support looking them up.
09:21@rhickeyabrenk: afaict Jira/Confluence use their own groups even with LDAP, but Confluence can use Jira's
09:22shooverthe atlassian presentation is worth it for slide 10
09:22AWizzArdEveryone who not joins to BitBucket really misses a lot of dev comfort ;)
09:22AWizzArd-to
09:22abrenkrhickey: at least Confluence supports LDAP groups: http://confluence.atlassian.com/display/DOC/LDAP+User+Management
09:22bartjsilly question, distinguish the use-cases between "for" and "map"
09:23bartj, (for [i (range 10)] (* i i))
09:23clojurebot(0 1 4 9 16 25 36 49 64 81)
09:23AWizzArdOne can losslessly convert a git repo into a hg repo (and back).
09:23bartj, (map #(* % %) (range 10))
09:23clojurebot(0 1 4 9 16 25 36 49 64 81)
09:23bartjsame result :)
09:23@rhickeyabrenk: then it's Jira that doesn't
09:23no_mindatlassian is lanning to buy bit bucket
09:23AWizzArdno_mind: the BB website is already updated.
09:23AWizzArdAtlassian logos everywhere.
09:23no_mindoh kool
09:23no_mindso they already bought it
09:23AWizzArdIt is so great, I can now have a million private repos.
09:24LauJensenAWizzArd: yes! One for each line of code!
09:24AWizzArdLauJensen: exactly what I thought!
09:24LauJensenAWizzArd: We can make a chat program which logs each line in a repo of its own, like twitter!
09:24AWizzArdtwitbucket.org
09:24abrenkrhickey: that's a pity
09:25bartjah, never mind
09:27chouserbartj: right, there is a fair number of cases that work approximately as well in 'for' and in 'map'
09:28bartjchouser, I was just thrown aback, they could be used inter-changeably sometimes
09:28bartjis there a *light-bulb* moment I am missing here :)
09:30chouserthe 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:30andyfingerhutbartj: for can do nested "loops", whereas that is not as trivial using map.
09:32abrenkrhickey: 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@rhickeyabrenk: yes, I just want to do groups once, I don't care where
09:36abrenkrhickey: 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@rhickeyabrenk: Confuelnce using Jira users/groups might be sufficient
09:37abrenkbecause that's the "just one vendor" scenario...
09:38@rhickeyabrenk: yes
09:38abrenk...the pain then starts if you want to integrate another tool.
09:38@rhickeyabrenk: we have limited resources to apply to this
09:39@rhickeyabrenk: got a recommendation for a free (for open source projects at least) ldap server?
09:40abrenkrhickey: I use OpenLDAP
09:41abrenkOpenLDAP was there in the beginning and I didn't have the resources to look at the alternatives that came up in recent years.
09:41msappleris 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:41msappler (and
09:41msappler (< (Math/abs (- xlight x)) (+ half-w max-range))
09:41msappler (< (Math/abs (- ylight y)) (+ half-h max-range))))
09:44abrenkit's like managing apache: just config files, no fancy web interface
09:44LauJensenmsappler: [[xlight ylight x y] (map float [xlight ylight x y]) ?
09:45msappleroh thanks
09:46msapplerwhy didnt i think of this simple solution? 0_o
09:46andyfingerhutIf 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:46chouserit won't.
09:47LauJensenandyfingerhut: you just ran it through the chouser-test :)
10:03AWizzArdFrom 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:03AWizzArdSo, maybe BitBucket will soon also support Git repos.
10:04bartjandyfingerhut, chouser thanks!
10:07mrBlissis wikipedia slow at the moment or is it just me? (I know http://downforeveryoneorjustme.com/ but it's just slow, not down)
10:19cemerickmmm, git BitBucket repos. That's a fine idea.
10:20AWizzArdcemerick: for now there is a lossless converter
10:21cemerickAWizzArd: I don't do hg. :-P
10:21klangGitBucket .. heh
10:21cemerickklang: nice
10:24klangcemerick: too easy
10:34cemerickit's too bad clojure.test only reports test results. Knowing when they've started, what their runtime is, etc. would be very handy.
10:35cemerickw/o writing one's own test runners, that is
10:36esjcemerick: Bamboo ?
10:36cemerickesj: Hudson, but that's besides the point. Bamboo has its own clojure.test test runner?
10:38esjcemerick: 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:38cemerickesj: 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:44esjI think it should be able to give you that: run-time for each test etc
10:47cemerickesj: 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:47cemerickAnyway, getting it done isn't a big deal -- just a shame that it's not baked in already.
10:47cemerickAnyone know what the status of clojure.test is (perhaps vis a vis lazytest, etc)?
10:48abrenkcemerick: i have code lying around to write the test run time to the JUnit XML output
10:48abrenkcemerick: wanted to contact stuart about contributing it tomorrow
10:48esjHmm.... 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:49cemerickabrenk: that'd be a great addition.
10:49abrenkcemerick: I also wrote a wrapper around multiple test reporters
10:49chousercemerick: any thoughts on how to have nREPL server support websockets without an external dep?
10:50chouseris it sane to consider a pure-clojure websocket server impl?
10:50abrenkI wanted the standard report to go to *out* in addition to the junit report to target/surefire-reports to show up in hudson
10:50esjabrenk: awesome !
10:51cemerickchouser: 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:51chouserok
10:51abrenkI still have an hour or two before i need to leave what would be the best way to have somebody take a look?
10:51abrenkfork clojure at github and publish there?
10:51chouserI have visions of a pretty web-based nREPL client.
10:51cemerickindeed, I'd say many do :-)
10:52esjabrenk: yes.
10:52cemerickI've love to have someone that knows websockets (at least better than I) take a crack at an nREPL websockets adapter.
10:52abrenkesj: okay!
10:52cemerickShould be able to run on the same port, even.
10:55cemericksexpbot: help
10:55sexpbotYou're going to need to tell me what you want help with.
10:56cemerickdo we have a bot with mailboxes?
10:56RaynesDefine 'mailbox'?
10:57cemerickRaynes: leaving messages for other handles for delivery upon their next arrival?
10:57Raynessexpbot 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:58Raynes$mail Raynes Message
10:58sexpbotMessage saved.
10:58Raynes$mail
10:58RaynesLike that.
10:58cemerickok, thanks, I'll give it a whirl
10:59phenom_cemerick, i've got a websockets implementation in erlang
10:59@rhickeyhrm, 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@rhickeybut could be:
10:59@rhickey(let* [expr__80 x] (if (= 42 expr__80) 43 (throw ...)))
10:59cemerickphenom_: nifty, though I wouldn't really know what to do with it :-)
11:00cemerickwas it difficult to impl?
11:00phenom_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:00phenom_*thought
11:00cemerickphenom_: thanks, good to know. Link?
11:01Raynesesj: Yes, it does. ;)
11:01esj*gasp*
11:01cemerickI'm hoping to bait someone else into doing the websockets support for nREPL.
11:01@rhickeycemerick: trying to avoid netty?
11:01phenom_cemerick: github.com/djunforgetable
11:01neotykcemerick: have you seen sample of aleph websockets?
11:01phenom_check thor_websockets.erl
11:01cemerickrhickey: yes, nREPL should have no dependencies other than clojure
11:01cemerickneotyk: hrm, nope
11:02cemerickI didn't really know what websockets were until rhickey mentioned them last week :-P
11:02djpowellHmm. Anyone encountered "gc overhead limit exceeded" in clojure apps?
11:02neotykcemerick: good luck implementing your own http server with websocket support
11:02cemerickneotyk: I don't need an HTTP server, AFAICT?
11:02phenom_if i was a pro with clojure, id certainly help but im a beginner :P
11:03djpowellIt is a server app on a virtual server that does lots of churn, but shouldn't be using much memory overall
11:03neotykcemerick: well, websocket uses http extension mechanics
11:04AWizzArdcemerick: Netty is not specifically a http server. It only happens to support that protocol.
11:04AWizzArdCan be used to implement an echo server, a time server, etc.
11:04abrenkesj: the code is currently on the 1.2.x branch but it applies cleanly to master. on which branch should I commit?
11:04cemerickneotyk: 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:04djpowellWonder if I'm getting some weird gc behaviour on that environment
11:05neotykcemerick: yes, client asks to upgrade protocol to websocket
11:05esjabrenk: i'd go with 1.2, but that could be just me.
11:06abrenkdjpowell: the error means that gc is leaving no time to the app itself. heap is completely used up by non-gc-able objects.
11:06AWizzArdcemerick: Jetty also supports this Ajo thing instead of HTTP
11:06cemerickneotyk: which is just delimited UTF-8 "frames"? Certainly doesn't seem to involve an HTTP server.
11:06AWizzArdAJP13
11:07cemerickIn any case, I'm trying to not get sucked into websockets yet
11:07cemerickAWizzArd: Sure; don't want the 12MB dependency or whatever is though
11:07djpowellYeah. 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:07AWizzArdcemerick: exactly, that is true
11:07neotykcemerick: if you would still like to leverage support offered by other libs: check http://github.com/maacl/aleph-ws-test
11:12@rhickeycemerick: so you'd write something directly on TCP?
11:13@rhickeynetty jar 768k
11:13AWizzArdThat could be acceptable.
11:14djpowellDoes doing repl stuff over a http persistent connection suck?
11:14neotyknetty is very clean in it's deps
11:14@rhickeycemerick: abstracting away the transport is very valuable but non-trivial
11:14cemerickrhickey: 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:15cemerickIf websockets aren't doable without external deps, then it should be no problem to have a separate nrepl-websockets artifact, etc.
11:16@rhickeycemerick: 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:17chouserrhickey: you're expecting TCP to go away?
11:17@rhickeychouser: no tunneling, no SSL, no in vm without much wheel reinventing, free from netty
11:18cemerickrhickey: the protocol is entirely text-based. Should work over any transport AFAIK.
11:18@rhickeycemerick: it's not the bodies, it's the coordination
11:19ohpauleezjust for the record, I have a version of repl-server (mostly) running on netty/aleph
11:19ohpauleezI did it to learn aleph, pretty sweet
11:20cemerickrhickey: I'll need some education, then.
11:20@rhickeycemerick: you could write it to netty then swap in your dependency-less tcp stack, letting others use netty
11:21cemerickrhickey: if I had hair, that would've brushed the top of it
11:21@rhickey?
11:22cemerickI've never even looked at netty's project page or whatever.
11:22@rhickeyhttp://www.jboss.org/netty
11:22cemerickheh
11:22AWizzArdI think it would be really useful for that use-case.
11:22ohpauleezcemerick: You can also use netty, which is 80% just wrapped netty
11:22AWizzArdhmm
11:22ohpauleezgah, aleph
11:23KirinDavenetty is pretty neat.
11:23@rhickeywhat 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:23neotykcemerick: look at this impl: http://github.com/maacl/aleph-ws-test/blob/master/src/aleph_ws_test/core.clj
11:23cemerickrhickey: so one has to learn websockets and have appropriate libraries to write a REPL client?
11:24neotykand it already solves problem of old browsers that doesn't have WS support
11:24@rhickeycemerick: learn websockets or learn your custom protocol?
11:24KirinDaveneotyk: That's pretty clever.
11:24abrenkcemerick, esj: http://github.com/abrenk/clojure/tree/abrenk-clojure.test
11:24@rhickeycemerick: because the existing repl can work over sockets
11:24abrenkany idea when stuart sierra will be around?
11:25chouserwebsockets isn't a sufficient protocol for the feature set nREPL is targetting. needs something on top
11:25cemerickrhickey: not with tools, and not asynchronously
11:25@rhickeycemerick: right, I'm not saying it's adequate, just that there will be a protocol
11:25@rhickeyyours or some standard, e.g. stomp
11:26chouserjson
11:26@rhickeyor wesockets
11:26KirinDaveNo one in this community likes BERT, huh? :)
11:26@rhickeyjson is just a (bad) data format
11:27@rhickeynot a communication protocol
11:27chouserjson over websockets
11:27KirinDavejson-rpc is the protocol, and almost no one ive met actually likes json-rpc 1.1
11:27KirinDaveMost people change it subtly to take some of the insanity out.
11:27chouseras opposed to clojure-string-pairs-over-websockets
11:28@rhickeyrepl is somewhat more messaging-ish than rpc ish
11:28KirinDaverhickey: Both bert and json-rpc make allowances for that.
11:28cemerickrhickey: 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:29cemericks/a name/the name
11:29cemerickor term, whatever
11:30neotykcemerick: do you think your users will share same opinion ?
11:30cmiles74Would something like XMPP be better fit?
11:30chouserKirinDave: after a quick glance at json-rpc I don't see that it helps nREPL over a custom json protocol
11:30KirinDavecemerick: fwiw, I think your protocol is straight forawrd.
11:30KirinDavechouser: I am not advocating it at all.
11:30cemerickneotyk: insofar as my users are clojure toolmakers, yes
11:30chousercmiles74: I'm have a newfound dislike of XMPP
11:31KirinDavechouser: I was just clearing up a gap in the conversation.
11:31chouserturns out XMPP has weaknesses as a transport protocol.
11:31KirinDavechouser: JSON being "bad" though, I'd take big exception to. :)
11:31chouserer
11:31chouserturns out XML has weaknesses as a transport protocol.
11:31chouserKirinDave: I have not generally thought of json as bad either, but I'm loathe to contradict rhickey on something like that.
11:32KirinDaveLol.
11:32KirinDaveI'll take a shot.
11:32cemerickI 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:33KirinDaverhickey: 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:33KirinDaveI'm in for it now. Probably not, actually. :)
11:33chousercemerick: I was imagining optionally swapping a websocket layer between the message protocol and the raw socket.
11:33cemerickKirinDave: nah, I don't think json has much to apologize for.
11:33KirinDaveSo no one's mentioned Avro in this conversation
11:33KirinDavehttp://avro.apache.org/docs/current/
11:33chousercemerick: while secretly hoping we'd end up with something a little less ... odd ... for the message encoding layer. :-)
11:34cmiles74You can use Netty to build a TCP-based client/server, it might save you some time.
11:34KirinDaveWe're considering using it.
11:34cemerickchouser: indeed -- that's what I meant by "they could run on the same port". Sniff for HTTP header, switch as necessary.
11:34KirinDaveFor those of us writing APIs, Avro seems like a good call for internal stuff.
11:34cemerickcmiles74: 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@rhickeyI've to run, here's my 2 cents:
11:35cmiles74cemerick: gotcha.
11:35KirinDavecemerick: 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:35cemerickKirinDave: you've not :-)
11:35@rhickeyplease 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@rhickeyplease use a standard protocol like websockets or stomp
11:36@rhickeyplease do not use json, it is inadequate, and you can always downgrade to json
11:36@rhickeybut representing richer things in json means more work in reconstructing them than a simple js read for clojure data
11:36@rhickeyreader
11:37@rhickeysince that reader doesn't need to do many things like backquote
11:37ohpauleezis there a short hand for busting a vectors into subvectors of n-length
11:37ohpauleez?
11:37KirinDavecemerick: It's a port of webmachine to clojure.
11:37@rhickeyback later...
11:37KirinDavecemerick: For the prototype, on top of ring. I haven't decided if I'd ditch ring in the future.
11:37cemerickrhickey: 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:38KirinDaveUgh, the java stomp library is hosted in mercurial. Deeply disappointed.
11:38cemerickKirinDave: Nice :-D
11:38cemerickKirinDave: You've seen http://github.com/ordnungswidrig/compojure-rest ?
11:38KirinDaveYes.
11:38KirinDaveI think Webmachine is a better model.
11:39cemerickthat's the best prior art I've seen in that vicinity
11:40KirinDaveyeah, and it was the inspiration for my plan, actually
11:41KirinDavecemerick: I was looking for some advice tho
11:42KirinDaveSo I've got this implemented as a protocol with a default hash: http://bitbucket.org/justin/webmachine/wiki/WebmachineResources
11:42KirinDaveAnd I'll start building functions and macros to make construction of such a responder trivial.
11:43KirinDave(and probably one to invert the hash-based (extend...) syntax to a (defresource ...) for maximum performance later.
11:43edwIs there a preferred #clojure pastebin?
11:43KirinDaveToday I'm starting on http://bitbucket.org/justin/webmachine/wiki/BigHTTPGraph
11:43KirinDaveedw: Gist.github.com is great
11:43chousercemerick: could use websocket-style framing so you don't need the leading "entry count" on nREPL messages.
11:43edwThanks.
11:43KirinDaveAnd 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:44KirinDaveThe functional approach is, in my mind, much more straightforward.
11:44chouserKirinDave: both? a graph of functions?
11:44KirinDaveBut, the introspectability (if there is such a word) of the object graph that is consumed
11:44KirinDavechouser: Well of course things like tests would use graphs.
11:44clojurebotWho??
11:44KirinDaveerr, would use funs
11:45cemerickKirinDave: functional is a hard default to override, even here
11:45cemerickchouser: the thing about functions for something like this is that they're opaque
11:46chouserthey can now carry metadata
11:46cemerick(hrm, maybe that's what KirinDave was responding to re: introspectability)
11:46KirinDaveBut 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:46KirinDavecemerick: Indeed.
11:46cemericktrue, but if you need the same bits in the metadata as in the fn body, that's not so hot
11:47KirinDaveBoth seem very clojure-y and very lisp-y.
11:47KirinDaveBoth are amenable to helpful macros.
11:47edwThis call to Incanter's `dataset` procedure seems a bit...fugly. Am I missing some obvious idiom here? http://gist.github.com/602986
11:47cemerickKirinDave: I think it's a winner
11:47KirinDavecemerick: Which?
11:48cemerickKirinDave: functional graph approach. fn's are either opaque, or require repetition of the representation.
11:48KirinDavechouser: So your gut reaction is a bit of syntax that fills out metadata on a function and populates it?
11:48KirinDaveYeah
11:49KirinDavecemerick: 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:49chouserKirinDave: no, my gut reaction is "ick"
11:49KirinDavechouser: At the whole project concept?
11:50cemerickKirinDave: I'd much prefer a fn that produced a fn from the node representation, then attached the repr as metadata
11:50cgrandyou can avoid the repetition by making the record implements IFn... not sure it's a goog idea though...
11:50chousertrying to overcome that, what about writing sexprs that contain all the needed info from the graph in the most natural way
11:50KirinDavecgrand: Ha.
11:50KirinDavechouser: I agree that syntactically this decision should be concealed at the earliest opportunity. You don't need to sell me on that. :D
11:50chouserthen either walk the s-exprs or define macros to turn that into code
11:51cemerickI've been avoiding macros more and more of late. *shrug8
11:51chouserthe specific code it gets turned into could then be changed later if you don't like what you chose first.
11:52KirinDaveI'm just wondering if there'd be benefit either way that I can't think of.
11:52KirinDaveI suppose debugging and testing.
11:52chouserI'm liking this more and more. ignore the implementation and capture that graphs complexity as simply and succinctly as possible
11:53KirinDaveI 100% agree. I'm just trying to think about what the pros and cons are for the various outputs of the macro.
11:53KirinDaveImplementing a graph like this is a slam dunk for lisp, which is one of the reasons I was not afraid of it.
11:53chouserdon't worry abuot it
11:53chouseryou can do both
11:54KirinDavecgrand: Actually that suggestion raises a lingering question I've had.
11:54amalloybarging in late here; this discussion sounds interesting but i'm not sure what it's about. anyone mind filling me in?
11:54KirinDaveamalloy: I'm implementing WebMachine in clojure.
11:54chouseronce 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:55chouserthat probably would be something very compact and fuctional
11:55KirinDaveamalloy: The discussion is on implementing http://bitbucket.org/justin/webmachine/wiki/BigHTTPGraph
11:55chouserif 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:55KirinDaveAh.
11:56cgrandcemerick: can I comment on the OSGI doc?
11:56cemerickcgrand: sure, msg me your gdocs email?
11:58cgrandKirinDave: which lingering question? Why records do not implement IFn?
11:58KirinDavecgrand: No.
11:59KirinDaveI was curious what ever happened to repl-utils that made show such a hassle to get into your namespace
11:59KirinDaveErr, not yours
11:59KirinDavethe proverbial your. :)
12:01amalloyKirinDave: 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:05KirinDaveyeah
12:06ohpauleezShow should just promoted
12:06ohpauleezI use it a lot
12:06abrenkesj: an example how to use multiple test reporters with my code is at http://gist.github.com/603009
12:10DeusExPikachuanyone here use incanter?
12:14amalloyohpauleez: seconded
12:15amalloyi would use it a lot, if i could remember how to :require it
12:16jlr,(let [crazy-hashmap {() [], #() {}}] (get crazy-hashmap ()))
12:16clojurebot[]
12:17chouserohpauleez, 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:18ohpauleezto be replaced by anything similar?
12:18ohpauleezor just deprecated?
12:18ohpauleezor you can't say
12:23chouserI 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:32chouserhm, dir is there -- I wonder if a patch that makes it work with classes would be acceptable?
12:35AWizzArdrhickey: will (keys my-record) *always* first return the fields of the slots and only *then* the __extmap
13:01ohpauleezchouser: I'd ideally like dir to work like show when done on classes
13:02ohpauleezI also like the separation, ns vs class
13:03anonymouse89is there a way to do something in a namespace from another? for example def a var for configuration purposes?
13:04ohpauleezanonymouse89: take a look at in-ns, it might be what you're looking for
13:05ohpauleezanonymouse89: also take a look at clojure.contrib.ns-utils
13:05anonymouse89ohpauleez: so I could temporarily change my namespace using in-ns def something and then switch back?
13:06anonymouse89ohpauleez: ah, immigrate from clojure.contrib.ns-utils may be what I'm looking for, thanks
13:07ohpauleezcool, happy to help anonymouse89
13:11cemerickchouser: FYI, nREPL's :value is no longer included in :out
13:20dakronechouser, 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:30jlrdakrone: As long as you save your order number, re-entering email + order number allows you to access it at any time
13:31jlrI 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:32jlrYou get the final version with it of course lol
13:32jlrThey email you each time it's been updated.
13:34dakronejlr, gotcha, thanks
13:34dakronealso, _fogus_ & chouser, do you accept bug reports? If so, where to send them?
13:34chouserdakrone: the manning forum is best
13:35dakronecool, thanks
13:35chouserdakrone: not sure how much longer we can still get changes in before they starting pulping trees
13:36ztellmancemerick: if you'd like any help using aleph to provide websocket support, just let me know
13:36cemerickztellman: 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:37ztellmanfor what it's worth, aleph treats websockets like pretty much like any socket protocol
13:38ztellmanyou could do your base TCP communication using aleph, and that would transfer pretty seamlessly over to websockets
13:38cemerickYeah, that's my general impression of websockets in general
13:39cemerickI think there's some requirements mismatch or simple miscommunication at the root of the current uncertainty.
13:39chouserhttp://jmesnil.net/stomp-websocket/doc/
13:39ztellmanhow so?
13:40sproustchouser: do you know when the paper print is going into production?
13:40sproust(I bought MEAP, but I prefer to read pulp, I've stopped myself from reading the PDF so far...)
13:40chousersproust: 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:41sproustThx.
13:41RaynesI only bought the PDF version. I don't have any programming-related dead-tree books.
13:42ztellmancemerick: 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:42cemerickztellman: 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:44sproustcemerick: reading your doc; surprised, I thought over environments also used swank.
13:46cemericknope; there's no clojure client, and the protocol isn't super-friendly (or particularly well-documented)
13:46chousercemerick: I'm liking stomp for this
13:47chousercemerick: custom headers seem widely supported and would suffice for id, timeout, ns, and status
13:47chousercemerick: add a bodytype to indicate if the payload is code (in a request) or out/err/value (in a reply)
13:48chouserthis buys you well-defined transport and quoting rules, along with code that implements them including over raw or web-socket
13:49chouserand 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:50cemerickHow did I get to the position of being the old fart for whom TCP and ssh tunnels were sufficient?
13:50cemerickClearly, retirement is nigh.
13:52chousercemerick: I am rather amused that you're the one pulling for a dep-less new implementation of something. :-)
13:52cemerickha
13:53cemerickI go where the requirements lead me. *shrug*
13:53rickmodesilly 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:53chouserand equally that I'm the one pasting this link: http://jmesnil.net/weblog/2010/01/14/using-stomp-with-hornetq/
13:53cemerickchouser: yeah, we've got a bizarro-world role reversal going on
13:55cemerickIt doesn't seem like a pure-clojure, no deps implementation of stomp is worth bothering with.
13:56ChousukeFactory factories. yay :P
13:56chouserIt wouldn't be a general-purpose stomp server, just one that can handle nREPL messages.
13:58chouserif read-stomp-message were more than twice the size of nrepl's current read-message, we did something wrong.
14:02cemerickI really don't care what the protocol is, as long as it can be easily implemented. I'll certainly investigate stomp more though.
14:02kotaraknrepl?
14:02chouserkotarak: http://github.com/cemerick/nREPL
14:03kotarakchouser: I know :) Already clone locally. I mean this stomp thing. I just read "cemerick" and "protocol".
14:03cemerickkotarak: There are some protocol rumblings. Not sure what to make of it all, yet.
14:04kotarakother feedback?
14:04cemerickyeah
14:04chouserof the rhickey kind
14:04kotarakui
14:04cemerickkotarak: http://clojure-log.n01se.net/#11:35
14:05cemerickI've been hermeneutic-ing all day now
14:05cemerick:-D
14:05LauJensen Nice, Rich hates JSON as well :)
14:07cemerickodd that we've gotten to a place where json is disliked by so many?
14:08LauJensencemerick: I understand why you consider Rich and I to be an army, but we're really just two people
14:09cemerickLauJensen: you guys are hardly the first I've heard :-
14:09cemerick:-)
14:09LauJensenoh... :]
14:10kotarakcemerick: for stomp I'll need an external non-Java program to handle the protocol. bleh.
14:10cemerickyeah, I know :-)
14:11cemerickkotarak: Don't worry. I'm not sold on the complexification, at least not yet.
14:12cemerickIf I am, then we'll be sure to have another path in that won't bind you in knots.
14:12@rhickeycemerick: what complexification?
14:12cemericktongue-in-cheek, there (at least partially)
14:12LauJensenrhickey: Shouldn't you be half-way in Aarhus by now?
14:13cemerickrhickey: standard protocols, netty et al., etc etc.
14:13cemerickrhickey: have you read http://bit.ly/nreplnotes ?
14:14@rhickeyif 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:14kotarakcemerick: I please don't feel to bound. My requirements are quite tough.
14:14kotaraks/I/Oh/
14:14sexpbot<kotarak> cemerOhck: Oh please don't feel to bound. My requOhrements are quOhte tough.
14:15LauJensenhehe
14:15@rhickeycemerick: skimmed those. they call for a message based procol and I'm saying why invent a new one?
14:16cemerickrhickey: 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:16chouserkotarak: surely you'll need an external program anyway -- you're not going to talk to a socket straight from vim, were you?
14:16@rhickeycemerick: because it leaves the base doing all the work instead of little of it
14:16cemerickrhickey: 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:17scottjWanting 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@rhickeycemerick: you are making them definitely lose the raffle by supplying a protocol for which they definitely can;t get a free impl
14:18cemerick...but for which they can write one in ~10 min?
14:18@rhickeynew protocols == bad
14:18kotarakchouser: right, but read something like netcat vs. something understanding stomp
14:18@rhickeyexisting protocols = free clients, free servers, free specs, choince of impls, choice of langs ...
14:19cemerickrhickey: let's ignore the protocol question for now. What about external dependencies?
14:19cemerick(funny enough, I was aiming for an HTTP impl before various people impressed upon me the importance of the dependency issue)
14:20@rhickeycemerick: you are only looking at the positives - look no deps! vs the tradeoffs - look we re-implemented 16 wheels!
14:20@rhickeyhttp is unsuitably disconnected
14:21@rhickeywe don't want rpc, we want async messages
14:21cemerickanother reason why I dropped it :-)
14:21cemerickrhickey: 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:21chouserkotarak: there's a stmp client in perl -- could just use that in vim. :-)
14:21@rhickeycemerick: agreed
14:22@rhickeycemerick: and yet, we're on the jvm for a reason, as you often say
14:23kotarakchouser: 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@rhickeycemerick: 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:23cemerickrhickey: but faced with wanting to interop in this case with a host of hosts, as it were. Other langs, emacs/SLIME potentially, etc.
14:23chouserI think nrepl would only need stomp's SEND message, nothing else
14:23cemerickrhickey: :-O
14:23@rhickeycemerick: you completely lose me on why your personal protocol is better for people than a standard one
14:24chouserthis would allow for re-implementation approximately as simple as implementing cemerick's proposed protocol but also allow use of existing libs
14:24kotarakchouser: + connect and (if politeness is of interest) disconnect.
14:24cemerickrhickey: it's not better, just simpler, and guaranteed to be implementable regardless of client platform/lang
14:24chouserkotarak: sorry, yes
14:25@rhickeycemerick: websockets and stomp are sufficiently simple and have bountiful implementations
14:25kotarakThere 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:25cemerickchouser: noted, I'm arguing with rhickey at the moment, tho :-D
14:25cemerickrhickey: I think kotarak and technomancy might disagree with that.
14:26cemerick(e.g. vimclojure & SLIME et al.)
14:26@rhickeycemerick: well, they are no worse of then with a custom protocol, for which no one gets a free impl
14:26@rhickeythan
14:27cemerickagain, I think implementation simplicity is a factor
14:27chouserunles the custom protocol is enough simpler than any available standard protocol
14:27@rhickeycemerick: 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:27chouserwhich is why I keep talking about a subset of something like stomp.
14:28cemerickrhickey: not if that means that other langs and environments are less likely to be able to interop
14:28@rhickeycemerick: than with what? stomp is everywhere
14:28@rhickeycustom comm protocols stink
14:29@rhickeyhowever simple
14:29@rhickeyhanging your message handler off a stock stomp/websocket client rules
14:29cemerickI'm certain that it does.
14:30@rhickeyif 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:31cemerickWhat has the world come to, where I'm here, and rhickey is suggesting putting hornetq in clojure core?! ;-)
14:31@rhickeyI 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:32cemerickrhickey: 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@rhickeycemerick: I'm certainly not going to re-implement message queues in order to avoid a dep
14:33@rhickeycemerick: but elisp people already have slime etc, and may be the only people who won't have stomp et al
14:33cemerickrhickey: don't worry, I've saved you the hassle :-P
14:34cemerickrhickey: 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:34lpetitHello all
14:34@rhickeycemerick: I have to imagine stomp is simpler than swank/slime
14:35@rhickeyswank/slime btw being poster children of custom protocols
14:35cemerickrhickey: 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:36dnolencemerick: rhickey: http://code.google.com/p/wave-client-for-emacs/source/browse/lisp/wave-client-websocket.el?r=b9619eaac2687be674fd4c680d276960735dac63
14:36dnolenwebsocket for elisp
14:36chouserrhickey: do you have any comment regarding using a subset of stomp, or is that not acceptable?
14:36@rhickeydnolen: yes, websocket even simpler
14:36chouserwebsocket isn't sufficient though
14:36cemerickwhat chouser said
14:37@rhickeycemerick: than pick a standard protocol, it directly impacts that goal
14:37lpetitrhickey: 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@rhickeythen
14:37cemerickrhickey: 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@rhickeychouser: 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:39chouserrhickey: to fully implement stomp appears to me to be drastically more complex then cemerick's protocol.
14:39@rhickeycemerick: 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:40dnolenchouser: how so? what feature is missing?
14:41ztellmanchouser: syntactically, STOMP seems pretty simple; are you talking about the semantics?
14:41cemerickrhickey: 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@rhickeychouser: but the vast majority of people can just grab an impl of stomp for their lang off the internets
14:43@rhickeyso, we're basically afraind that elisp users, who have embraced the complexity of swank, will balk at stomp?
14:43@rhickeyhttp://www.hccp.org/erlang/stomp.erl
14:43cemerickrhickey: That was just an example, of course. :-/
14:44chouserdnolen: what feature is missing from what?
14:44dnolenswank is epitome of what's wrong a custom protocol no? :)
14:44dnolenchouser: from websockets
14:44chouserztellman: yes, I'm talking about subscribe/unsubscribe/commit/ack, etc. things we don't need
14:44@rhickeystomp clinets for c.c++,c#, delphi,erlang,flash,haxe,java, objective c, perl, php, pike, python, ruby, smalltalk
14:45cemerickdnolen: nREPL is message-based, not just synchronous streams
14:45@rhickeyplus stomp can transparently ride on all message queues
14:45cmiles74I was just reading that webpage!
14:45cmiles74http://stomp.codehaus.org/Clients
14:46ztellmanchouser: ok, so you only use SEND, and have the canonical client and server ignore everything else
14:46ztellmanwill that break existing implementations?
14:46chouserztellman: that's essentially what I've been suggesting -- was hoping someone who knew stomp better to confirm that that's workable
14:46chouserthough that language list may make it moot
14:47@rhickeychouser: how do you receive?
14:47ztellmanchouser: I can't be that person, unfortunately, but I don't see what could break if subscribe/unsubscribe/etc. were noops
14:48s450r1ure
14:49drewrI 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@rhickeystomp may be more than we need, but the point remains, try to find a widley-implemented standard protocol that fits ok
14:51scottjdrewr: I think the concern is for the implementer.
14:51ztellmanaccording 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:52ztellmanthat would probably break existing clients, though
14:52@rhickeycemerick: and there's no saying, e.g. that you couldn't do a no deps impl of stomp on the server side
14:52scottjthough porting slime to nrepl sounds like so much work if someone's not deterred I don't think implementing stomp would do it
14:52cemerickscottj: I'm hopeful. Not being able to use the tools you want with REPLs running in deployed apps is frustrating.
14:53cmiles74If the client uses SUBSCRIBE, there could be support for multiple sessions to the same running process.
14:53dnolenscottj: clojure uses such a tiny portion of slime tho from what I can tell.
14:53dnolencompared to the CL experience, Clojure SLIME is fairly anemic
14:53cemerickrhickey: that seems ludicrous to me
14:54cmiles74COMMIT and ABORT look like the only two that really don't fit with my idea of what the REPL does.
14:54scottjdnolen: repl inspector debugger autodoc etc
14:54@rhickeycemerick: I bet you could implement stomp in a couple of pages of clojure, tops
14:54cmiles74Er, and BEGIN.
14:54chousercmiles74: yeah, I don't think we'd need transactions
14:55dnolenscottj: debugger doesn't work and swank-clojure has custom implementations of most of those. just the commands are bound to familiar things.
14:55cemerickrhickey: to save client implementors from figuring out how to write > 2\n"id"\n"blah"\n"code"\n"(println 5)"
14:56cemerickand rather, have them go find a stomp client lib?
14:56scottjdnolen: stacktraces and breakpoints and continues work. well yeah swank-clojure has to define the foundation for all those things.
14:56@rhickeycemerick: it's not the sending, it's the receiving, sockets, error handling etc
14:56@rhickeyif you have a stomp client, you basically connect and set up a handler function
14:57dnolenscottj: breakpoints? that's never worked in SLIME w/ Clojure. stacktrace sure, but that's trivial.
14:57LauJensendnolen: ? break-points work fine
14:57scottjdnolen: there's probably stuff inslime w/ clojure you're unaware of :)
14:58@rhickeyone of us could have written a stomp server in the time we've spent arguing about them :)
14:58dnolenLauJensen: setting breakpoints in Clojure with SLIME?
14:58LauJensendnolen: You set the breakpoints with swank.core/break
14:59dnolenLauJensen: oh yeah, that doesn't work very well
14:59LauJensendnolen: works fine for non-multithreaded stuff
14:59@rhickeyin fact, looking at the protocol I think merely choosing it delivers most of the desired benefits and won't require a dep
14:59dnolenLauJensen: or lazy stuff if I recall?
15:00scottjwith a few lines of code works fine with multithreaded too.
15:00@rhickeychouser: it seems to me that avoiding some of the protocol saves little, it's so simple
15:00LauJensendnolen: possibly
15:00dnolenLauJensen: so I rest my case, not useful :D
15:00LauJensenhater
15:00scottjI have an emacs key that inserts and removes breakpoints that work with multithreaded and I use it all the time.
15:01LauJensenscottj: demo or it didnt happen
15:03@rhickeychouser: we can ignore things semantically not meaningful to us as long as we do the protocol dance correctly
15:03chouserok, sure
15:05@rhickeyactually 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:06cemerickrhickey has gone enterprisey on us all! :-P
15:06wdouglasX(
15:06@rhickeycemerick: it's a flexibility that falls out of a little indirection and standards
15:07cmiles74I'm all enterprisey, I've never read the stomp docs until today. It looks like most MQ servers already support stomp.
15:07@rhickeystomp is widely supported
15:07@rhickeyclients and servers, lots of bridges
15:08cemerickrhickey: Q: are you viewing nREPL (conceptually) as a networked/hosted REPL, or as the basis for a clojure MQ or somesuch?
15:08@rhickeycemerick: 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:08duncanmla la la
15:08kotarakahem, how would a repl interaction look like with stomp?
15:08@rhickeycemerick: are they different?
15:09wdouglasrhickey: 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:10kotarakIf I transport code to be executed in the body, how can I specify *in*?
15:10@rhickeycemerick: I just think with a slightly broader view of the world you could get a lot more bang for the same effort
15:10kotarakIf I transport *in* in the body, where do I specify the code?
15:10cemerickkotarak: presumably, each k/v pair would be written out in a SEND
15:10cemerickrhickey: I *really* wish you had stated that, oh, 4 hours ago.
15:10duncanmi'm learning Incanter - I don't understand how 'incanter.core/group-by' works
15:11kotarakcemerick: and everthing in one transaction and COMMIT would finally trigger the evaluation?
15:11cemerickkotarak: mmm, maybe. I only first heard of stomp earlier this afternoon, so I'm in no position to be advising.
15:12kotarakcemerick: yeah. sorry. was actually asking more into the open. (But you answered. ;P)
15:12@rhickeycemerick: I think it falls out of first principles - indirection, opacity, standards, orthogonality, generalization
15:13@rhickeywhat is a repl but a remote execution system?
15:13chouserkotarak: I'll write up an example of what I was thinking. probably wrong, but may help as a starting point
15:13kotarakchouser: yes, please. To get a feeling how stomp would work.
15:14hugodcemerick: I have a version of swank-clojure running with futures similarly to your nrepl :)
15:14hugodthe rpc protocol is factored out too
15:16cemerickrhickey: 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:16cemerickThere's no reason why MQ concerns should push their way into simple point-to-point operation.
15:17@rhickeycemerick: exactly the opposite, if you use stomp you can slide them _under_ later
15:17cemerickrhickey: I never said the wire protocol had to be carried along. Quite the opposite.
15:18cemerickThis is exactly what multimethods are for, etc.
15:18@rhickeystomp has very little mq-ness, no brokers etc, mostly connect/send/receive/deal-with-erros
15:18@rhickeywe can ignore transactions
15:19cemerickThat's fine, and we can use stomp, but it doesn't need to be baked into the thing for the simplest use-cases.
15:20cmiles74Looking at the docs, stomp seems very simple.
15:21@rhickeyI 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:21chouserkotarak: http://gist.github.com/603361
15:21@rhickeyyour 'simple' protocol will be a ball-and-chain
15:21chouseroops, hang on already see a mistake
15:22cmiles74Stomp looks very close to the "simplest" protocol.
15:22chouserthere
15:23@rhickeycemerick: basing it on something like stomp (at the lowest level promised) will keep people from writing socket code
15:24@rhickeyand thus enabling swapping transports _under_
15:25cemerickrhickey: and this is where you start pitching netty to me again ;-)
15:25@rhickeycemerick: no, as I said, I think simply offering something like stomp as the lowest-level promise will enable swapping things _under_ it
15:26@rhickeyand I think stomp in clojure sans deps is very tractable. ditto elisp
15:26@rhickeychouser's probably halfway done :)
15:28chouserI found this webserver.clj I last touched in April 2008...
15:29@rhickeycemerick: the main objectives are standard protocol and transport independence, not deps :)
15:31@rhickeygoing client -> proxy -> client instead of repl server == stomp server is just a forward-looking way of implementing
15:33@rhickeyin 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@rhickeyto be clear, repl-client -> stomp-client -> stomp-[proxy]-server -> stomp-client -> repl-server
15:34hiredmangetting hornetq is a drag
15:34@rhickeyhiredman: how so?
15:34hiredmanI am using it to get irc notifications as growls (irssi on a remote machine)
15:35hiredmanif I recall it was a pain to get matching jars of hornetq and netty
15:35hiredmanand hornetq only had javadocs up for a released version that wasn't in maven yet
15:35hiredmanand they didn't build javadocs for the embedded server stuff
15:36@rhickeyhiredman: I just grabbed the zip and it has hornetq and netty jars...
15:36hiredmanbut I still kind of wish we used it at work over rabbitmq
15:36hiredmanrhickey: but to pull it in via project.clj
15:36hiredmanwhich I guess if it comes with clojure it's no big deal
15:36@rhickeyhiredman: oh, that
15:37@rhickey:)
15:37cemerickgoodness, hopefully optional
15:37cemerickrhickey: I'll take a closer look at stomp and see if there are other alternatives floating about.
15:37@rhickeycemerick: sounds fair
15:37cemerickIt's all yak-shaving AFAIC so far, though.
15:37@rhickeycemerick: thanks for listening
15:38hiredmanthe 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:38cemerickrhickey: 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@rhickeycemerick: did that
15:43@rhickeychouser: so taking this approach:
15:43kotarakchouser: how do handle *in*?
15:43@rhickeyto be clear, repl-client -> stomp-client -> stomp-[proxy]-server -> stomp-client -> repl-server
15:43@rhickeybrings 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@rhickeyand the other stuff will be dummied by the proxy or supplied by a real mq
15:44kotarakchouser: one probably needs a transaction. SEND type input, SEND type code, COMMIT something like this...
15:47kotarakchouser: or input is another destination, where data can be streamed to.
15:48chouserrhickey: I'm not sure that a no-dep repl-server is really no-dep if it needs a proxy running somewhere
15:48@rhickeyso the repl server does not accept subscriptions, nor ack nor receipt
15:48chouserrhickey: I like the flexibility of that topology, but ...
15:48@rhickeythe proxy is another page of clojure code in the same vm as the repl server
15:48chouserah, ok
15:48@rhickeyindirection!
15:49kotarakrhickey: subscriptions could be used for a running repl session to carry over state between connections.
15:49chouserkotarak: *in* is a great question. I don't think any of the nREPL docs cover that yet, do they?
15:49kotarakrhickey: for vim it will be connect, send stuff, receive answer, disconnect, connect, ...
15:49kotarakchouser: it accepts now an "in" key with data which is provided as *in*
15:49@rhickeykotarak: let's not go there now, but the idea of separate subscriptions for out and err is possibly useful
15:50@rhickeyalso in
15:50chouserkotarak: my tendency would be to do *in* async like *out*
15:50kotarakrhickey: I have to go there now. If you propose stomp, i have to think how a repl can work across stomp.
15:50chouserkotarak: could you work with named fifos? periodically reading from them to append to a buffer?
15:50hiredmanrhickey: 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@rhickeyso a repl could have twon in-queue, input an *in*, and 3 out queues, output. *out* and *err*
15:51kotarakchouser: on windows?
15:51chouserkotarak: :-(
15:51kotarakchouser: I'd like to drop win support, but I need it myself. :/
15:51kotarakwould make things a hell easier...
15:51chouserkotarak: the problem is that repls aren't really transactional at all
15:52chouserexpr->return value is, but in/out/err are not
15:52@rhickeytransactionality in stomp is about the message to the mq, not the repl-server
15:52chouserhm... maybe in is a bit
15:52kotarakchouser: well. Mine works quite well. With know limitations, like blocking while a command runs and no streaming in.
15:52chousersorry, shouldn't have used that word.
15:53@rhickeyactually taking the mq approach of stomp greatly simplifies the design, since a repl server really has 5 endpoints
15:53@rhickeyall could be addressed inside a single connection
15:53kotarakvim sucks really hard with outside world interop. :(
15:54@rhickeyhiredman: that's kind of general, but I could easily see problems. There is no visibility of classes between loaders
15:55chouserkotarak: ok, so ought to be able to send in and expr as seperate messages.
15:55chouserthe expr you send will presumably block on *in* which will be satisfied by a subsequent message.
15:56hiredmanrhickey: thats what I want, I want the classloader to be it's own little universe
15:56@rhickeychouser: did you see above? a repl serve is 5 queues
15:56kotarakrhickey: that doesn
15:56@rhickeyhiredman: then you'll have to tell me more about load not working
15:56chouserkotarak: 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:56kotarakoops
15:57kotarakrhickey: that doesn't help me. I have to cut things down.
15:57@rhickeykotarak: a stomp client can do that over a single connection
15:57chouserrhickey: yep, makes sense. destinations named like /sessionname/out or /sessionname/expr ?
15:57@rhickeychouser: right
15:57@rhickey2 inbound, 3 outbound
15:58hiredmanrhickey: well I guess I will do more digging then
15:58@rhickeyclients can send input, or *in*, get output, *out* and *err* cleanly
15:58kotarakchouser: I can live with that. Someone wanting more has to use an external repl anyway. More is not possible with vim.
15:58chousermy 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:58shooverdoes stomp SUBSCRIBE mean two clients can receive messages from one REPL?
15:58@rhickeychouser: both repl server and repl client use send/message
15:58@rhickeythe repl server is not a stomp server
15:59chouseryes, but the client will see MESSAGE for responses
15:59kotarakshoover: I would think so.
15:59chouserand the repl server will see MESSAGE for expr and in
15:59@rhickeychouser: yes, as will the server for input
15:59@rhickeyright
15:59chousergood
15:59@rhickeyI'm finding this very clean compared to repls over sockets
16:00@rhickeyinterleaving in/out and the streams usually being gross
16:01chouserclient has to subscribe to all three channels
16:01@rhickeyyou'll need some flushing policy for output
16:01@rhickeychouser: if they want
16:01kotarakrhickey: 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@rhickeytimeout + amount-driven
16:02chouserand has to send something to the server to tell it to subscribe to /my-new-repl/in and /my-new-repl/expr
16:03@rhickeychouser: no, server establishes all five queues
16:03chouserwhen?
16:03dmiller2718rhickey: time for ClojureCLR question?
16:03@rhickeychouser: when it comes up
16:03chouserso only one session per server?
16:04@rhickeychouser: dunno, could be multiplexed or yes, then client will need to tell server to listen to queues it establishes
16:04@rhickeydmiller2718: shoot
16:04@rhickeyactually, I have to run, bbl
16:05@rhickeysorry
16:05dmiller2718rhickey: too bad. Later.
16:06shooverdmiller2718: 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:06dmiller2718rhickey: Later for me will be in a day or two. Heading to the airport now.
16:07ninjuddi'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:09ninjuddchouser: you aren't already working on a clojure stomp library, are you?
16:09shooverI don't get why async is so good for the repl expr. Isn't that part of this problem essentially RPC?
16:09chouserninjudd: who, me?
16:09chouserwhy would you think such a thing?
16:10ninjuddjust because i was thinking of doing the same thing...
16:10chouserninjudd: you should do it. I definitely shouldn't.
16:10ninjuddneither should i
16:10chouserninjudd: note what rhickey said about separate repl-server-as-client and stomp proxy
16:11wdouglasHow would that work having the proxy on the same vm as the repl server?
16:11chouserI do have a few lines of code that listen on a port and parse http-like headers
16:11ninjuddchouser: yeah. if i understand stomp correctly, wouldn't that be the only *right* way to do it?
16:12chouserok, http://gist.github.com/603361 is updated
16:13ztellmanI don't know if most of what a messaging queue can do is necessary
16:13ztellmanshould each client have to ACK every line from *out*?
16:13ztellmando we want to journal output if no one's listening?
16:13chouserztellman: stomp doesn't require acks
16:14ztellmanchouser: there is an ACK message I saw, did I misunderstand?
16:14ztellmanah, never mind
16:14ninjuddztellman: is that what ack auto is for? to not require acking every message?
16:14chouseryes, but servers aren't expected to send that unless the client has asked for it
16:14ztellmanack is not the default
16:14chouserninjudd: I think so, yes.
16:15ztellmananyways, it seems rather trivial to create a message router in nREPL rather than proxying it
16:15chouserwdouglas: 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:17wdouglaschouser: 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:17chouserso 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:19wdouglasAh great. Would stomp allow for a group of real stomp servers to process requests (can we build it on stomp at least)
16:19ohpauleezztellman: Love the new docs you've been putting up. Let me know anytime I can help
16:20chouserwdouglas: 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:20ztellmanohpauleez: glad you're finding them helpful, they're still very much in-progress
16:20ztellmanchouser: how siloed would these individual sessions be?
16:20chousermaybe 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:21ohpauleezztellman: It was more than enough to push me up the learning curve. I've already happily used aleph in two systems now
16:21chouserztellman: not at all
16:21chouserhm
16:21ztellmanchouser: what's the point, then?
16:21chouseractually, that's a good point
16:22ztellmanyeah, there should be 5 channels, period
16:22ztellmaneveryone shares *out*, everyone's *in* is mingled, etc.
16:22chouserthe jvm only has one real out/in/err for the process
16:22kotarakchouser: you can do tricks to split that, see nailgun
16:23ninjuddchouser: 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:23ninjuddkotarak: yeah, i wrote a simple proxy to split System/out and err for cake too
16:23ztellmanohpauleez: glad to hear it. please don't hesitate to tell me if you run into any obstacles, I'm hungry for feedback
16:23ohpauleezwill do
16:24ztellmanninjudd: how does that handle new threads?
16:24kotaraknailgun basically provides per thread ins and outs which are inherited across new threads
16:24kotaraka given thread might choose to override the one it got from its parent
16:25kotaraksharing in/out/err between repl session is a no-go
16:25ztellmanI'd argue sharing classloaders between repl sessions is a no-go
16:25ztellmanso start a new server if you want something different
16:26ninjuddztellman: yeah, new threads would need separate queues beneath the repl's path
16:26lpetitAll in all, I hardly see clients heavily use *in*
16:26kotaraklpetit: I do
16:26kotarakheavily
16:26ztellmanif 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:26KirinDaveHum
16:26KirinDavehttp://idisk.me.com/dfayram/Public/Pictures/Skitch/This_Morning_s_Git_Protocol_Outage_-_GitHub-20100929-132219.png
16:27KirinDaveReminder to everyone: Never be this guy.
16:27LauJensenhaha
16:27kotarakztellman: I can silo multiple repl session on a single vm today. We should I choose something less than that?
16:27lpetitkotarak: can you explain?
16:27KirinDaveLauJensen: Even funnier; he's french.
16:27LauJensenKirinDave: I figured, either French, German or Danish :)
16:28ninjuddkotarak: here's the code from cake for splitting System/out https://gist.github.com/8ff63cbfe153c1d382e3
16:28chousercould you subscribe to someone else's /expr and /in and watch what they're doing?
16:28kotaraklpetit: 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:28kotaraklpetit: not using *in* means escape hell
16:29ztellmankotarak: cake seems to use a process-per-project approach
16:29ztellmanare you saying that's not necessary?
16:29chouserninjudd: so if you print from an agent or future, that output gets lost?
16:29kotarakztellman: no. But I want multiple independent repl sessions in parallel which do not interfere with each other on one single vm.
16:30chouserkotarak: how do you handle print or read-line from agents or futures?
16:30lpetitkotarak: but maybe not anymore if nREPL uses stomp, though ?
16:31kotarakchouser: 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:31lpetitanyway
16:31ztellmankotarak: so isn't that a deal breaker?
16:31ninjuddchouser: 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:31kotarakztellman: what?
16:31ztellmankotarak: the loss of output
16:31ninjuddthat's what the with-outstream macro is for
16:32kotarakztellman: 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:33kotarakztellman: If you I want everything from inside my IDE I must use something different from vim.
16:33ninjuddchouser: added a simple example to the gist
16:34chouserok, what if there was an api for tying new stomp destinations to java streams.
16:34chouserthen 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:35ninjuddchouser: that would be awesome
16:35kotarakchouser: isn't that trivial? /repl/1/out, /repl/1/in, /repl/1/err, /repl/1/eval, /repl/1/result, /repl/2/in, etc...
16:35kotaraksubscribing to /repl/1 would make that keep state between connections.
16:36kotaraknot subscribing would be one-shot repl
16:36kotarakfor a single command, eg. completion request or something
16:36kotarakunsubscribing would basically stop that repl.
16:36ninjudddon't you have to subscribe to receive any messages at all?
16:36kotarakhmm... bit subscriptions work only will we are connected?
16:37kotarakninjudd: hmm... you are right.
16:38lpetitout 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:38chousermy point is that the handling of repl "sessions" could be kept largely out of the protocol
16:38kotarakI think it is possible to get this easily running over stomp, properly separate for separate repl sessions.
16:39kotarakchouser: I think it has to be.
16:39ztellmankotarak: what sort of classloader trickery is necessary to make that work? I'm not particularly familiar with nailgun
16:39chouserif 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:40lpetitI 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:40chouser s/now/new/
16:40kotarakztellman: It does no classloader trickery at all.
16:40kotarakztellman: but I get the impression we are talking about different things.
16:40ztellmankotarak: so how does my #'user/a not shadow your #'user/a?
16:40ztellmanin our separate repl sessions
16:41ninjuddztellman: they would be the same
16:42ninjuddthat is currently what happens with cake if you open two repls in the same project
16:42kotarakztellman: 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:43ztellmanthat feels like a leaky abstraction to me
16:43kotarakztellman: that's how the IDEs work
16:43ztellmancake's process-per-project seems reasonable
16:43kotarakztellman: ok. rowing back. That
16:43kotarakThat's how VC works
16:44chouserthe 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:45kotarakchouser: bingo.
16:45@rhickeychouser: messages are tagged with ids
16:45chousersomewhat harder is sending (prn :hi) and (prn :lo) at the same time and separating the responses
16:45chouserharder than that (future (prn :x)) and (future (prn :y))
16:45kotarakchouser: why? Have different repl "sessions" with different ids.
16:45@rhickeywow, this is way out. we need to determine what "session" means
16:46chouserright
16:46@rhickeya session could have its own set of 5 queues
16:46chouserrhickey: that's what http://gist.github.com/603361 now demos, but I'm not sure if it makes sense
16:47chouserbecause of the future :x/:y case above
16:47ninjuddbut should you be able to connect to someone else's 5 queues? like tmux or screen
16:47kotarakFor 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:47chouserninjudd: that's a different question. sounds like fun to me.
16:48chouserkotarak: but doesn't handle future :x/:y, right?
16:48chouserkotarak: even if you block waiting for the future to complete?
16:48kotarakchouser: It could if the connection was long lasting, but it can't because vim is too limited for that.
16:48astoddardWould 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:48lpetitchouser: w/regards to separating things that come from printing simultaneously, there's simply no solution I guess.
16:48@rhickeyor a server could multiplex its input queues and have 3 output queues per client/session, providing clients identify their identity in the message
16:48kotarakchouser: but there is not technical reason it could not do that.
16:49chouserkotarak: sure there is. how does the thread in the pool know which session to write to?
16:49ninjuddi 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:50ninjuddif you really want to be sure where a future prints, you can rebind *out* inside it
16:50kotarakchouser: 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:50ohpauleezastoddard: clojure.string
16:50ohpauleezall the util methods got promoted
16:50ohpauleezastoddard: http://clojuredocs.org/Clojure%20Core/clojure.string
16:50chouserkotarak: but calling future may not spawn a thread, it may use an existing one. nailgun really does this?
16:51chouserohpauleez: except the ones that got deleted. :-P
16:51@rhickeyyou 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:51ohpauleezchouser: Yes, except all the ones that got deleted :)
16:51kotarakchouser: ah. Ok. That's bad. No. It uses ThreadInheritableLocal or something similar cryptic. So it probably doesn't work with futures.
16:51@rhickeyone gatekeeper per JVM
16:52chouserkotarak: similar issue of course with agents and their pools
16:52astoddardohpauleez: Thanks, don't know how I missed clojure.string
16:52ninjuddrhickey: the session-id in the CONNECTED message could be used for that
16:52ninjuddthough i suppose you would need a way to tell the repl server about new session ids
16:53chouserrhickey: 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@rhickeyninjudd: the connected stuff is for the mq, you can't use it for app logic like that
16:53ninjuddrhickey: why not?
16:53chouserninjudd: I imagine it doesn't get proxied
16:54ztellmanrhickey: when you're advocating for websockets, do you mean that they should be native to nREPL? Why not just have another proxy?
16:54chouserztellman: definitely another proxy
16:54@rhickeychouser: other than with-bindingds et al?
16:54@rhickeybound-fn
16:55ninjuddchouser: i'm just saying you can use that as a unique id and add it to your queue paths
16:55ztellmanchouser: okay, so why all the angst about dependencies?
16:55kotarakDon't forget System/in and friends.
16:55kotarakI mean System/out.
16:56chouserrhickey: hm. I guess that's what existing repl servers have to do now anyway.
16:56@rhickeyninjudd: that sessoin is the id between the client and the mq, not the client and the repl-server
16:56chouserninjudd: the repl-client and repl-server each connect to a proxy. each gets their own session id and neither sees the other's
16:57chouserztellman: stomp itself is also a dependency, server and client
16:57ninjuddrhickey: 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@rhickeychouser: aren't we implementing stomp ourselves? so no deps?
16:57chouserztellman: as much or more angst is there as with websockets
16:58chouserrhickey: yep, ninjudd's probably half done already.
16:58ztellmanyeah, I thought this was going to be a cleanroom version of stomp
16:58ninjuddhaha
16:58chouserztellman: same for websockets I hope
16:59ztellmanchouser: 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@rhickeythe easiest way to do this correctly is to use a real mq in between while writing the repl client/server
16:59polypusis contrib 1.3.0-alpha1 up yet?
16:59ninjuddi've created a repo and typed about 10 lines of code, so yeah... half done http://github.com/ninjudd/clj-stomp
16:59@rhickeythen, sub in a proxy
16:59@rhickeythat way you know it will work over a real mq
16:59@rhickeyand you haven't conflated the roles
17:00chouserrhickey: 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@rhickeychouser: what socket? client and server don't know about sockets
17:01polypusis [org.clojure/clojure-contrib "1.3.0-alpha1"] available through lein?
17:01chouserstreams?
17:01clojurebotduck-streams is now clojure.contrib.io
17:01ztellmanchouser: wait, I may have misread that; are you saying there should be a cleanroom version of websockets as well?
17:01@rhickeychouser: but no, a queue data structure could be used in proc
17:02chouserrhickey: right, ok.
17:02@rhickeymore indirection
17:02chouserthat's not quite what I was thinking, so I see what you mean.
17:02chouserztellman: that's what I'm saying, yes.
17:02ztellmanchouser: why?
17:02ztellmanif you want a web frontend, just run a different process against the message broker
17:03chouserztellman: so I can add an nrepl thread to some process and point my web browser at it.
17:03chouser s/thread/lib/
17:03ninjuddztellman: right clojure shouldn't have to use websockets at all as long as the broker supports it
17:03@rhickeyin fact, you should write the repl client and server with stock java stomp clients, then sub in our stomp
17:03polypusnever mind, found new form [org.clojure.contrib/datalog "1.3.0-alpha1"]
17:03polypus
17:04ztellmanchouser: so the message broker will be in-process?
17:05ninjuddztellman: it can be, or not. shouldn't matter
17:05chouserright
17:06ztellmanok, 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:06chouserthe 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@rhickeyztellman: how so? the in/out/err etc are inherent complexities of remote repl
17:07chouserbut 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@rhickeymq style logic allows you to multiplex them sensibly
17:07ztellmanrhickey: if I understand this correctly, in/out/err/eval/response are all going through the message broker
17:07@rhickeyztellman: yes, and?
17:08ztellmanrhickey: so why can't a separate web-facing process forward messages to it through the message broker
17:08@rhickeyztellman: I don't see where the web comes into it
17:09ztellmanrhickey: this conversation started re: websockets
17:09kotarakI'm I right in the assumption, that the stomp stuff is just envelope?
17:09chouserztellman: it absolutely could. but I'd like that particular feature without requiring a separate process out there
17:10chouserkotarak: yes, though I'm tucking a few custom headers in there just for nrepl
17:10@rhickeyhttp://jmesnil.net/stomp-websocket/doc/
17:12@rhickeyso, 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:12chouseror custom headers
17:12chousertype: in, type: err
17:12@rhickeychouser: yes, fine, didn't see that support
17:13chouserthat was my original thought with stomp, before someone mentioned multiple destinations
17:14chouserthat means you only have to subscribe once. *shrug*
17:14@rhickeychouser: just wondering if it makes the server/client easier or harder to write, or more or less responsive
17:15@rhickeyone subscription sounds easier
17:15chouserI wonder if it changes promises about order of messages at all
17:15ninjuddone other benefit is that is may assure that the relative ordering is correct
17:16chouserninjudd: jinx!
17:16ninjuddhehe
17:16@rhickeychouser: I hope not, who can tell the interleaving of e.g. *out* and output anyway?
17:16ztellman*err*'s position relative to *out* might be useful information, though
17:17chouserztellman: can't bet on that -- those flush inconsistently
17:17@rhickeyright
17:17chouserI guess that's true of *out* and return value too.
17:17@rhickeyright
17:18chouserthough for the latter the server could promise to flush *out* before sending return-value
17:18chouserand then if the mq swapped them everyone would be sad.
17:18@rhickeybut if, e.g. accessing a queue or connection must be single threaded, then these things will have to block each other
17:18chouseror queue up
17:18@rhickeychouser: still contention at the queue
17:19chouseryeah
17:19@rhickeybut not much
17:19@rhickeyclients will likely be happier with one subscription
17:19@rhickeybut who knows
17:19lpetithmm
17:20lpetitprobably depends on the API of stomp impls, and the out of the box facilities to plug hook functions in both scenarios
17:20lpetits/stomp impls/stomp client impls/
17:21sexpbot<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@rhickeylpetit: I doubt any have the ability to route to separate functions based on our custom headers
17:21@rhickeybut all will allow separate functions per subscription
17:21lpetitso enter the multimethod world
17:21lpetitok
17:21lpetit(at least ! :-) )
17:22ninjuddthere is the selector header for subscribe, but it has to be supported by the broker
17:23lpetitchouser: you can also provision a place for an additional header meta data, for cases where nREPL will play in OSGi-like land :)
17:23ataggartrhickey: 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@rhickeyataggart: links are good
17:23ataggarthttps://www.assembla.com/spaces/clojure/tickets/445
17:23@rhickeythanks
17:24lpetitchouser: 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:24lpetit#445
17:25chouserlpetit: can probably handle that in the code you send, can't you?
17:25lpetitdoesn't sexpbot or clojurebot have a facility for generating clojure links
17:25chouserhm. maybe your idea is better.
17:26lpetitchouser: it's a fresh idea, though.
17:27@rhickeyataggart: it will just make overload resolution more complex. Also, makes you more dependent on representation, so I decided to make you specify
17:27lpetitchouser: 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:28lpetitmay be used to change *bundle* in the repl session
17:28jjidowhat are the allowed characters in identifiers? I need to name a "private" var
17:29@rhickeyataggart: you can try it, but your chances of not breaking something are slim
17:29@rhickeyataggart: seems like something to do differently in cinc
17:30ataggartrhickey: 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@rhickeyataggart: 42 was an int, now it is a long.
17:37cpfrHey, what ballpark is clojure's speed in?
17:37cpfrfaster than python, slower than java?
17:39lancepantzyes, and sometimes :)
17:39lancepantzor arguable, and arguable
17:39cpfrthanks
17:40cpfrjust trying to reason about where it makes sense to use it
17:40ataggartIt can be as fast as java. It depends on what you're doing and how you're doing it.
17:40cpfrsince right now I am just using it as nicer glue for lucene and hadoop
17:41kotarakcpfr: got code which is on par with Java, but ugly
17:42cpfrkotarak, anything macros can't clean up?
17:42kotarakThen the macros are ugly
17:42jjidoHow to? Unroll optional named arguments. Callers should not have to wrap optional named arguments in a map literal:
17:42jjido(release-sharks 2 :laser-beams true)
17:43lancepantzjjido: (apply hash-map opts)
17:43ataggart(defn release-sharks [n {:keys laser-beams other-key etc}] ...)
17:43amalloyjjido: http://tinyurl.com/2caflx5 for a description of legal symbols
17:43jjidolancepantz: that works on a list of :key value?
17:44lancepantz-> (apply hash-map '(:foo "a" :bar "b"))
17:44sexpbot⟹ {:foo "a", :bar "b"}
17:44ztellmanjjido: (fn [x y & opts] (let [opt-map (apply hash-map opts)] .... ))
17:44amalloyjjido: (defn release-sharks [& {:keys [laser-beams]}])
17:44ztellmanto fill out lancepantz's answer
17:44ataggartyou don't need to do that. the :keys destructuring was added precisely to handle this situation.
17:45amalloyataggart: jjido is asking how to avoid having the caller construct a map
17:45jjidoztellman: thanks
17:45ztellmanattagart: it wasn't clear if he wanted to enumerate all the optional keys
17:45ataggartyes. I'm agreeing with your reply
17:45ataggartI was just late ;)
17:45ataggartand incorrect in the format
17:46ataggartthat's what I get for not yet installing clojure on this new machine.
17:46amalloyztellman: my destructuring version is shorter and clearer, isn't it? and as of 1.2 it's identical
17:46jkkramer(defn release-sharks [n & {:as opt-map}]) is also shorter
17:47ztellmanjkkramer's is identical and better
17:47ataggartbut missing the binding of the relevant values
17:47ztellmanI was just trying to clarify what lancepantz wrote
17:47amalloyah
17:48amalloyyes, mine requires enumerating the keys; a plus or a minus depending on what you want to do
17:49jjidoall right, but if there are additional (unnamed) arguments can I extract that too?
17:50jkkramer(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:51amalloyjkkramer: oh, sexy. didn't realize you could combine :keys and :as
17:53jkkrameramalloy: ya. :as, too
17:54jkkramer,(let [{:keys [a b z] :or {z 10} :as opts} {:a 1 :b 2 :c 3}] [a b z opts])
17:54clojurebot[1 2 10 {:a 1, :b 2, :c 3}]
17:55jkkramerer, :or too
18:08jjidothat does what I want: (defn sharky [& more] (let [{:as opts} (drop-last 2 more)] (opts more)))
18:13ossarehis there a room for Ring specific questions?
18:14lancepantzossareh: #clojure-web
18:14ossarehnice, cheers!
18:16cemerickWell, the channel was certainly busy while I was gone. :-)
18:17jweiss_if I want to apply the regex #".at" to "dog cat bat" and get back ("cat" "bat") how do i do that.
18:18ninjuddcemerick: welcome back!
18:18lancepantzcemerick: lol
18:19lpetitcemerick: chouser has almost finished the stomp deps-free impl !
18:20jweiss_ah re-seq
18:20lpetitno, just kidding
18:20cemerickYeah, i was disappointed to not find nrepl entirely finished when I got back!
18:20lpetit:)
18:20lpetitcemerick: ready to add osgi support backed in ?
18:20lpetit:)
18:45jjidoare we not allowed varargs in a protocol?
18:48jjidoThis protocol signature: (copy [self & bindings]) matches the following function: (fn [self foo bindings] nil)
18:48jjido:(
18:51ztellmanjjido: no, it's an unfortunate limitation
18:51ztellmanhowever, it's easy to create a non-variadic function in the protocol called function-name-
18:52ztellmanand then (defn function-name [x y & rest] (function-name- x y rest))
18:52cemerickjjido: rest args turn into an array argument, since defprotocol defines a Java interface
18:52jjidoztellman: I see
18:53cemerickyou'd call copy via (copy obj (into-array [rest args here]))
18:53cemerickHardly an ideal situation for sure.
18:55jjidocemerick: I don't really understand
18:55cemerickdefprotocol creates a hosty (thus Java) interface
18:55ztellmancemerick: websocket->nREPL bridge looks something like this: git://gist.github.com/603718.git
18:56ztellmanjust in case you were wondering
18:56ninjuddchouser, cemerick, ztellman, rhickey: done with a very rough stomp client implementation. feedback is welcome. http://github.com/ninjudd/clj-stomp
18:56cemerickjjido: and Java implements variadics with a trailing Object[] argument
18:57cemerickThus, you have to satisfy that (at least currently)
18:57ninjuddi'm somewhat new to protocols, so don't be to hard on me ;)
18:57jjidocemerick: yeah, but how do you declare Java variadics with defprotocol?
18:58cemerick(defprotocol Foo (bar [a & rest]))
18:58jjidocemerick: does not work (Clojure 1.2)
18:58ztellmancemerick: that doesn't work, rhickey implied that it never would
19:02cemerickdamn, I could have sworn I had done that before :-/
19:02cemerickjjido: sorry, my bad :-(
19:03jjidocemerick: np
19:04cemerickninjudd: FWIW, nREPL has been targeting clojure 1.1.0
19:05ninjuddcemerick: why?
19:05cemerickninjudd: because it's still used widely, and probably will be for at least some time to come
19:06cemerickas it is, lpetit may be peeved at me for not targeting 1.0.0
19:07ninjuddcemerick: well it would be easy to modify my code to not use protocols
19:07cemerickyeah, I just wanted to let you know
19:07ztellmancemerick: never mind about the aleph stuff, then, unless that can go in a separate process
19:08ninjuddcemerick: now that you mention it, i would like cake to still support 1.1 as well
19:08cemerickninjudd: I think it's a must, at least as long as Stuart's book is around
19:09ninjuddforever?
19:09cemerickI mean, selling in significant numbers
19:09ztellmanis his book actively misleading w.r.t. 1.2?
19:09ztellmanor does it just not explain the new features
19:10cemerickno, but it's reasonable that people will actively seek out the version specified in it
19:10cemerickStill the highest sales rank among clojure book, actually.
19:10ninjuddcemerick: 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:10ztellmancemerick: it's an excellent book, no surprise there
19:11ninjuddadded a short example to the readme.. should have done that before i posted it
19:15cemerickpresumably it'd be ideal if the java broker impl were used to automate testing against a live beast
19:17ninjuddcemerick: yeah, i agress. i just spun up stompserver before running the tests because i wanted to get to running the tests quickly
19:17ninjudds/agress/agree/
19:17sexpbot<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:17cemericksure
19:18ninjuddrhickey was talking about having a clojure broker implementation too
19:19jjidodo I need to repeat 'bindings' here: (new LinkedListClass (:head bindings) (:tail bindings) (:empty bindings)) or is there a short form?
19:21cemerickninjudd: yeah, it'd be necessary for the everyones-a-client architecture he has in mind
19:23ninjuddthat piece will be considerably more complicated, but not necessary to get started
19:24scottjjjido: not necessarily better: (let [{:keys [head tail empty]} bindings] (LinkedListClass. head tail empty)) (apply #(LinkedListClass. %&) (select-keys [:head :tail :empty] bindings))
19:28jjidoscottj: in the first solution, what happens if the keys are out-of-order?
19:29scottjjjido: in the :keys ... the order doesn't matter
19:29jjidoselect-keys should work
19:30jjido,(let [{:keys [foo bar]} {:bar 22 :foo 1}] foo)
19:30clojurebot1
19:31scottjthere 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:32scottj[foo bar] refers to the key names, not order.
19:33jjidook
19:49ninjuddcemerick: 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:56SirNickSo 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@rhickeycemerick: any further thoughts on stomp?
20:23ninjuddrhickey: 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@rhickeyninjudd: seems pretty simple
20:26Raynescemerick: It's widely used? By whom?
20:28ninjuddrhickey: 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@rhickeyninjudd: performance is not a reason to choose (or not choose) protocols
20:31ninjuddrhickey: 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@rhickeyninjudd: well, one likely other extender is to use an existing client
20:34ninjuddthats a good point
20:35lancepantzisn't the discussion moot with the req of nrepl supporting 1.1
20:47chouserbecause ` is not '
20:48chouseroh, sorry, was scrolled up. SirNick ^^^
20:49SirNickchouser: Yea I'm just confused how ` is handled by clojure. Is it transformed by the reader into the (seq) expression?
20:50dreishYou can use (read-string "`(...)") to find out.
20:50dreishBut yes.
20:50@rhickeyno interactive repl takes input from other than *in*, is there a reason to distinguish?
20:51chouser,'`(1 x ~x)
20:51clojurebot(clojure.core/seq (clojure.core/concat (clojure.core/list 1) (clojure.core/list (quote sandbox/x)) (clojure.core/list x)))
20:51@rhickeywe had talked about input distinct from *in*, but I'm trying to talk myself out of it
20:51chouserSirNick: contrast the result of x with ~x
20:52chouserrhickey: you mean using *in* for the expression to evaluate as well?
20:52@rhickeyof course a repl outputs to *out* , but for some reason I still want them separate
20:52@rhickeychouser: yes
20:53SirNickchouser: 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@rhickeyI guess intermingled input and *in* makes it harder to pair request/response
20:54chouseroutput is separate because it means something different -- I want it colored differently
20:54@rhickeybut then I wonder about *in* in general
20:55ninjuddrhickey: 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:55chouserfor 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@rhickeyimagining 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:56chouserSirNick: '`[(+ 1 2) ~(+ 3 4)] and `[(+ 1 2) ~(+ 3 4)]
20:56@rhickeye.g. (do (prn "what is your name?") (println "Hi " (read)))
20:57chouseris that an argument for mixed or separate input expr?
20:57@rhickeyhow will the clinet know the next thing it sends is not a command?
20:58@rhickeychouser: mixed I think
20:58ninjuddrhickey: hehe, that is exactly the kind of issue that made me think separate would work better
20:58@rhickeyninjudd: how could it work separate?
20:59@rhickeyall human typing needs to go to the same place
20:59@rhickeyor no interactive apps
21:00@rhickeysome of that typing will be commands, some potentially read from *in*
21:00ninjuddi 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:00SirNickchuser: 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@rhickeyninjudd: how do you enter two commands in a row?
21:01ninjudddon't end a line with a complete form, i suppose
21:01ninjuddyeah. it presents a problem for pasting
21:01@rhickeyninjudd: I don't think that works
21:02ninjuddyeah, the way cake works currently is with interspersed input, but i mulling over changing it. but pasting is important
21:02ninjuddrhickey: i think you're right
21:04ninjuddi suppose most people are :)
21:04chouserninjudd: indeed
21:05chouserother solutions seem convoluted
21:06chouseror maybe just broken
21:08@rhickeyso, 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@rhickeysince some read calls may eat some sends
21:08@rhickeyalso I presume send on newline, even if incomplete form?
21:08@rhickeyclient send
21:09chouserthat's not how my clojurescript client worked, but I don't think I handled interactive reading at all
21:09ninjuddrhickey: cake does not send until it has a complete form
21:09@rhickeywe're not imagining dribblling characters are we?
21:11ninjuddseems 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:12chouserthe terminal today does tricky things to avoid repeating a prompt when multiple forms are sent at once
21:13@rhickeychouser: that's perhaps a bit too fancy, but right now I'm more concerned about not needing to support dribbling
21:13chouserif the server supports incomplete forms line-at-a-time, how is it any harder to support dribbling?
21:14@rhickeychouser: maybe not, but seems wasteful, also how does one backspace/delete?
21:15chouserI 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:16ninjuddcemerick: 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:16chouserand you're right about skipping prompts -- that's up to the client UI I think.
21:16@rhickeyprinting the result of eval goes to output, all other *out* separate?
21:17chouserthe server knows when it's doing that printing that it's different, why not retain that info?
21:17ninjuddyou need to support incomplete forms anyway if you want stdin between forms to be streamed
21:18@rhickeychouser: 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@rhickeyI definitely want them separate, even if many clients will merge
21:19cemerickRaynes: what's widely used?
21:22cemerickrhickey: stomp seems like the best option
21:23@rhickeycemerick: did you see above about input commands and *in* needed to be the same?
21:24cemerickYes, though I was skimming the log.
21:26ninjuddit 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:27cemerickrhickey: 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@rhickeycemerick: that's bad
21:30@rhickeycemerick: and certainly not what I want
21:31@rhickeycemerick: how can we reconcile this with your initial vision?
21:31@rhickeyesp. - do you feel this will no longer satisfy it?
21:33cemerickrhickey: 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:34hiredmanspeaking of queues … http://intensivesystems.net/tutorials/stream_proc.html
21:34cemerickI 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:35cemerickI'm not sure I have the time to redesign from the ground up.
21:35cemericknot right now, anyway
21:36cemerickI suppose I may feel differently in a bit. I'm fairly frustrated with the status quo though.
21:38@rhickeycemerick: I wasn't aware you had so much implemented already, still thought you were brainstorming
21:39cemerickrhickey: really?
21:39cemerickthe http://github.com/cemerick/nREPL link has been out there a bunch
21:41jjidocan I set a record attribute after creating it?
21:41cemerickjjido: records are maps; use assoc
21:41Anniepoo_anybody have wise words on unit testing agents?
21:41@rhickeycemerick: I didn't know there was code, thought you were just starting when you advertised the repo
21:41jjidoor, can I declare a record before giving its definition
21:43jjidocemerick: not just maps and assoc just returns a new map -- doesn't change the original
21:43cemerickah
21:43cemerickjjido: that's generally considered to be a good thing :-)
21:44cemerickrhickey: Not sure what to say. That there's an impl has been at the top of the design notes for a bit too.
21:44cemerickAnyway, 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:45cemerickjjido: 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:46jjidoI have this: (def a (new recordtype 1 2 (new b))) (defrecord b [] protocolname (what [_] a))
21:46@rhickeycemerick: 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:47yayitsweiAnniepoo_: haven't done that before- is this related to your Second Life library by any chance?
21:47cemerickjjido: well, you have to define 'b' before creating a new instance of it
21:47@rhickeyI've got to go now, but let's see if we can't make the best of it tomorrow
21:47jjidocemerick: but b uses 'a' in its definition
21:48Anniepoo_I'm having trouble figuring out good ways to make unit tests for the
21:48cemerickjjido: yeah, that's not going to work
21:48cemerickrhickey: sure; have a good night :-)
21:48Anniepoo_blackboard/broadcasting thing, so if that's what you mean, yes
21:50Anniepoo_not sure how it's related.
21:51airolsonhas anyone encountered the repl in slime apparently not evaluating anything?
21:52airolsonwhen I hit return, the cursor moves to the next line and that's it
21:53jjidoI used alter-var-root cemerick
21:54cemerickjjido: that's sort of a function of last resort
22:02amalloyairolson: one of the reasons it does that is if you have an unclosed paren
22:02ossarehor an unterminated string
22:03airolsonamalloy: (System/getProperty "java.class.path") exhibits the behaviour
22:03jjidocemerick: would not be needed if I could tell Clojure that a will be defined later
22:04cemerickjjido: 'b' seems fairly wrong though -- shouldn't the 'a' instance be a field of 'b', rather than a top-level var?
22:06jjidono I need 'a' at top-level
22:06airolsonaha, my problem was using slime-fancy instead of slime-repl
22:07airolsonamalloy, ossareh: thanks anyway :)
22:10jjidowhat if I just do (def a) (defrecord b [] protocolname (what [_] a)) (def a (new recordtype 1 2 (new b)))?
22:10cemerickjjido: yeah, that will work -- though I doubt that you really need a at the top-level.
22:11cemerickIf you're just setting up a var for a forward reference, better to use (declare a) though.
22:11jjidocemerick: I didn't know about declare, thanks!
22:19sproust`Is there an equivalent to CL's (disassemble) in Clojure?
22:21cemericksproust`: at the moment, AOT-compile the code in question, then use javap
22:21cemerickEclipse has a bytecode viewer baked in, which is nice.
22:32sproust`That's neat.
22:33sproust`Eclispe, huh.
22:34cemericksproust`: yup -- since 3.3, it looks like http://archive.eclipse.org/eclipse/downloads/drops/R-3.3-200706251500/whatsnew/eclipse-news-all.html
22:35cemerickThere's a jad plugin for eclipse too, but I've never used it
22:35cemerickIt'd be killer to have single-action views per function, of course. I'd say that's perfectly within reach of ccw already.
22:43lambdalionI'm have some questions about clojurescript...
22:43lambdalionerr- I habe some
22:44chouserlambdalion: :-(
22:44lambdalionI'm wondering if 1) it is still being developed
22:45lambdalionwhy the sad face chouser? clojurescript, or my revision fail ;)?
22:46chouserclojurescript questions
22:46lambdalionaha...
22:46chouserit's badly out of date
22:46lambdalionI'm a pretty big fan of the CL lib "parenscript"
22:47lambdalionyes, that is one of my questions- I notice that the last commit was quite a while ago...
22:47hiredmantechnomancy: I think I've got lein using a in project classloader working
22:47chouserbut I'm not interested in putting effort into it until clojure-in-clojure is further along
22:47lambdalionand it seems like the lib relies on some earmuff vars that are no longer around in the compiler
22:48hiredmantechnomancy: tests fail, but they are all looking for files written in /tmp that no longer get written
22:48lambdalionI see...
22:48chouserlambdalion: clojurescript is about getting clojure semantics into javascript. If you only want clojure syntax on javascript semantics, there are options
22:50chouserscriptjure is one, I think
22:50lambdalionwell, 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:50cemerickThe most popular, I think.
22:50hiredmanlast I looked scriptjure didn't have a LICENSE
22:50lambdalionah- is that more analogous to parenscript?
22:51cemerickhiredman: EPL according to its only source file *shrug*
22:51cemericklambdalion: yes
22:51lambdalionI guess I was wondering.. if I wanted something like parenscript in clojure, would clojurescripy be something I could start from...
22:51cemerickor, at least insofar as I'm familiar with parenscript
22:52hiredmancemerick: no kidding, well that is good to know
22:52lambdalionbut I read through the source and.. seemed very much about the Java bits
22:52lambdalionwhich makes sense, I guess, if you want to preserve the semantics
22:53cemericklambdalion: clojurescript is clojure-in-javascript. scriptjure is writing javascript in parens. http://github.com/arohner/scriptjure
22:53cemerickMight not be exactly what you want, but I'd start there.
22:54lambdalionOK, thanks... I have always been really impressed by parenscript...
22:54lambdalionthe two macro namespaces are confusing, but...
22:55lambdaliononce 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:55lambdalionVut I hadn;t seen sriptjure- I will look at that. Thanks.
22:57lambdalionHmm- well that is what I have been thinking about...
22:57dnolenlambadalion: I've used scriptjure, it's ok, from what I can tell not as robust as parenscript.
22:57lambdalionI was just wondering if there was anything like a start on it already.
22:57arohnerlambdalion: dnolen can you guys go into more detail about what is possible with parenscript?
22:57arohnerI haven't used it
22:59dnolenparenscript: it translates CL -> Javascript
22:59lambdalionhmm...
23:00arohnera better way to phrase that question: "what advantages does parenscript have that scriptjure lacks?"
23:00lambdalionparenscript is actually surprisingly difficult to completely explain... the reference manual is here: http://common-lisp.net/project/parenscript/reference.html
23:01dnolenarohner: probably just maturity, it may have a sophisticated compiler as well - I haven't looked to closely at the source.
23:01lambdalionand the tutorial is here: http://common-lisp.net/project/parenscript/tutorial.html
23:01lambdalionbut...
23:01lambdalionparenscript has two macro-spaces...
23:01lambdalionand the implications of that are not immediately obvious.
23:02arohnerlambdalion: so that you can have "clojure macros" and also "javascript macros"?
23:02lambdalionyes, zactly
23:02lambdalionbut- that's hard to fathom.
23:03lambdalionbut even wiothout that generating parenscript from CL is really nice...
23:03arohnerlambdalion, dnolen : well if you have any suggestions on scriptjure, I'd love to hear them
23:04sproust`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:04lambdalionwith 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:05chouserlambdalion: 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:05lambdalionI 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:06lambdalionDid learn a bit about the compiler circa then from reading the code though, so not a loss.
23:07lambdalionyeah- I sis figure out that it was very different int intent from parenscript, which has almost the opposite philosophy
23:07lambdalionerr- did fugure out
23:07dnolenarohner: will do, I used it briefly - I'm working on a CouchDB front-end that modeled after python-couchdb - type checked mappings.
23:08dnolenarohner: 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:10chousersproust`: that doesn't sound good. reduce won't work?
23:11sproust`(defmacro doseq* [seq-exprs & body] `(doall (map (fn ~(first seq-exprs) ~@body) ~(second seq-exprs))))
23:11lambdalionI think a straightforward port from CL's parenscript can't be done in anything llike what I imagine idiomatic clojure to be...
23:12sproust`chouser: I just wanted to temporarily accumulate the result of my doseq's body.
23:12sproust`chouser: rather than edit, I made a version that accumulates...
23:12lambdalionbut I imagine something like it could be made for clojure.
23:12cemericksproust`: see for?
23:13sproust`cemerick: of course. Reinventing the wheel. Thanks,
23:13dnolenlambdalion: 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:13dnolenlambdalion: metadata is magical thing.
23:13dnolen,(meta (with-meta (fn []) {:foo 'bar}))
23:13clojurebot{:foo bar}
23:16lambdalionI am following that code, but failing to follow the implication...
23:16sproust`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:17sproust`Basically, I have a single (pmap), when I replace it with (map) I get a clean exit from the command-line.
23:17chousersproust`: you just need (shutdown-agents) when your program is all done
23:18dnolenlambdalion: you can store data for latter reflection on core datastructures as well as fn.
23:18dnolens/fn/fns
23:18sproust`chouser: thx.
23:18cemerickchouser: do you remember what the issue was with switching the pools to use daemons?
23:18sproust`re. Agents: is there any fundamental reason that agents aren't put in a library, and are part of the core?
23:19chousercemerick: probably just programs that worked fine in the repl quitting too soon when run as scripts
23:19cemericksproust`: same could be said of any of the concurrency primitives.
23:19sproust`Seems to me a smaller Clojure is a more portable one, and thus stuff like agents would be better segregated into a module...
23:19sproust`Yes indeed.
23:19dnolenlambdalion: 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:20lambdalionalright, 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:20cemericksproust`: There's not a lot you could slice out and make it worth your while in terms of deployment footprint, etc.
23:21sproust`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:21hiredmansproust`: rhickey just mentioned possibly pulling in a whole message queue implementation into clojure
23:21cemerickchouser: I guess I don't see why an await is worse than (shutdown-agents)
23:22lambdalionsproiust: I agree- the concurrency bits are actually not at all the most compelling bits of Clojure, to me...
23:22cemericksproust`: there's certainly no requirement that other impls carry a full boat
23:22dnolenlambdalion: np. and I meant "Clojure not having objects-like-things at the time". Things have changed in 2 years.
23:22cemerickhiredman: That seems absolutely crazy to me.
23:22hiredmana little
23:23lambdaliondnolen: ah, I see- well I wasn't thinking about OO there- frankly I do OO only under duress ;)
23:23cemerickI can see the maven shade exclusion config already :-/
23:23hiredmanbut since I like queues, and have hornetq setup already..
23:23sproust`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:23chousercemerick: Yeah, I don't remember how it was decided to switch. I'm sure it's in the logs, IRC or ggroup. :-P
23:23lambdalionCLOS is more than OO though... at least the way that term is usually used.
23:23chousersproust`: except regex in python is painful. but other than that I agree with you.
23:24cemerickhiredman: feh. If we're to go by usage, then clojure should have jetty bolted in by now.
23:24sproust`chouser: why is it painful? Because of the absence of an aif-like idiom?
23:24sproust`mo = re.match(... ) ; if mo: ...
23:24lambdalionHmm- I think Python is a bit schizophrenic in this regard.
23:25hiredmancemerick: :)
23:25chousersproust`: 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:25lambdalionIt falls somewhere between a good shell language and a good general purpose language a lot of the time.
23:26arohnercemerick: I thought the definition of curmudgeony was monotonic increasing?
23:26sproust`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:26cemerickarohner: I'm on a log trend of late, it seems.
23:26cemericksproust`: Every host will have a different mix of features. js is the penultimate example guaranteeing that.
23:27sproust`Urg.
23:27lambdalionSure- 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:27chouserthough now with workers, I wonder how much of the concurrency stuff we can get
23:27cemerickor down to a more fine-grained level, ClojureCLR's regex impl won't be identical to the JVM's.
23:27chouserlambdalion: compile clojure to python!
23:27chouserany day now
23:28lambdalionhmm- well Python would work OK for us except that we just can;t get enough speed here-
23:28sproust`chouser: with Python's
23:28hiredmanthere is a lisp -> python opcodes already
23:28chousercompile clojure to C++!
23:28lambdalionour algorithm takes about a second to run in Python...
23:28sproust`chouser: with Python's AST you could go straight to bytecode.
23:29lambdalionit must ecentually run in about 20=40 milliseconds
23:29lambdalionerr- 20-40
23:29cemericklambdalion: tried psyco?
23:29cemerick(which is semi-deprecated these days, IIRC? Still works, last I knew)
23:29lambdalionI must say though that if we had tried to develop it in C from the start we would bever have developed it.
23:29lambdalion*never
23:30sproust`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:30lambdalionYep- I agree.
23:30chouserbedtime. have fun, all.
23:30sproust`Nighty night.
23:30lambdalionIn pour case performance is so important that we wil rewrite in C entirely...
23:31hiredmanugh, can't you just generate llvm ir and then compile that?
23:31lambdalionBut 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:32sproust`lambdalion: What kind of problem are you solving?
23:33lambdalionhmm- a few parts, but basically automatic deformation of meshes bound to spline curves for people doing 3d character animation.
23:34lambdalionIt can't be too fast, and will never be fast enough....
23:34lambdalionthe python is for prototyping, but...
23:35lambdalionit 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:35sproust`/?
23:35clojurebotmake 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:36lambdalionon the other hand developing the algorithm in C++ would be even worse.
23:36hiredmanclojurebot: botsnack
23:36clojurebotthanks; that was delicious. (nom nom nom)
23:36sproust`lambdalion: is this for a post house?
23:36lambdalionwell we have two choices- cPython or c++
23:37lambdalionit is meant for a commercial Maya plugin
23:37lambdalionI imagine that clojure 1.3 or 1.4 might be close to fast enough- that is Java might be close.
23:39lambdalionbut we wouldn;t be able to use it without undue work...
23:39lambdalionthe lot of plugin developers is living with the dicisions of the software you write plugins for.
23:39lambdalion*decisions
23:41cemericklambdalion: 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:44lambdalionhmm- to be honest, compiling clojure to C had not even occurred to me...
23:47lambdalionI'm not sure how I would go about that, actually...
23:47hiredmanlambdalion: http://gist.github.com/223246
23:47cemericklambdalion: well, you don't have to worry about compiling to C, just with translating to scheme
23:48lambdalionI guess if the scheme compiler compiles to C you just need to compile Clojure to scheme, but...
23:48hiredmanthe previous gist http://gist.github.com/222974
23:48lambdalionif the point of using C is performance you would need to have quite a bit of control over _two_ stages of compilation.
23:51lambdalionThe 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:51lambdalionGotta say though that that clojure->scheme->->C idea is very interesting...
23:52lambdalionmaybe not applicable for what I am doing now, but...
23:55dnolenclojure->javascript->V8 ?
23:56lambdalionActually 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:56lambdalionfirst time I was introduced to the idea of functions that returned functions...
23:58lambdalionNot sure about the V8 stage though...
23:59sproust`If you're gonna bother writing out Scheme, why bother with Clojure in the first place.