3 ms·
I think the major difference between the Clojure REPL experience and most other language's REPLs that I've worked with is the fact that Clojure REPLs can connec
by ss3000 7y ago
I think the major difference between the Clojure REPL experience and most other language's REPLs that I've worked with is the fact that Clojure REPLs can connect to a running stateful system (or a situated program as Rich Hickey coined it), and allows you to explore and manipulate the system's state and behavior dynamically at runtime, which makes it an incredibly powerful tool for building and debugging such a system.
Most REPLs I've used in other languages are strictly for evaluating individual commands in an isolated, stateless manner.
- barrkel 7y agoRuby's REPL, and particularly when enhanced with Pry (binding.pry), can function like this reasonably trivially. You can't connect to an existing system like attaching a debugger, but you can make a call to binding.pry or binding.pry_remote depending on a parameter. Usually Ruby is used with Rails, where in development mode modifying the source and repeating the request is just as easy.
- emidln 7y agoIn Python, twisted.conch provides an ssh transport and a repl implementation which is trivial to hook up in a live system. The ecosystem doesn't really support the use case though, so you end up building all tooling from scratch (tmux plus vimux helps a lot here). You also have to structure your code in a somewhat unnatural way for python, like using a dependency injection system to reload and trying to approximate clojure.core/in-ns.
- marcosdumay 7y agoConnecting through ssh to the machine and running a Python debugger there is a much better supported alternative that will give you a REPL capable of querying and modifying a running system. Also, you can avoid dependency injection with monkey patching. Lisp will give you a 2 way compiler, where you can change things and then save them into a source file, AFAIK, Python has nothing like this, but just changing a live system is well supported and common.
- emidln 7y ago> Connecting through ssh to the machine and running a Python debugger there is a much better supported alternative that will give you a REPL capable of querying and modifying a running system. ssh into an interpreter gives me perfect control and is reasonably well supported (as far as twisted things go). If you have tmux setup correctly, you can use emacs/vim to eval against your ssh'd python the same way you'd work locally. I've done this for over a decade. It's similar to how I use nrepl+clojure. You can't avoid dependency injection with monkey patching. You have to restart your system on certain changes or reload all of your modules. Further, you need a global reference as an entrypoint to your objects, otherwise you drop in with a debugger/repl and you, what exactly? set a breakpoint for the entire running application? No thanks, not in prod anyway. At least in Clojure, our best practices including using live REPLs for debugging/troubleshooting, but patching only when absolutely necessary. At my last gig, we had tooling setup to allow varying levels of modifications to a particular clojure app with full traffic, limited traffic, or no traffic (depending on what type of environment was required for debugging), and then tooling to auto-apply patches via a combination of zk+ssh+nrepl (only listens on localhost; the hosts and ports were defined in zk) for emergencies (when the system couldn't be restarted safely for some reason). Most of the time, however, the tooling would give you a session to a given app, and when you left the session, would restart the process (safely via load balancing), since it would be problematic to leave systems in indeterminate state.
- BiteCode_dev 7y agoI like how you just stated "this is a native killer feature", and immediately, 2 other comments stated, "well, with a bit of work, we can have half of this killer feature too in my language". Come on, I'm a Python fan, but no, we don't have anything close to that Clojure experience. And it's certainly not native anyway. I mean, twisted? Really? I co-wrote the book "Expert Twisted", and even I wouldn't be caught dead pretending it's simple. So how can you advocate to do this + ssh + reload() (which is very unreliable in python) as an alternative to what OP talks about. No language is perfect. Other techs have fascinating promises. Let's stop a moment and admire that instead of trying to sell our stuff all the time.
- agumonkey 7y agoThis is cultural tbh, Lisp went all in with repl style and added more features over time. Give it 10 years and jshell or python will have similar traits (possibly).
- yogthos 7y agoI think immutability plays a big role here as well. Clojure makes it natural to structure your code in a way where things can be reloaded individually without having to worry about global state. The REPL would be of much more limited use in a language where everything is coupled via shared mutable references. This can also be seen with ClojureScript where hot loading works reliably out of the box, while all attempts at do hot loading in Js are flaky to the point of not being of much use.
- lispm 7y ago> The REPL would be of much more limited use in a language where everything is coupled via shared mutable references. That would be surprising, since the REPL was developed for Lisp in the 60s, which actually works that way.
- pixelperfect 7y agoThat isn't a contradiction - the advantages of a REPL are greater for Clojure than for Lisp.
- lispm 7y agoFrom what I see that seems not to be the case. Reloading code in REPLs in Lisp is widely used.