Open vkz opened 4 years ago
The motivation for starting the back end before the REPL was mainly racket-xp-mode
and also multiple REPLs #338 , and is discussed in this blog post.
There is a racket-stop-back-end
command. Also racket-start-back-end
, which is actually a (re)start (it effectively does a stop if running, then starts). I made those commands "just in case", but didn't document then because I didn't consider them to be thing normal users should actually ever really need. However if you're hacking on Racket Mode's back end, itself, then you might need them.
Does that explain what you're seeing, and what you need?
By the way, each REPL still does the Racket thing with a custodian so that state like ports etc. is still reset when you exit the REPL -- and indeed still reset on every racket run. That hasn't changed!
If there is some state that is not covered by the custodian, then let's try to figure that out and make sure that it is.
One bit of state that isn't (can't?) be managed by a custodian is Racket's module registry. Which sounds like it might match your description?
Anyway if you racket-stop-back-end
it will reset that, too, and automatically exit any/all REPLs.
To follow-up:
I think the TL;DR is: Use racket-stop-back-end
instead of racket-repl-exit
if you want to stop the entire Racket Mode back end and all REPLs. AFAICT that should get the same "clean slate" effect that you want.
Having said that, if you have some specific scenario where you would like not to need to do this -- not even the old way with racket-repl-exit
? Then if you can give me more details (a small example program and steps to follow would be great!) I'd be happy to take a look and try to understand what's going on.
Been muling this over a little. Maybe what I really need isn't necessarily to fix this issue but rather come up with a pleasant enough way to develop "services" and long-running programs in Racket without losing the conveniences REPLs afford and my hair. The issue described above came about because I was watching the filesystem, automatically recompiling any sources that changed and auto-restarting the service. REPL becomes pretty much redundant here but the experience is less than pleasant. I'd like my REPL back please. Starting the system in the REPL is fine and dandy but then everything flies in the face of "we load one module and its namespace - that ought to be good enough for everyone" Racket mantra. I experimented with staring off in REPL and then (enter! mod)
which does the trick but I guess goes against the grain of what both DrRacket and racket-mode are about. It also doesn't address the problem of reloading changed dependencies. We are using (require ...)
everywhere, not dynamic-rerequire
after all.
I wonder if this deserves a separate discussion? How did you do this for Extramaze? Maybe even Racket mailing list but I fear it'll inevitably fall into top-level hopeless
routine and not everyone there cares about Emacs experience.
I'll mull this over, too.
A few quick thoughts, just in the meantime:
Good news: After the recent changes, racket-mode
(editing) and racket-xp-mode
no longer need a REPL, no longer need to "run" your program, in order to do useful things while editing and exploring code. They full-expand the code but don't run it. In that respect things have improved. You no longer need to use the racket-repl-mode
part to do IDE-ish activities.
I think you're already familiar with racket-reloadable
? It makes you identify parts of your program that are supposed to be reloadable. On the one hand this is a nuisance, on the other hand it provides clarity. (A probably poor analogy would be how Haskell makes you split out the functional from side-effecting parts of your program?)
When I've done "system-y" things, I find a lot of the battle is simply avoiding things that initialize themselves at the module level -- e.g. (define the-thread (thread ...))
-- and replacing that explicit start-xxx
functions. For one thing, this helps make initialization order explicit in a main.rkt
that requires multiple such modules -- now it calls the start-xxx
functions explicitly. For another thing, each such module can be evaluated and run in a REPL without the initializations happening, and you can interact with its functions, um, functionally. :) And turn some of those interactions into unit tests.
So again those are just quick thoughts, and possibly Captain Obvious ones, at that. I'd be happy to discuss and consider more.
Hi! I've thought about this more, but I'm not sure how to proceed.
I don't (yet) see a specific bug to fix. Maybe I should relabel this from "bug" to "enhancement".
But then also, I don't (yet) understand a specific feature to implement, with a recipe I could use to say if it's working as-desired.
So I think I'm going to go with the "question" label. (Or I could add a "brainstorming" label, I suppose?)
I hope this doesn't seem defensive. I'm definitely still open to discussing, understanding, and considering other workflows and how Racket Mode might (or might not) be able to support those! I think I'd just like that in its own "bucket", separate from to-do items that are ready to be done.
Appears neither of us have a solid idea how to proceed, so I may even suggest that we close it for now instead of relabeling. It's the kind of thing that may linger for years until someone gets annoyed enough to just close it. I have some ideas that may result in actual code or suggestions we'll be able to discuss. I'm working on several projects in Racket atm and trying to keep tabs on what trips me up and my workflow in general.
Thank you for giving it thought!
Here is an example, but may not be much use. Seems like documentation is the best solution? Starting with something like:
#lang racket/gui
(define frame (new frame% (label "example")))
(send frame show #t)
When you hit F5, you get a new repl with a new frame, shown in X11 (normally). After hacking around a while, I have seen racket-mode in a state where the new frame is not shown in X11. In this state, running the program at the command line does create the frame, and killing the process does allow racket-mode to create a new repl which acts normally.
I don't know how to reproduce this reliably though.
Actually I can reproduce this behavior by hitting ^d to terminate the repl. C-c C-\ seems to do it also. M-x racket-stop-back-end
fixes the issue.
@acarrico Thanks I opened #520 as its own issue because I suspect that can be fixed/closed independently --- at least, you have a specific recipe to test. Having said that, it might turn out to shed light on the original, so no worries, of course it's fine/great you started it off by making a comment here.
Hey Greg. This is a weird one which I'm not entirely sure how to report or reproduce reliably. Perhaps you'll be able to think of where the problem might be simply by knowing how sausage is made.
I had on several occasions the following happen:
This last step led me to check processes and turns out that killing REPL buffer doesn't actually kill the server process. That could be considered a feature and I guess I understand how "restarting" repl is so fast now, cause server keeps running. I would argue though, that this isn't what I expect to happen when I "kill my repl". First, I'd probably wish that was clearly documented and
racket-repl-exit
with universal prefix would make a prominent appearance in docs. Second, and that's a more alarming thing is that looks to me that the background process holds on to some state and that's what's been causing my issue. That's terrifying since I can no longer trust my REPL and defeats the whole "always start fresh" paradigm Racket is so proud of without my gaining any Clojure-like "liveness".Unless you can think of where the problem might be, I would file it under "weirdness" until I can figure a way to reproduce reliably.