The Dart VM supports stateful hot reload and it's used heavily by Flutter developers. There are some kinds of structural changes that necessitate a full restart that wipes state away, but the VM is suprisingly good at migrating the existing objects in the heap to match any changes to the underlying classes and preserve as much state as possible.
Right so I think this the approach that most UI frameworks tend to adopt, which is to have a central data store that then is persisted between changes to the view code that generates a view from that store (this is effectively how hot reloading works for things like Redux with Webpack or Elm and I think based on those docs, also how Dart does it).
I'm curious though what happens if you have to make changes to that data store in a statically typed language like Dart, e.g. change the type of a field. The docs there only seem to have a few sentences about that (which I think is talking about a related, but slightly different thing, which is that hot reload allows a whole new host of paths to create state which might've been impossible to ever achieve during the normal, non-hot-reloading operation of an app, including violating certain assumed invariants):
> If code changes affect the state of your app (or its dependencies), the data your app has to work with might not be fully consistent with the data it would have if it executed from scratch. The result might be different behavior after hot reload versus a hot restart.
Does the app crash? Or does it automatically restart with a fresh slate (maybe this falls under the "some kinds of structural changes that necessitate a full restart that wipes state away" you mentioned)? Or is the change ignored? Or is there some degraded "delayed type checking" mode that occurs with hot reload that changes a type into a runtime type guard and causes some sort of exception for anything that requires the field to be a certain type?
> which is to have a central data store that then is persisted between changes to the view code that generates a view from that store
You may think of it that way conceptually but the language and VM don't think of it that way. It's all just objects in memory in the heap. Architecturally, there's no real separation between persisted and non-persisted state.
> Does the app crash? Or does it automatically restart with a fresh slate (maybe this falls under the "some kinds of structural changes that necessitate a full restart that wipes state away" you mentioned)? Or is the change ignored?
I'm not an expert on the details, but I think it simply won't do the hot reload if it determines that it can't do so safely. It's up to the user to then choose to do a full restart and wipe the state if they want.
I was going to make a similar comment about reload() in Python. One dev technique out of the many available is to have your code being edited in your editor while in another terminal window, using an ipython repl to drive it. Currently one would need to `from importlib import reload` and of course ipython itself has
*edit to @dwohnitmok as the author of Crafting Interpreters mentioned, it really works pretty well in practice. And for cases where I was changing enough state that it bails out, you can either set a breakpoint in a test or create a little closure to build up the right state and then pass back an fn to step through in ipython.
Infact, this dev style reinforces an immutable nearly functional data centric programming model. With that model, changes to code won't impact the data, so reloads are actually rare. Have shallow reference chains, use value types in simple containers and lots of problems kinda melt away.
It isn't something I explored that deeply. When a reload fails, you know about it and you just reload the program and continue. It could manifest itself in lots of ways, any of which I don't have off the to of my head.
https://docs.flutter.dev/development/tools/hot-reload