3 ms·
Doesn't the ability to "hot reload" in either CL or Node largely depend on how the application is structured? For example, if you were developing a web server t
by dmux 4y ago
Doesn't the ability to "hot reload" in either CL or Node largely depend on how the application is structured? For example, if you were developing a web server that sat in an infinite loop waiting for requests to come in, how would you go about redefining a function referenced inside that loop? Wouldn't there need to be two threads of execution? One that was the web-server and a second that acted as the REPL? To redefine something in the web-server, the two threads would have to synchronize in order for the new definition to be passed off. Couldn't this same setup be implemented in any language that supports threads and some type of `eval` function?
Edit: The two threads of execution I mentioned above are likely what the combination of SLIME + Swank are doing.
- mtlmtlmtlmtl 4y agoI have done this exact thing in CL before. What you do is have your event loop function just be a loop calling another function, where all the event handling actually happens. When the event handler function is recompiled, the new version will run /the next time the function is called./ If the recompiled function is currently running that stack frame and anything deeper won't be affected for that call. The only thing you can't do is redefine the loop function itself since it never stops running. That's why you factor it so there's no reason to change that function, just the functions it repeatedly calls. Hope that explanation made sense. Edit: And yes, the way this is implemented under the hood is that the repl has its own thread. You could do this even in C. In fact people have done this for the Linux kernel for example(at least for binary patches). The great thing in CL is the language is designed with the functionality in mind, and the dev tools just support it, so you get it for free.
- dasyatidprime 4y agoIncidentally, this is nearly identical on top to the pattern Erlang uses for the same reason, where most processes couple a long-lived “behavior” with a callback module with a particular structure and a pure-data state value threaded through everything. When the module is replaced, the new functions are picked up automatically, and there's also a callback for adjusting the state information on code changes if need be. The underlying “system message requesting your process to ensure it picks up the code reload” part is quite different, though!
- dreamcompiler 4y agoOthers have answered the question but the reason this works in CL is rather simple: Function calls (by default) have a single level of indirection. When CL calls a function it looks up the address of the function in a table (the symbol table), then jumps to the given address. If you redefine the function associated with the symbol, the next call gets the new definition. Yes, you need a separate thread (native or green) for the REPL but it has less to do with the REPL being a separate thread and more to do with the symbol table being a global data structure. This is why there is no "linking" step in Common Lisp compilation: CL keeps the symbol table around at runtime; C just throws it away.
- pfdietz 4y agoNote, however, that a CL compiler is allowed to assume that calls to functions defined in the same file are to that definition (so it can short circuit the function lookup.) This is from the CLHS section 3.2.2.3. http://clhs.lisp.se/Body/03_bbc.htm http://clhs.lisp.se/Body/03_bbc.htm "All conforming programs must obey the following constraints, which are designed to minimize the observable differences between compiled and interpreted programs:" [...] "A call within a file to a named function that is defined in the same file refers to that function, unless that function has been declared notinline. The consequences are unspecified if functions are redefined individually at run time or multiply defined in the same file."
- dreamcompiler 4y agoI suspect this has to do with deferring warnings from forward definitions, but I might be wrong. It's still common behavior for REPL redefinition to have an immediate effect on the next function call unless that function was declared inline. (Regardless of what file the function was defined in.)
- deleted 4y ago[deleted]