4 ms·
Jupiter works good as long as all your code is in one file. You can't really modify code outside of cells you made. In Common Lisp you can develop a project wi
by killerstorm 2y ago
Jupiter works good as long as all your code is in one file. You can't really modify code outside of cells you made.
In Common Lisp you can develop a project with multiple files interactively, you can even modify library code, maybe even the runtime
- nomilk 2y ago> you can even modify library code, maybe even the runtime this would be difficult (and not recommended) but not strictly impossible in languages other than lisp (e.g. read library files, edit them, re-write them, re-load the library). But to play devil's advocate, isn't the language feature that makes this easy in lisp its homoiconicity, as opposed to its REPL?
- killerstorm 2y agoNo. It is easy because: * The environment for top-level definitions in the file is almost identical to REPL. I.e. there's not much special about a file, thus you don't need a context of a file to submit a new definition. * Symbols provide an indirection mechanism which isn't tied to a specific location. * CLOS actually put a lot of effort into doing something reasonable on redefinition. Python module system is based on dicts. While it would seem like it would be easy to manipulate in runtime, module 's dicts are constructed by module-level import statements, and re-constructing the right state of all modules after an update might be tricky. OTOH if you update symbol's function in CL, every user of that symbol will pick up the new definition. It's also more performant than dicts: caller has a pointer to a symbol and needs to do just one indirection, there's no lookup at runtime.
- skydhash 2y agoNot really. The runtime, plus your code is a virtual machine. It’s similar to docker container in that regard. The REPL is your shell. And you can poke around everything. Another language that has that is Smalltalk/pharo. In comparison, the Python REPL feel like the os part was burned on ROM.
- whartung 2y agoAnother feature of CL, specifically CLOS, is that it actually has a formal protocol for changing classes. A formal protocol you can tap into. While hardly omniscient, I don’t know of another language that does offer this. I don’t even think Smalltalk has this. (Smalltalk has a fundamental primitive related to this called “become:”, which can be used for this purpose, but that’s less formal than what CLOS provides.) What does this mean? It means that you can change the structure of classes, AND their instances, in a live, running system. Not just their structure, but how the system transmutes from the old structure to the new structure. How the conversion is done. What does this have to do with the REPL? It’s part and parcel of the kind of environment and functionality of the system that is exposed by the REPL. The REPL is not just a console that you can type into, and use backspace, and what not. It’s the door to the very rich world underlying the system. And this is the key point. In CL, the REPL is not an afterthought. It’s not an add-on. It’s a core competency. Much of this no doubt came from the Lisp Machine experience, where all you had was a running image that, like a surgeon, you had your arms elbow deep into. A system where you could not trivially just stop and restart for every little change. A system where you had to have the ability to change the tires on a running vehicle. The vast majority of modern REPL environments don’t have that burden, so when things get tough, they can punt. “Eh, just restart and do over.” It’s absolutely fair to consider whether that quality is actually still germane in the modern era. Hard to imagine a scenario where you might do something like a change like this on a running server, especially in our age of “cattle, not pets”. But the legacy is still there from that past time. A time when not only were they pets, they were coddled and spoiled. So the folks back then had to think this stuff through.
- pjmlp 2y agoThat is why I always give Lisp enviroments and Smalltalk as example, when someone comes up with the common excuse that Python cannot have good JITs, as it is too dynamic. Finally it is starting to change.
- pfdietz 2y agoThe REPL is not an add-on in the sense that it comes with the implementation, but it is in the sense that if it were not provided, it could be implemented using only things available standardly in a Common Lisp implementation.
- lispm 2y agoThe language features that make this possible are a) late-binding and b) resident development tools (compiler, debugger, interpreter, inspector, trace, ... are all included in the runtime).
- killerstorm 2y agoNot all kinds of late-binding is good. Python uses dicts which has more runtime overhead than symbols, but make it hard to develop code interactively. Consider foo.py def foo1(x): return x+1 bar.py from foo import foo1 def bar1(x): return foo1(x)\*2 I can modify foo.foo1 in REPL: foo.foo1 = lambda x: x+3 but bar.bar1 will still use the old definition! bar1 lookups foo1 via a dict which is constructed when bar is imported, so it won't be updated unless I reload all files. So dicts are just wrong for this, there are too many of them. Symbols are basically perfect for this as they provide an easily manageable point of indirection and also much more performant.