[HN Gopher] On Repl-Driven Programming (2020)
       ___________________________________________________________________
        
       On Repl-Driven Programming (2020)
        
       Author : ivanvas
       Score  : 25 points
       Date   : 2022-05-05 18:54 UTC (4 hours ago)
        
 (HTM) web link (mikelevins.github.io)
 (TXT) w3m dump (mikelevins.github.io)
        
       | mbil wrote:
       | Used Clojure for ~4 years, doing REPL-driven development in
       | Emacs. Have used Ruby and Java since. Maybe it's a rosy
       | retrospection, but in terms of program production I think that
       | was the most productive I've ever been. Falling into a flow state
       | was much easier. Translating complex ideas into code was much
       | easier. Building constructs up piece by piece felt natural and
       | smooth. Sometimes I worry I'll never work in a LISP again.
        
       | ngcc_hk wrote:
       | Objective c could be. You can have undeveloped method ... if you
       | can make any unbanked message invoke debugger and continue ?
       | 
       | Not so sure about swift playground.
       | 
       | One surprise may be mvs ... it is not a Repl. But the idea is
       | that the system cannot be stopped. The sysplex cannot be down
       | because you have a sub-system or just a program error. You have
       | to look at any core dump and fix the system whilst it is running.
       | Obviously not development-Repl. Waterfall and punch card, thank
       | you. But production-Repl.
       | 
       | For production-Repl, basically all current systems needed it.
       | There is no stop of your game world. Or may be yours but not the
       | underlying world. It continues to run even on function upgrade or
       | bugs etc.
       | 
       | The real question is this production-Repl kind (not exactly Repl
       | but the feature of keep the image running, debug or change one
       | part of it and propagate the change without breaking the system)
       | is really hard.
       | 
       | Changing a s/370 control block or jes2 exit lately? Good luck and
       | thanks you for all the fishes, that is why I go away.
        
       | revscat wrote:
       | tl;dr:
       | 
       | LISP and Smalltalk have the only True REPLs because only in those
       | can you rebuild the interpreter and redefine classes without
       | restarting.
        
       | Jtsummers wrote:
       | Part of why this [EDIT: to clarify - the debug/break loop process
       | paired with the REPL] works in Smalltalk and Lisp is their
       | dynamic nature, and also to the fact that they are _systems_ as
       | much as _languages_. In principle, Ruby and Python should be able
       | to have as capable dev environments. With more static languages
       | like C, Java, C#, and others you run into the problem of needing
       | more  "skeleton". You can't write:                 void foo() {
       | bar();       }
       | 
       | in those languages and expect the compiler to be thrilled about
       | it. _But_ you could get closer. Java runs on the JVM, C# on the
       | CLR, those provide _systems_ on which the languages (or programs
       | written in those languages) are executed and the kind of access
       | needed to approach the debugger-driven development approach. I
       | haven 't done this in a long time but with C# you can do:
       | void foo() {         throw new NotImplementedException();       }
       | 
       | Now when your program execution hits `foo` you can catch it in
       | the debugger (versus just crashing or otherwise terminating, or
       | needing to set a breakpoint). With VS (and probably others, I did
       | this with VS) you can change this code and recompile it and
       | resume from that point. Now you decide to make the call to `bar`,
       | oops, that method doesn't exist yet so you _also_ have to create
       | `bar`, and you can stub it out the exact same way. So it 's not
       | as easy and pleasant as in Lisp or Smalltalk where you can forgo
       | the skeletal framework of the program and jump straight into it,
       | building each function, method, class, etc. only as needed (truly
       | JIT development), but you can get _close_. I believe Java has
       | some similar facilities with some dev environments. There is
       | _more_ work, but it 's not totally impossible.
       | 
       | All that said, I really enjoy the way you can do this in Lisp
       | (and Smalltalk). I've been debating re-solving the Synacor
       | Challenge [0] and recording how I did it in Lisp the first time.
       | I used the debugger in precisely this way, writing a basic
       | version which could read in the binary blob and did minimal
       | parsing, but then entered an _ecase_ (case expression that errors
       | if there is no matching case). For every instruction that I hadn
       | 't implemented (none of them at the start) it brought me to the
       | debugger, I modified the program, resumed it and it continued
       | until the next unimplemented instruction. By the time I'd
       | finished, I had the interpreter for the byte code up and running
       | and was immediately getting to work on the rest of the challenge.
       | This also worked as a nice goal-directed approach, implementing
       | the whole interpreter was a "big" (not really) task, how to break
       | it down and which part to do _first_? Well, interpreting the
       | binary blob acted as my (very complex) test case and gave me
       | immediate feedback (I also added some basic debugger capabilities
       | to the interpreter) on whether I had done it correctly. No need
       | to make the whole thing before testing it, I got to incrementally
       | test each small change.
       | 
       | That approach could also be made to work with C# as I described
       | before, write a basic skeleton and parse the instructions but
       | throw a `NotImplementedException` whenever you get to an
       | instruction you haven't, well, implemented yet. Then using VS
       | change the throw to a method call (or do it locally) that
       | implements the handler for that instruction. Repeat until all of
       | them are filled out. It's not as smooth as the Lisp or Smalltalk
       | cases would be, but it's doable.
       | 
       | [0] https://challenge.synacor.com - programming challenge by the
       | same guy that does Advent of Code.
       | 
       | ----------
       | 
       | Also, this has come up on here a few times in the past since it
       | was written (2020). Two past submissions with comments:
       | 
       | https://news.ycombinator.com/item?id=25620256 - Jan 3, 2021 (208
       | comments)
       | 
       | https://news.ycombinator.com/item?id=25618457 - Jan 3, 2021 (5
       | comments, 4 + 1 dead, don't know why it's dead)
        
         | tester756 wrote:
         | I do often use this approach in C#, so I started calling it
         | debugger driven development
         | 
         | Seems like I should try Smalltalk
        
       | cobaltoxide wrote:
       | A peculiar workflow of REPL-driven programming environments is
       | that the running program is eventually "saved" by writing the
       | state of the virtual machine to disk. There may be no source code
       | to rebuild from, if the program was built interactively. It has
       | its appeal, but it's kind of a nightmare from a maintainability
       | standpoint.
        
       | dang wrote:
       | Related:
       | 
       |  _On Repl-Driven Programming_ -
       | https://news.ycombinator.com/item?id=25620256 - Jan 2021 (206
       | comments)
        
       ___________________________________________________________________
       (page generated 2022-05-05 23:00 UTC)