9 ms·
Of course people "realise" this. But those REPLs are not actually REPLs. They are interactive language prompts. They aren't actually REPLs. As the joke goes, Py
by memefrog 3y ago
Of course people "realise" this. But those REPLs are not actually REPLs. They are interactive language prompts. They aren't actually REPLs. As the joke goes, Python doesn't have a REPL: it lacks READ, EVAL, PRINT and LOOP.
Being able to type in code and have it evaluated one line at a time isn't a REPL.
- mathisfun123 3y agoi have no idea what subtle or nuanced distinction you're trying to strike so what exactly do you imagine is the difference between a lisp repl and a python repl? Edit: people that aren't familiar with python (or how interpreters work in general) don't seem to understand that being able to poke and prod the runtime is entirely a function of the runtime, not the language. In cpython you can absolutely do anything you want to the program state, all the way up to, and including, manually push/pop from the interpreter's value stack (to say nothing of moving up and down the frame stack), mutating owned data, redefining functions, classes, modules, etc. You can even, again at runtime, parse, to AST, and compile source to get macro-like functionally. It's not as clean as in lisp but it 100% gets the job done.
- LispSporks22 3y agoIn TFA, go to the “Try this in your favorite repl”, try that in your “repl” and that would be the fine distinction you’re missing.
- mathisfun123 3y ago>The answer to that question is the differentiating point of repl-driven programming. In an old-fashioned Lisp or Smalltalk environment, the break in foo drops you into a breakloop. do you want me to show you how to do this in a python repl? it's literally just breaking on exception...
- deleted 3y ago[deleted]
- deleted 3y ago[deleted]
- eadmund 3y agoNo, it’s not: an exception unwinds the stack all the way up to where the exception is caught. By the time the enclosing Python pseudo-REPL sees the undefined function error, all the intervening stack frames have dissolved. The way it works is that a function tries code, and catches exceptions. In Lisp (and I believe Smalltalk), it doesn’t work that way: there is an indirection. Rather than try/except, a function registers a condition handler; when that particular condition happens, the handler is called without unwinding the stack. That handler can do anything, to include reading and evaluating more code. And re-trying the failed operation. It would be possible to implement this in Python, of course, but it doesn’t offer the affordances (e.g. macros) that Lisp has, and it’s not built into the language like it is in Lisp (e.g., every single unoptimised function call in Lisp offers an implicit ‘retry’).
- patterns 3y agoSince Smalltalk was mentioned, please consider following points: 1. Smalltalk has first class, live activation records (instances of the class Context). Smalltalk offers the special "variable" thisContext to obtain the current stack frame at any point during method execution. If an exception raised, the current execution context is suspended and control is transferred to the nearest exception handler, but the entire stack frame remains intact and execution can be resumed at any point or even altered (continuations and prolog like backtracking facilities have been added to Smalltalk without changing the language or the VM). 2. The exception system is implemented in Smalltalk itself. There are no reserved keywords for handling or raising exceptions. The implementation can be studied in the live system and, with some precautions, changed while the entire system it is running. 3. The Smalltalk debugger is not only a tool for diagnosing and fixing errors, it also designed as tool for writing code (or put differently, revising conversational content without having to restart the entire conversation including its state). Few systems offer that workflow out of the box, which brings me to the last point. 4. I said earlier that Racket is different from Common Lisp. It's not only about language syntax, semantics, its implementation or other technicalities. It is also about the culture of a language, its history, its people, how they use a language and ultimately, how they approach and do computing. Even in the same language family tree you will find that there are vast differences, if you take said factors into account, so it might be worthwhile to study Common Lisp with an open mind and how it actually feels in use.
- FPGAhacker 3y agoCan you connect to a running server or other running application, inspect live in memory data, change live in memory data, redefine functions and classes and have those changes take immediate effect without restarting the server or app? I think that is that is the big difference. It’s a triple edged sword bonded to a double barreled shotgun though, and the very antithesis of the idea of functional programming vs mutable state.
- mathisfun123 3y ago>Can you connect to a running server or other running application, inspect live in memory data, change live in memory data, redefine functions and classes and have those changes take immediate effect without restarting the server or app? The answer to all of these things, at least in python, is emphatically yes. I do this absolutely all the time. You can debug from one process to another if you've loaded the right hooks. You don't need to take my word for it or even try to do it; you just need to reason a fortiori: python can do it because it's an interpreter with a boxed calling convention and managed memory, just like lisp interpreters. It's amazing: people will die on this hill for some reason but lisp isn't some kind of mysterious system that was and continues to be beyond us mere mortal language/runtime designers. the good ideas in lisp were recognized as good ideas and then incorporated and improved upon.
- FPGAhacker 3y agoCan you give me some links? I don’t program clojure much these days but I’ve never found anything comparable in python.
- mathisfun123 3y agohttps://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html https://www.jetbrains.com/help/pycharm/remote-debugging-with... I need to be very clear so that no one misunderstands: this is not proprietary pycharm functionality - this is all due to to sys.settrace and the pydev debug protocol https://www.pydev.org/manual_adv_remote_debugger.html https://www.pydev.org/manual_adv_remote_debugger.html So you can hook this up completely by yourself with some work but lucky for you and me pycharm makes it effortless.
- lispm 3y agoHow does it look like in Python? In Lisp: CL-USER 43 > (+ 1 (foo 20)) Error: Undefined operator FOO in form (FOO 20). 1 (continue) Try invoking FOO again. 2 Return some values from the form (FOO 20). 3 Try invoking something other than FOO with the same arguments. 4 Set the symbol-function of FOO to another function. 5 Set the macro-function of FOO to another function. 6 (abort) Return to top loop level 0. Type :b for backtrace or :c <option number> to proceed. Type :bug-form "<subject>" for a bug report template or :? for other options. CL-USER 44 : 1 > (defun foo (a) (+ a 21)) FOO CL-USER 45 : 1 > :c 1 42 Note that we are not in some debug mode, to get this functionality. It also works for compiled code. Lisp detects that FOO is undefined. We get a clear error message. Lisp then offers me a list of restarts, how to continue. It then displays a REPL one level deep in an error. I then define the missing function. Then I tell Lisp to use the first restart, to try to invoke FOO again. We don't want to start from scratch, we want to continue the computation. Lisp then is able to complete the computation, since FOO is available now.
- mathisfun123 3y ago>Note that we are not in some debug mode, to get this functionality. Jesus Christ I swear it's like you ascribe mysterious powers to the parens. Do you think the parens give you the ability to travel through time or reverse the pc or what? Okay it's not in a debug mode but it's in a "debug mode". Like seriously tell me how you think this works if it's not effectively catching/trapping some sigkill or something that's the equivalent thereof? I have never in my life met this kind of intransigence on just manifestly obvious things.
- _19qg 3y agoCommon Lisp programs run by default in a way that calls to undefined functions are detected. Here the Lisp simply tries to look up the function object from the symbol. There is no function, so it signals a condition (aka exception). The default exception handler gets called (without unwinding the stack). This handler prints the restarts and calls another REPL. I define the function -> the symbol now has a function definition. We then resume and Lisp tries again to get the function definition. The computation continues where we were. That's the DEFAULT behavior you'll find in Common Lisp implementations.
- ghfwlc 3y agoRestarting from the debugger keeps state without third party Python hacks that you mention. In this example Python increments x twice, Lisp just once: >>> x = 0 >>> def f(): ... global x # yuck! ... x += 1 ... >>> def g(y): ... h() ... >>> >>> g(f()) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in g NameError: name 'h' is not defined >>> >>> def h(): pass ... >>> g(f()) >>> >>> x 2 Versus: * (setf x 0) * (defun f() (incf x)) * (defun g(y) (h)) * (g(f)) debugger invoked on a UNDEFINED-FUNCTION in thread #<THREAD "main thread" RUNNING {1001878103}>: The function COMMON-LISP-USER::H is undefined. Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [CONTINUE ] Retry calling H. 1: [USE-VALUE ] Call specified function. 2: [RETURN-VALUE ] Return specified values. 3: [RETURN-NOTHING] Return zero values. 4: [ABORT ] Exit debugger, returning to top level. ("undefined function") 0] (defun h() nil) ; No debug variables for current frame: using EVAL instead of EVAL-IN-FRAME. H 0] 0 NIL * x 1
- actuallyalys 3y agoIMO, the downside with the term REPL is that if you don't understand the specific Lisp definitions of the terms, it sounds like any other interactive execution environment.