Live data from Hacker News

On Repl-Driven Programming

mikelevins.github.io

91–100 of 210 posts

Re: On Repl-Driven Programming

#91
post #73

Is there a simple way to get code I write in a lisp REPL back into my editor? That's the part missing for me and why I usually only use interactive shells (REPL or otherwise) for testing APIs or small pieces of code. I can't imagine writing a program in its entirety in a REPL.

You write it in the editor and send statements to the REPL. You're not just sitting looking at a command line. The REPL is a conversation with running state, but the conversation doesn't have to take place only through a single blinking terminal window. In proper REPL-driven development, the editor is fully integrated with the running session, and you can evaluate either in an attached terminal session or through you…

Yes, exactly. It's perhaps my fault for not making this more explicit in the essay, but the "repl" in "repl-driven programming" does not mean the repl window.

Re: On Repl-Driven Programming

#92

How is this different from, say, programming in Python and being forced to drop into a debugger whenever there is an error? The debugger also lets you see everything in the stack, modify definitions, etc. MATLAB and R both have options to drop you into a debugger if there is an error. Not sure if Python's debugger can do this, but other than that, this style of programming is perfectly doable outside of Lisp and Smal…

So go ahead and set up that working situation and try this:

Define a function foo() in one module that calls a function bar() in another one, but don't define bar().

Now call foo().

Now, in the debugger that you break into, give a definition for bar(), and resume the execution of foo(). Don't quit the program and restart it; that's cheating!

If that works fine, please tell me what tools you're using, because they'll materially improve my tools for some work I need to do.

Also, try this:

Define some classes and make a bunch of instances of them. Write a few methods on the classes. Start your program running with code that uses those classes and methods.

Now change one or more of the class definitions. Don't stop and reload the program! Again, that's cheating.

When you land in the debugger (you do land in an interactive debugger, right?) use it to inspect the stack and find out which classes and methods are on the stack and what's responsible for the breakage. Ask the Python runtime to show you all the functions, types, and values that are on the stack, and when you find the likely culprit, ask it to take you to the source for the version that's currently on the stack.

Now, while you're still suspended in the call stack, redefine the offending classes and methods and tell Python to use the new ones. Now resume the broken computation. If you hit another problem, use the same tools to find and fix that one, too.

After you've done all that, please let me know what your Python toolchain is so that I can use it, too.

Also, if that's all perfectly doable in Matlab and R, that's good to know. Let me know about those tools, too. I haven't had much occasion to use them, but that might have to change if they work that way, too.

Re: On Repl-Driven Programming

#93
post #18

Is there a modern non-Smalltalk, non-Lisp (or its derivatives) non functional imperative programming language that supports a "real repl" that the author is talking about? I don't know if that kind of environment is for me but I'd love to give it a spin. I have never found the REPL (the Python/Ruby REPL which is not a "real repl" according to this article) to be that useful beyond quickly playing with API of a librar…

Bash?

Shells in general are a great example IMO. They are what I'd maybe call repl-first environments, in that they are used primarily as interactive repls but can be used to write programs.

Re: On Repl-Driven Programming

#94

Having used Clojure and Common Lisp professionally, I think advocates for REPL driven programming universally overstate the utility of a first rate REPL. Yes, it’s nicer than Python’s. Yes, it’s convenient. No, I never ended up doing my development in the REPL first . Why? Because editing mistakes in a REPL usually sucks, because a REPL is not a text editor. What I ended up using heavily was REPL to file integration,…

As I said elsewhere, when I say "repl-driven programming", I do not mean "programming in a repl window", or "programming at a command shell". I'm talking about the runtime's read-eval-print loop, not the UI's repl window.

When I'm working, there is little or no migrating of code from the repl buffer to a file because it's already all in a file. I almost always work in a file. I write snippets in a file, send them to the repl with a keystroke, and build up the world incrementally as I discover what it needs to be. As the contents of the file get larger and more complicated, I move things around and organize them. It's a conversation with the repl, not an editing session in the repl window.

I don't consider any Clojure tools I know of to constitute a proper repl-driven environment, precisely because the language and runtime lack support for the kinds of programming and debugging that I've taken for granted for decades. If I can't inspect and edit and redefine everything in the runtime, it's not the full, proper set of tools.

I've written a good bit of Clojure code, and I'll happily do it again if I need to do something that isn't convenient in, say, Common Lisp, but I consider it an acceptable alternative to things like Haskell and Scala and F# and Swift, not an attractive alternative to Lisp and Smalltalk.

I do occasionally need to restart a Lisp environment because of some gnarly breakage I've committed, but it's pretty rare. Moreover, killing and restarting my favorite lisps takes about--wait, let me check--okay, a second and a half to kill a live app in staging and have it back up, fully-functioning.

Re: On Repl-Driven Programming

#95

I think it would help as well to list languages that have various levels of 'real repl' implementations. Wonder what modern (systems you can 'make money with') there are that support this. I know common lisp + smalltalk and worked with both and really liked them for these reasons. I miss this functionality all the time as it was far more efficient (to me!) than modern debuggers.

Isn't Python and Matlab a 'real' REPL? They are money makers.

It's not about whether they make money. It's about whether you can do absolutely everything needed to build your program interactively by talking to it while it's while it's running.

Re: On Repl-Driven Programming

#96

For Ruby users, pry gets you most of the features discussed in this post. You can get the error break loop, and drop into the live environment with binding.pry. Code can be added and expressions adjusted at this point. It’s very powerful and the only “debugger” I’ve ever needed for Ruby.

