3 ms·
I'm not an expert in Go, Emacs or Lisp in general. I think I should have said Go has 2 levels, local (no prefixes) and imported (always prefixed). While the imp
by jasonkostempski 12y ago
I'm not an expert in Go, Emacs or Lisp in general. I think I should have said Go has 2 levels, local (no prefixes) and imported (always prefixed). While the import lines are super long (usually a URL), the prefixes tend to be incredibly short because, by default, the name is the last segment of the fully qualified name. From what I gathered here, are the Emacs prefixes only a convention and have to worry about conflicting with the rest of the world? I think it's the short names and the required prefix (to avoid function name conflicts) that set the Go way apart. Like I said, I'm no expert, but when I saw how Go did it I thought it was a very good balance between all the tradeoffs that have to be considered for namespaceing.
- taeric 12y agoThe difference is that in elisp there is no importing. Either the files have been loaded or they haven't. The convention is that you prefix functions from your package with a common name. This has a few drawbacks that are obvious. It also has a few benefits that are perhaps not as obvious. To list a few. If I want to override a function that a lot of other folks use, I can just redefine that function. I don't have to find a way to convince a module system that for every importer of "Foo" I want to override "do-baz." I just provide my own definition of "foo-do-baz." Similarly, if I want to find all of the places that this method is used, a very simple textual search works. (This is debated in that thread a little.) Finally, since emacs is ultimately made for direct user experiences, if someone wants to try their hand at creating some things, they don't have to learn about any module system. Simply prefix your functions with a name and you are done. That last really needs underscoring for some of us. You want to try your hand at writing an emacs extension? Simply start defining stuff in the scratch buffer. If you want to make sure it is saved, do so in a file. No need to setup any sort of module system. Now... all of this sounds like I am against a module system. I honestly just don't know enough to care at the moment. I suspect they are oversold. I also suspect they are somewhat useful at times. Don't know which way the needle ultimately falls. Edit: Looks like I removed an opening sentence. Apologies. I meant to lead this off with, "Ah, that makes sense. I think I can see the difference..."
- wtbob 12y ago> If I want to override a function that a lot of other folks use, I can just redefine that function. That's possible and easy using Common Lisp packages. Just use DEFUN with the symbol naming that function, and anyone using that function will now use the new name. > Similarly, if I want to find all of the places that this method is used, a very simple textual search works. That doesn't work, but a symbol-based search will. > That last really needs underscoring for some of us. You want to try your hand at writing an emacs extension? Simply start defining stuff in the scratch buffer. CL is not so great at that, but for other reasons.
- taeric 12y agoThe first case intrigues me. Are you saying that if a package A has a symbol Foo, and another package B has a symbol Foo, how would I override only package B's? Same for the second scenario? Isn't the symbol Foo essentially shadowed, depending on the package?
- wtbob 12y agoThe first case, that of overriding a function in another package, is really easy: CL-USER> (defpackage #:foo (:use #:cl)) #<PACKAGE "FOO"> CL-USER> (in-package #:foo) #<PACKAGE "FOO"> FOO> (defun func () 1) FUNC FOO> (export 'func) T FOO> (defpackage #:bar (:use #:cl #:foo)) #<PACKAGE "BAR"> FOO> (in-package #:bar) #<PACKAGE "BAR"> BAR> (func) 1 BAR> (defpackage #:baz (:use #:cl)) #<PACKAGE "BAZ"> BAR> (foo:func) 1 BAR> (defun foo:func () 2) STYLE-WARNING: redefining FOO:FUNC in DEFUN FUNC BAR> (func) 2 BAR> (in-package #:bar) #<PACKAGE "BAR"> BAR> (func) 2 BAR> (in-package #:foo) #<PACKAGE "FOO"> FOO> (func) 2 Notice how package FOO defined a function FUNC, which package BAR used without the package prefix (because it :USEs FOO), while package BAZ DEFUNed FOO:FUNC, redefining it everywhere. > Are you saying that if a package A has a symbol Foo, and another package B has a symbol Foo, how would I override only package B's? Easily: A:FOO and B:FOO are completely different symbols (unless B imports A or vice-versa). Setting `(symbol-value a:foo)` has no effect at all on `(symbol-value b:foo)`. If package C imports package A, then C:FOO and A:FOO are the same symbol. If C needs to import both A, but wants to use its own FOO, then it can shadow FOO, which means it would import all the exported symbols of A, except for FOO. IF C wanted to import both A and B, then a correctable error would be signaled; in a typical implementation the corrections would include: using A:FOO in preference to B:FOO; using B:FOO in preference to A:FOO; and aborting the attempt. The only thing not portably possible to my knowledge is to rename a symbol in an importing package, e.g. making C:FOO2 be an alias for A:FOO. If one thinks about what a symbol is, that makes sense. What would `(symbol-name c:foo2)` be in that case? All this, BTW, is why I am so keen on Common Lisp as opposed to Scheme: it really is an industrial-strength Lisp. They standardized a lot of stuff twenty years (and three days!) ago, after a lot of thought. Yeah, there's some compatibility cruft, but it's generally not a big deal (and can mostly be hidden, if one wanted to create a MODERN-LISP package).