Hi,

After Rich's suggestion at the recent NYC meetup, I had a
detailed look at inferior-lisp vs. Slime, and nREPL, read
Chas' document, wrote a bit of code, tried to figure out the
issues for myself; here are my conclusions on nREPL:


- In the Slime/Swank model, there is a single IDE that
  connections to N possible types of LISPs via a rich
  protocol (and a lot of corresponding work on the
  workflow/GUI side in Emacs in the various fancy Slime
  functions I discussed at the meetup).

      Emacs/Slime -> Clojure, sbcl, clisp, Allegro, etc.

  My understanding of nREPL is that it inverts the problem
  by making M different IDEs able to connect to one type of
  LISP VM (Clojure).

      Emacs, Eclipse, NetBeans, whatever, etc. -> Clojure

  One of the assumptions is that by keeping nREPL simple the
  various clients will send whatever necessary Clojure code
  they want in order to perform the same common tasks that
  the Swank protocol already describes. I think that this is
  touted to be "powerful" because you can eval anything you
  like, i.e., "just send it some clojure expression you
  want". But from my POV, it only serves to move the
  complexity from the server/VM (currently in swank-clojure
  and the protocol) to the client/IDE.

  I think this is wrong, because every single IDE client
  will have to adapt itself to the various changes occurring
  in the Clojure VM as it evolves. This is just creating M
  times the amount of porting problems (for each client). By
  keeping the complexity on the server, every IDE that
  speaks a common protocol (*) works between versions.

  One could argue that a rich client library could be
  included that provides similar functionality that is
  currently provided by swank-clojure, i.e. the problem is
  lessened, because all the clients now share the same
  client library, so you port over the client lib and
  recompile and that should be enouhg. But what language do
  you do this in? Clojure itself? Pure Java? What about the
  Emacs-LISP client? Then you have a problem of having
  multiple client libraries that need be ported.


- I take another issue at nREPL: if someone is going to
  implement a request/response protocol that supports only
  generic requests (because the complexity should live in
  the client), why bother at all, why not instead just make
  it a really, really simple network REPL, without any
  protocol at all? e.g. all input means "eval", output is
  just output, no ids no nothing.... just a socket that you
  could connect to with telnet and have a repl right there,
  no protocol. telnet localhost 4005, type "(+ 2 2)" at the
  terminal, see "4" appear. That's it.

  I think it would be pretty straightforward to extend
  Emacs' inferior-lisp-mode to support talking to a socket
  like that instead of having to start a subprocess. This
  would give you "vanilla" communication with a live Clojure
  VM without having to start the VM from a parent process. I
  rather like this idea; it's the simplicity you currently
  enjoy with inferior-lisp, but over a socket; simple, can't
  break.

  IMHO if people will bother implementing a request/response
  protocol, why not just stick with a rich protocol like
  Swank's? It'll just be reinventing the wheel otherwise.


- Another problem with Slime that turns people off is the
  weirdness in where the output goes. To detail the
  weirdness:

  1. Return values get rendered in the Emacs minibuffer 

  2. stdout of the main thread goes to the *slime-repl* buffer

  3. stdout of all the other threads go to the console of
  the VM, because they inherit System/out 

  4. Side-effects from converting return values to string
     (i.e., from lazy seqs, e.g., (map println (range 10)))
     appear in the minibuffer too, interspersed with the
     return values.

  I think a fair bit of that weirdness can be addressed
  easily:

  - I already coded a fix for (4) in my clone of
    swank-clojure.

  - (2) is normal, that's what you expect.

  - (3) can be addressed in 1.3 by setting up a suitable
    binding to override *out* so that child threads inherit
    that that instead of the default *out*. The stream
    object that would replace *out* to should send a swank
    message back to emacs to have the output printed in the
    repl.

    Note that this isn't going to work always; pure Java
    code running in child threads could still output to
    System/out, the console (is there any way to hijack
    System/out in Java? I spent 10 minutes on it, it looks
    like not). Also, nREPL and even the simplistic
    telnet-like networked repl would suffer from the same
    problem.

  - (1) could be changed by adapting swank-clojure to return
    the result as an output command from swank, and to
    always return 'nil' as the result. IMHO this could be an
    option to Swank--I personally find it neat to have two
    separate places to print stdout and the result of the
    expression, and the slime repl vs. the minibuffer
    provide that, but I can see how that's a little weird.

  Those changes would make Slime behave a lot more like
  inferior-lisp-mode; a lot less strangeness, one place for
  all output, the *repl* buffer.


I'm curious to hear people's thoughts. I don't have a ton of
experience with Clojure and I also might be misled regarding
the aims of the nREPL project. What's bothering people with
Swank's protocol anyway?

In any case, I think it would be really cool to implement a
simplistic networked repl and adapt inferior-lisp-mode to
work with it (without a protocol), and fix the couple of
warts in Slime so that at least output doesn't go to three
different places.

--
M.



(*) Please note: I am aware that only Emacs supports the
    Swank protocol right now but I don't see why other IDEs
    couldn't support it too--it's just made up of LISP forms
    after all; in other words, if someone wants to replace
    the swank protocol by an equivalent one with a different
    encoding I don't really see the point. Anyway, for this
    discussion I'll assume emacs-rex is a suitable enough
    protocol; in fact, I think it probably is, because it
    has already proved itself with a large number of LISP
    environments, it has "history". In any case, that's a
    separate discussion. I think of emacs-rex as just "the
    protocol" and that other IDEs could implement it to talk
    with swank-clojure.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to