I've used it a good bit. When I'm using it, I miss the tools I have in Smalltalk and Lisp environments.

When I use Smalltalk or Lisp, I don't miss pry or the other tools I have when working with Ruby.

I do like Ruby, though. I probably like it better than any other language that isn't made of s-expressions. (Well, I like ML a lot, too.) But the whole time I'm working with it it just makes me want to write another Ruby implementation, but this time on top of a proper interactive runtime.

There is one, actually: MagLev, which is built on a Smalltalk runtime. As far as I can tell, though, it's dormant.

Re: On Repl-Driven Programming

#97
post #13

Definitions matter. A repl is a read, eval, print, loop. That means the code you enter at the prompt is converted from a String into literal data that can be evaluated (read). The data is then evaluated to produce a result (eval), and the result is then printed (print). If that's not what your REPL is doing then it's not a repl. That is not what's going on in e.g. python or ruby "repls". There is no "read" step here…

This seems extremely pedantic. Python and Ruby will “read” the string inside the “eval” function.

Other people are making the same point I'm about to make, but I'm going to try to clarify it anyway because, y'know, besides being a programmer, I'm also a technical writer, and I just have to scratch that itch.

Common Lisp source code (and the source code of its immediate ancestors) is not made of text strings. It's made of S-expressions, which are made of cons cells, symbols, numbers, and so on.

A text file of "Lisp source code" does not actually contain Lisp source code. It contains a text-based serialization of Lisp source code. Other serializations are possible (and there are things you can do in a Common Lisp repl to see some of them).

The "read" in "read-eval-print" means "deserialize the text into the source data that it's meant to represent".

This point is not trivial pedantry because the full power of the Lisp language is available to the read process, and can be brought to bear on how reading is done and what happens when you do it. Compilers for other languages certainly do read text strings and convert them into tree structures and so forth, but the difference is that those data structures are private to the compiler; the data structures that Lisp reads into are standard parts of Lisp's public API, as are the read function, the compile function, the eval function, the print function, and so on. It's all on the table for you to work with.

The same is true of the disposition of the s-expressions produced by the read process; you have an opportunity to bring the whole of the Lisp language to bear on those s-expressions before they are ever passed to (compile or) eval. Then, once again, what eval produces is S-expressions, and those, not strings, are passed to the print function. You once again have the opportunity to intervene in the process that produces the text serialization.

It so happens that I've spent the past six months working on an AI machine-control system written in Common Lisp, and every one of these capabilities was an important part of the work we were doing.

Re: On Repl-Driven Programming

#98

What are people’s thoughts on how using vs not using a REPL help or hinder one’s thinking as a programmer. Specifically I mean if you have no REPL and maybe a long compile time you’re forced to put a little more thinking and planning in up front if you don’t want to waste your time. You might be more meticulous in catching bugs. Whereas with a REPL you can throw stuff at the wall. If something breaks you can just twe…

I think it's a valid observation. Circumstances that make you think things through ahead of time compel you to learn things and gain skills that you would not otherwise learn and gain.

The other way around is true, too, of course.

But the intensely-interactive style of programming-by-teaching is the less common approach. In pretty much every thread I've been part of about the topic there have been commentators who've said they just weren't even aware of it as an option, who had no idea that full-featured repl-driven environments had ever existed or were a possibility.

What are the odds that such an obscure approach to programming has already attracted all the programmers who would benefit from it? Long odds, I'm guessing.

So my guess is that it's worthwhile to point out the option for the sake of people who would benefit from it but don't know they have the option.

For my benefit too, of course. I want more people to know about it, because that increases the chances that demand will rise. Rising demand increases the chances of greater investment in those kinds of tools, and reduces the chances of their extinction.

Re: On Repl-Driven Programming

#99
post #41
post #35

Earlier quoted context omitted.

> It is all a matter of tooling. I think the point of the article is that tooling can only get you so far. The abstraction they attempt to provide is leaky if the support for this style of development isn't firmly designed into the entire system.

Yeah, but in that regard developer culture is what matters. I have seen very few people actually using these kind of workflows back when Smalltalk and Lisp were more relevant (I used Smalltalk/V back then). It is like using gdb, many don't go beyond step, next, print, run, breakpoint and discover how powerful it actually is (same applies to other debuggers).

I am indeed claiming that tooling only gets you so far, if you don't have good support designed into the runtime.

I take you at your word that you didn't use the sorts of workflows I've described, but I did, and I still do, to the extent that I can, and it was common place among, for example, the programmers working on the bauhaus OS or the ones working on the SK8 development environment.

We kept images around as a matter of course for various purposes, for example.

Re: On Repl-Driven Programming

#100

For what it's worth, IPython's "autoreload" magic and Julia's "Revise" package get you _closer_ to what the author describes. In both cases, one can define functions/classes/structs in a file/module, load it in a repl, create objects etc, modify the file and have the changes propagate through to live objects

Closer but still so far. As soon as you have more than one module in Python it completely falls apart, despite any autoreload magic. It just isn't the same at all as REPL based programming. In Lisps you can write your entire program with an instance and a REPL running the entire time. No restarting the instance required. It works because it's just how Lisp works. A REPL is a trivial thing you can write yourself that…

> Whenever I think about it I can't quite put my finger on exactly what Python would need to make it the same. It's something to do with the way imports and namespaces work, though.

Python has a fundamentally broken module system, and Python 3 did nothing to fix it:

https://nedbatchelder.com/blog/201908/why_your_mock_doesnt_w...

https://docs.python.org/dev/library/importlib.html#importlib...

Post reply on HN