1. 21
  1.  

    1. 8

      In all seriousness, append-only programming is just a fun challenge, not a legitimate way of writing software.

      Really? “Append-only” is an apt description of what you get stringing together a few actions in a repl. Many times I have made a mistake in trying something out and had to redefine x or f or class A and try again, hitting up a few times to do my steps in the right order. These things rarely get persisted directly back to a file that I reuse but there’s no reason they shouldn’t and there’s probably been times it would’ve been useful if it did.

      Actually in fact this is how an interactive R session works. When you quit the repl it persists your environment—loaded data and function definitions and all—and loads it all again for you when you run R in the same directory. Writing “a program” in the conventional sense isn’t required for you to reuse your code.

      1. 5

        That’s kinda funny to me, because what you describe is exactly what I severely dislike about “REPL” programming in languages other than Common Lisp. Writing CL in Emacs, I might have an actual file, or just a scratch buffer, and rather than type into the REPL, I’d hit a key combo to evaluate whatever top level expression my text cursor was over. And when I redefined something, I didn’t need to go redo everything else in the same order all over, because Common Lisp was designed to work well with runtime redefinition.

        1. 3

          That’s way more ergonomic of course but it’s been my experience that I can’t make everything as ergonomic as I would like in a timely fashion. Like the cycle I describe isn’t particularly good but I would certainly say it’s legitimate, or at least useful. Some useful practices aren’t very good!

      2. 5

        Forth could be considered an append-only language. You can redefine any word in Forth, and from then on, any new code will use the newer version of said word. And with the appropriate tricks, you can probably get the older version of the word to “call forward” to the newer version.

        1. 4

          This seems like a parody of the wretched and chaotic approach to software development I observed at my last programming job. Our product had millions of lines of code, and nobody understood the full code base. Developers just reverse engineered bits of the code base so that they could make the changes they were responsible for, which mostly meant adding new code, as well as modifying existing code to call the new code. There was a ton of dead code that no longer served any purpose (it was no longer being called). At one point I needed to do some refactoring, and as part of that work I ended up refactoring a bunch of code that I suspected was dead code (although I couldn’t prove it, remember no-one understood the code base in its entirety). I talked to management about deleting this dead code, but they didn’t want to authorize that work. We should only be focused on adding new features.

          1. 3

            I would have been tempted to add a log statement in the dead code, and then check in six months if anything called it.

            1. 1

              I definitely lived there for a while. Eight or ten teams all trying to work on a web-app monolith that had undergone ten years of “organic growth”, and which had little in the way of automated testing (there were some efforts, but none of them managed to get ahead of the curve and achieve significant coverage). Which meant that people were, in general, terrified to touch any piece of code that any other team relied on. If a component existed but didn’t do quite what you needed, you just made a copy of it in your own namespace and modified that one. Maybe we should call it “COW software”.

            2. 6

              It’s called “waterfall”

              1. 3

                That’s a strawman of a strawman of a strawman.

              2. 2

                Existing code cannot be edited.

                The main benefit of this rule is that call sites for new code can not be introduced, resulting in programs that remain very stable over time.

                1. 2

                  Reminds me a lot of Elephant 2000 (McCarthy), and Babar (discussion) although doing this in C seems pretty hair-shirt.

                  1. 2

                    I’ve always kinda wanted to write software this way. Instead of writing a frobnicate() function and calling it, you would write a frobnicate_0_0_1() function. The next version would be frobnicate_0_0_2() or frobnicate_1_0_0(), depending on API stability. You could even have a frobnicate() function that calls the latest version or frobnicate_1() which calls the latest patch with a stable API.

                    Don’t some languages support that with exact versions of functions being called, instead of whatever version of the library that was installed last?

                    1. [Comment removed by author]