Comment by shawn_w

14 hours ago

That sort of hotfix workflow isn't really a thing in Racket or Scheme in general. Changing the definition of a function doesn't update everything else that calls that function like it does in CL.

Maybe emacs lisp works that way?

You know, after some testing with a bunch of different scheme implementations, I take back what I said, at least for working in a REPL.

    (define (displayln msg) (display msg) (newline))
    (define (inner x) (+ x 1))
    (define (outer x) (inner x))
    (displayln (outer 5))
    (define (inner x) (+ x 2))
    (displayln (outer 5))

outputs 6 and 7 in every one I tried, not the 6 and 6 I expected.

  • Perhaps you were thinking of lexical scope vs dynamic scope? Lexical scoping would prevent a local definition of inner from changing the definition used in outer.

      (let ((inner (lambda (x) (+ x 3)))) (outer 5))
      "7"
    

    But updating the definition of inner with set! or define changes the top-level definition.

Clojure allows for that, giving you neat hot reload capabilities when working in Clojurescript. I believe Emacs Lisp works the same way, and allows for fairly fluid debugging sessions.

Universal hot reload is really a messy beast though. For every "yeah we can just reload this without re-init'ing the structure" there's another "actually reloading causes weird state issues and you have to restart everything anyways" thing.

I've found that hot reloading _specific targetting things_ tends to get you closer to where you want. But even then... sometimes using browser dev tools to experiment on the output will get you where you want faster than trying to hot reload clojurescript but having to "reset" state over and over again or otherwise work around weirdness.

I think this flow works well in Emacs though because you're operating on an editor. So you can change things, press buttons, change things, and have a good mental model. Emacs Lisp methods tend to have very little state to them as well (instead the editor is holding a bunch of exposed state).

Meanwhile React (for example) has _loads_ of hard-to-munge state that means that swapping one component for another inline might be totally fine or might just crash things in a weird way or might not have anything happen. Sometimes just a full page refresh will save you thinking about this