Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My favorite is the way Go does it. There is 1 level. Names have a sane default, are short and descriptive and can be simply overridden in the unusual case of a conflict. Prefixing the (short) name is required which keeps me from having to guess as I'm reading.


How is this different from how emacs does it?


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.


The 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..."


> 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.


The 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?


The 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).


Ok, I think that make sense. Basically, importing it lets you refer to the symbol in an abbreviated way. But it is always that symbol. If there was some odd case where you wanted every ??:FOO to be overridden, it would be tougher. (No, I am not trying to make a case for that scenario. Just making sure I understand.)

And I understand what you are saying about CL being nice. I'm currently going through Land of Lisp and it is interesting to see how many things are covered. Granted, even scheme has this, to an extent. Reading SICP feels like reading a book on what was going to rise and fall in programming in the years to come.

Regardless, Thanks!


Emacs doesn't really have hierarchical packages, and if it did then the full prefix, not the abbreviated prefix, would be required.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: