4 ms·
I'm a very long time Python developer, but also did a project in Clojure, a type of lisp, over the last year. There is no comparison between the Clojure REPL a
by edanm 2y ago
I'm a very long time Python developer, but also did a project in Clojure, a type of lisp, over the last year.
There is no comparison between the Clojure REPL and the Python REPL. Python's is just literally a shell that you connect to and can run commands in. The Clojure REPL is far closer to a Python Jupyter notebook (if you know about it) built into your editor - it's a long-running process to which you can send commands all the time. But because of the way lisp is structured, and because of the tooling, you can just write Python code in the file you would normally use, stand on one line, and hit a command to get it sent to the REPL and the output of it written in the editor.
It's... hard to explain how powerful this is, and how much better things could be if we had similar tooling in Python.
Note: I still much prefer Python for many reasons, but this one aspect is something that I also used to think (yeah, Python also has a REPL) and I realize now that I had no idea what power this really has in lisp-world.
- bcrosby95 2y agoI try to tell my friends this and they accuse me of "gatekeeping" REPLs and that I'm an old man yelling at the cloud.
- iLemming 2y agoIt's actually not that hard to explain, yet without experiencing it firsthand, it is hard to see what this REPL fuzz is about. So, let's take a minimal, simple example: if True: print("Hello, Python!") and the equivalent code in Clojure: (when true (println "Hello, Clojure!")) In Clojure, you can send any expression fragment like a single symbol, list or even incomplete code and it will be evaluated according to its context. So, you can sent `true`, you can send `println` and you can even send `(when true println)` or `(when true (println))`, or even `(when true ,,,, (println))` (you can replace commas with line breaks if you want) and it will still be evaluated. In Python, you can send `True`, and you can send `print`, but you can't send `if True: print` (even with corrected indentation), because Reader would have hard time making sense of that. In Python, you need to adhere strictly to its syntax, and partial expressions that don't form a complete statement won't be evaluated meaningfully. In contrast, Clojure's REPL can work seamlessly with code fragments because the underlying representation of code is just data structures that are always valid within the REPL context. What makes it mind-blowingly cool is that you can send these expressions to a remote REPL without any transformation, serialization, or encoding, because it's not just code — it is data. In fact, some teams do just that. They'll keep an open socket on a running app, possibly performing somewhere in the cloud, so they can interact with it in real time. Putting aside the notion that this might not be the greatest idea, let's agree that this is a cool feature. The famous example of that is when something broke on Deep Space 1 (DS1) spacecraft in 1998, the team was able to fix it via REPL, see https://www.youtube.com/watch?v=_gZK0tW8EhQ https://www.youtube.com/watch?v=_gZK0tW8EhQ - "The Remote Agent Experiment: Debugging Code from 60 Million Miles Away" Sure, yes, Python is great, but when it comes to REPL stuff, you simply need a Lisp. It really is an amazing feeling when you can, for example, poke into any HTML element on a page dynamically, directly from your editor. Sure, you can do that with devtools in the browser, but it's not the same. You still have to switch to the browser; you can't type statements that are too long; and it's just not very convenient. Very nice (now years old) example is when Bruce Hauman showcased developing a "flappy-bird" clone - he would tweak the params, or straight change the code in his editor and the bird in the browser would fly differently, it's literally like writing code while playing a video game. Or Sam Aaron, writing music with Overtone is another great example. Another, more practical example is when you're exploring API response results, if you have REPL - you can send a single request and then dig through the data - group it, slice it, dice it, sort it, etc., something seemingly simple like this would require a bit more effort with any other language. I have my editor connected to a Clojure REPL instance at all times; I never know when I might need it.
- lucygoosey 2y ago[dead]
- dragonwriter 2y ago> The Clojure REPL is far closer to a Python Jupyter notebook (if you know about it) built into your editor - it's a long-running process to which you can send commands all the time. [...] > It's... hard to explain how powerful this is, and how much better things could be if we had similar tooling in Python. It would be kind of odd if we didn't, given what ecosystem Jupyter comes from. Sure, it's kind of surprising that the editor to integrations to do this haven't been around for a long time, but... https://code.visualstudio.com/docs/python/jupyter-support-py https://code.visualstudio.com/docs/python/jupyter-support-py
- edanm 2y agoI haven't looked at this specific plugin in a while, so I might be wrong, but from a quick glance (and from vague memories), it doesn't seem like the same thing. Look, I've been using Python professional for 16 years, and ever since starting to use Jupyter 7 years ago, have been a huge fan and proponent of Jupyter. But the Jupter model is different from the Clojure "true REPL" model. The main difference is that in Jupyter, you're doing something that is outside the normal files you use to write code. Both by writing in cells, but also you're physically in notebook files which are not part of a "regular codebase". Sure, if you're doing standalone analysis work or something, that makes a lot of sense. But if you're, say, writing the BE of a webapp, then you'd have your normal Django or whatever .py files, and separate Jupyter files for one-off analysis, or for writing testing code, etc. In Clojure, those can be unified in a way, both in the development process and in the future. Meaning, you'd start off with the equivalent of your Django .py file, you'd make a special "smart comment" which doesn't get executed normally, but which you can manually execute via an IDE command, you'd write some code there, and once it's working, you'd move it outside the comment to the "regular" part of the file. You've now essentially iteratively developed a new function that is just part of your normal codebase. And the "comment" that you wrote all the testing code in? That comment is still part of your file. You can use it to document the way your code runs, but in an interactive manner - anybody chancing on this file can just execute commands out of that comment and immediately see what they do. It's... hard to explain, but it's a really powerful model, that completely obliterates the line between "exploratory" code like writing in Jupyter, and the "production" code that ends up in your actual codebase. If you've never seen it, I highly recommend you look for a good video example of Clojure REPL-driven development.