5 ms·
> However, working with Clojure and Scheme, I understand the power of repl driven development that is difficult to explain outside the experience of it. The on
by throwaway894345 5y ago
> However, working with Clojure and Scheme, I understand the power of repl driven development that is difficult to explain outside the experience of it.
The only lisp I've dabbled with was Racket and I found the repl driven development to be a frustrating necessity. I would spend a lot of time trying to figure out the actual type of the thing that I a given function (even a stdlib function) needed, and futzing around in the repl seemed to be the fastest way to do it, but it was still quite slow.
It reminded me a lot of my extensive experience with Python where things that are easy in, say, Go, are quite hard. People rave about their repl, but it feels like they're comparing it to a script iteration loop rather than static analysis tooling.
That said, I completely buy the argument that Python's REPL is particularly bad and that there are other use cases where REPL-driven development shines. My mind is open, but these are the sorts of experiences the pro-REPL folk should be prepared to engage with in their evangelism. :)
- ReleaseCandidat 5y ago> People rave about their repl, but it feels like they're comparing it to a script iteration loop rather than static analysis tooling. You do know that statically typed languages have REPLs too? Like the ML family, including Haskell. And when using something like a Jupyter notebook with a kernel for your compiled language https://github.com/gopherdata/gophernotes https://github.com/gopherdata/gophernotes you can do similar interactive programming. REPLs are about trying out ideas or changes. Lisp REPLs take that a step further, as you interact with and in your whole actually running program.
- throwaway894345 5y ago> You do know that statically typed languages have REPLs too? Like the ML family, including Haskell. I do, but that I don't see how that relates to the bit of my post which you've quoted. I certainly didn't claim or imply that REPL and static type systems were mutually exclusive, only that REPLs are a poor substitute for many static analysis tasks. > And when using something like a Jupyter notebook with a kernel for your compiled language https://github.com/gopherdata/gophernotes https://github.com/gopherdata/gophernotes you can do similar interactive programming. Yeah, I'm aware. I operate a large JupyterHub cluster (among many other things) at work. :) > Lisp REPLs take that a step further, as you interact with and in your whole actually running program. That sounds nice, but it's too abstract to persuade IMHO. Personally, it seems like REPLs can make certain feedback loops a bit faster, and to that extent they seem like a modest quality of life improvement; however, considering how lisp folks positively rave about them, I assume I'm missing something.
- ReleaseCandidat 5y ago> that REPLs are a poor substitute for many static analysis tasks. Maybe I should have asked you what you use the REPLs of statically typed languages for. I actually never used REPLs for that (neither in Python, CL, Clojurescript nor Elixir). > That sounds nice, but it's too abstract to persuade IMHO. Of course it is. I also didn't get it until I've tried it myself. That actually has been the main cause why I tried (Common) Lisp at all (well I had been using Emacs Lisp before, but that doesn't really count ;).
- FPGAhacker 5y agoI use repls a lot, both when I used clojure and now when I mainly use python. The reason for me is language exploration. I write my program and don’t always know how to do something and the internet is ambiguous. With a nice repl I can rapidly iterate trying different things and doing micro in-situ experiments to explore and understand how the language (or library more frequently) works. It’s very edifying.
- throwaway894345 5y ago> Maybe I should have asked you what you use the REPLs of statically typed languages for. I don't really use them, which is kind of my point. Once in a great while I'll do some quick testing in the rare case that using a REPL is actually faster than just running the program, but to even call that a marginal improvement in my quality of life would risk overemphasis.
- dunefox 5y ago> I assume I'm missing something. You are indeed, Rackets REPL is very barebones. Use Common Lisp with either SLime or Sly and Emacs.
- igouy 5y ago> You are indeed… How puzzling that you do not spell-out exactly what you believe they are missing.
- CodeGlitch 5y ago> Lisp REPLs take that a step further, as you interact with and in your whole actually running program With python, I can add a signal callback which calls the inbuilt breakpoint() function. This means I can send my application a given signal, let's say SIGTERM, and it'll drop into they python debugger whereby I can then drop further into the python REPL. Does Lisp provide more than that out of interest? Edit: ah I see hot reloading is a thing. Not explored that in python.
- brabel 5y agoYes, it was mentioned in the post: you normally get prompted not just when there's a breakpoint, but when your code calls something that doesn't yet exist, for example, or try to access a non-defined variable [1]... you have the option to "fix" the issue and continue from the same point, continue with a different value, or just let it crash... and there's stuff like profiling and de-compiling [2] which are all available directly from the REPL as well. [1] https://lispcookbook.github.io/cl-cookbook/debugging.html https://lispcookbook.github.io/cl-cookbook/debugging.html [2] https://lispcookbook.github.io/cl-cookbook/performance.html https://lispcookbook.github.io/cl-cookbook/performance.html
- ekidd 5y agoMany early Common Lisp systems had impressive error handling. Certain exceptions would automatically break to an interactive Lisp window. But Common Lisp also has a fancy system for recovering from exceptions. So after you replaced the broken function, you'd often see a list of "restart" points from where you could retry a failed operation. So even if you failed in the middle of a complex operation, you could test out a fix without needing to abandon the entire operation in progress. I'm not entirely certain if this was as useful as it sounds, in practice, but it was certainly very impressive.
- retzkek 5y agoThere was a book published just last year about the CL condition system for anyone who wants to better understand it (disclaimer: it's sitting on my desk but I haven't read it yet): https://link.springer.com/book/10.1007/978-1-4842-6134-7 https://link.springer.com/book/10.1007/978-1-4842-6134-7
- pdonis 5y ago> my extensive experience with Python where things that are easy in, say, Go, are quite hard Can you give some examples? This is not something I've encountered (although I have much more experience with Python than with Go so there is probably plenty in Go that I have not encountered). > the argument that Python's REPL is particularly bad What argument is this? This is also not something I've encountered. I use Python's REPL all the time and it greatly speeds up development for me.
- vindarel 5y agoYes, Python's REPL speeds up development, but Lisp's REPL (we should say image-based development model) is even more interactive! We never wait for a server to restart, our test data is live on the REPL, we compile our code function-by-function with a keystroke and we get instant warnings and errors, when there is an error we get an interactive debugger that pops up and allows us to inspect the stack, go to the buggy line, recompile, come back to the REPL, resume the execution from the point we want, objects are updated when a class definition changes and we can even control that… it's crazy. From time to time it becomes a mess and I restart the Lisp image, but it's about every two weeks :p I tried to explain more here: https://lisp-journey.gitlab.io/pythonvslisp/ https://lisp-journey.gitlab.io/pythonvslisp/ Note that I'm not a 10x master, I use CL for mundane, real-world tasks (access to an FTP, parsing XML, DB access, showing products on a website, sending email with sendgrid…), my programs had 1 trivial bug, I am more productive and I have more fun… Just to say it has its uses, even today, even with "all the libs" of Python (and btw, see py4cl).
- pdonis 5y ago> We never wait for a server to restart I'm not sure I understand. When I run Python's REPL, I'm running the interpreter on my local machine; I'm not talking to any server. The same would be true if I run the Lisp interpreter, but I don't see how that is any advantage for Lisp over Python.
- ahefner 5y agoStart your Python REPL, do your interactive development, measure your average time before aborting and reloading the python instance. How much time elapses? Minutes? Hours? When I've done Common Lisp heavily, I've lived in the same instance between multiple days up to weeks. This feels perfectly natural. Admittedly it is hard to justify why this difference is meaningful.
- p_l 5y agoScheme is remarkably less interactive than Common Lisp, though specifics depend on dialect of Scheme. Common Lisp is remarkably more geared towards interactive use, but while it does make it easy most of the time to be used with just minimal REPL - as in literal (loop (print (eval (read)))) - it's best to use integrated, enhanced environments like SLIME/SLY/SLIMV/etc or one of the IDEs (LispWorks, AllegroCL, Clozure CL IDE)
- didibus 5y ago> I would spend a lot of time trying to figure out the actual type of the thing that I a given function That's just because your were a noob. You hadn't learned and internalized the standard library yet, and you hadn't learned to understand flow and structure of types and functions and variables. I too when I started with Lisp had the same struggles, but they go away with expertise. That's why you'll hear people talk about "training wheels", when you program in a statically typed language with an extensive IDE doing a lot of static analysis for you, you basically operate constantly with training wheels on. You never really learn what class does what, what methods they have, what types things are, you rely heavily on your IDE. For example, ask an experienced Java developer to write some Java in notepad? They don't know what to import, where to find anything, completely lost, productivity hits zero. And I'm not degrading Java devs or that setup. What happens in Lisp is that you have to learn your language, you can't rely on an IDE or the compiler. In theory you could also learn Java to that level, stop using an IDE and you'll be forced to really know the language as well. Here's the kicker? Once you learn the language to that level, your productivity in it skyrockets! But until you do, its a slow crawl. And it's only ounce you've got that experience that the ability to change the program as it is running through a REPL really brings about speed, you don't use it to figure basic things like types and what standard functions exists, but to tackle real business logic or explore libraries and 3rd party APIs to get a grasp on those quickly. Take this from someone who went from strongly typed Java, C++, C#, ActionScript 3 to a Lisp. I'm now way more productive in Lisp. P.S.: Also, you'll have static analysis in Lisp as well, depending on which one and your setup. In Clojure, I have static analysis, an IDE, a connected REPL, and use all three actively.
- JetSetWilly 5y agoA typical standard lib may have thousands upon thousands of functions with many less commonly used arguments and options. If you are saying "memorise the lot" is the only route to productivity on lisp then I'm out, because that's unrealistic. And let's not get into libraries outside of the standard lib, am I expected to memorise XML parsers, graphics APIs, and so on as well? If you are saying "memorise what you commonly use" then that's fine, except that any typical program usually involves a lot of "lesser used" stuff as well.
- mateo411 5y agoWhy do you think the Python REPL is particular bad? What would you do to improve it? I think it works pretty well, but maybe I'm just used to it.
- throwaway894345 5y agoLast I checked you couldn’t await inside a REPL and various other idiosyncrasies. Lots of small paper cuts.
- phyrex 5y agoYou can’t even go into a namespace and change functions there
- randomswede 5y agoCode parsing in the Python REPL is different from that in Python source code files. Not MUCH different, but different. Specifically, if you try to paste a function definition that has blank lines in it, into the REPL, the first blank line will be interpreted as "end of function" and the rest of the function will become incorrectly indented garbage.