5 ms·
A million lines of Lisp
- brandonkm 18y agoI've been really interested in Lisp lately, for someone that knows next to nothing about this language, this is a pretty interesting read.
- ajross 18y agoThis kind of loses me towards the end. I mean, sure, emacs is a freakishly large lisp program. I get that part. But, what's the point here? The abstractions in emacs (modes and hooks are the ones discussed in the linked post) really aren't that strange, or unique, or even lisp-specific. Nor are they without analogs in other tools written in conventional imperative languages. An emacs written in python, frankly, wouldn't look that different. A mode by any other name would hook as smooth.
- jrockway 18y agoEmacs is mostly impressive because it's a million lines of lisp with no lexical variables or namespaces. Emacs lisp has almost all the flaws that we criticize PHP for, but somehow it is actually useful and maintainable. I think that's interesting. An emacs written in python, frankly, wouldn't look that different. You're right, but I just can't imagine that. When I think of editing text, I think of writing Lisp to do it for me. I just can't comprehend doing it any other way... and my primary language is Perl :)
- JesseAldridge 18y ago"An emacs written in python" Such as http://peppy.flipturn.org/ http://peppy.flipturn.org/
- ken 18y agoYou're right that the features he mentioned seemed to not be terribly unique to Lisp. But note that your claim wasn't really true before Python 2.5 (less than 2 years old). Imagine trying to write one of Emacs Lisp's most common special forms, save-excursion, in Python without context managers. Even (especially!) Python programmers would admit that Python 2.5 is more powerful than Python 2.4. Emacs has a million lines of Lisp written with this feature not easily emulated in Python 2.4. The Lisp in my Emacs here uses save-excursion 9000 times; is there any Python program in the world that uses context managers 9000 times yet? I'm impressed that a 20+-year-old language can hold its own with a 21st-century one under active development by somebody willing to (somewhat) break backwards compatibility. That's not to say that Elisp was this great 20 years ago -- it had, what, one kind of loop? -- but macros let it grow in directions that its users wanted. You can't really add editing-specific features with custom syntax to Python.
- jrockway 18y agosave-excursion could just be a function though. Here's what the implementation would look like. I don't know Python syntax, so I'll use Lisp, but I'll keep Python's featureset in mind. No macros, no lambdas. (defun save-excursion (function) (let ((point (point)) (mark (mark)) ...) (funcall 'function) (set-mark mark) (goto-char point))) Then you would say: (defun do-something nil (...)) (save-excursion 'do-something) Ideal, no. Possible, yes.
- jrockway 18y agoThat should be (funcall function). I shouldn't post code before I have coffee :)
- JesseAldridge 18y agoOk, this is probably me being ignorant, but can't you do stuff like this to get macros in Python: import os, subprocess def macro(string, filename="~/macro.py"): program_name = os.path.expanduser(filename) out = open(program_name, 'w') out.write(string) out.close() command = ["python"] command.append(program_name) subprocess.Popen(command) macro("print 'Hello macro!'") It seems like with a bit of ingenuity you could achieve any level of abstraction using a technique like that.
- logjam 18y agoShow us some new control structures using your, um, scheme.
- JesseAldridge 18y agoI'm not exactly sure what you mean by "control structures", but how about this: def switch(case, actions): macro(actions[case]) switch(2, ["print 'foo'", "print 'bar'", "print 'baz'"])
- silentbicycle 18y agoFor one example, what about if the arguments in the switch list had side effects? >>> def boo(x): ... print "BOO" ... return x + 3 >>> [1, 2, 3, boo(4) + 0, 5][1] will result in BOO 2 . Each element of the list would be evaluated down to a result value, then the appropriate one is chosen. I'm pretty sure you would need to wrap every item in the switch list in a function just to delay the evaluation. This is just as true for if a different Python interpreter were executing generated code. Adding control structures means extending the core language, such as being able to add a new exception-catching construct that could return evaluation to where it was thrown if, after passing through the exception handler, the preceding test no longer holds true. Or a command that backs up the surrounding for loop by one step. For example. What you wrote above would be useful for some things (generating boilerplate code, certainly), but it doesn't alter the underlying language.