|I posted earlier (http://arclanguage.org/item?id=3202) about whether Arc needs modules. I learnt 2 things:|
1. Always unit test your comments :)
2. I'm not very good at expressing myself in forums.
So here's another crack at saying what I wanted to say...
In 'Why Arc Isn't Especially Object Oriented' (http://paulgraham.com/noop.html) Paul Graham wrote:
"If a language is itself an object-oriented program, it can be extended by users. Well, maybe. Or maybe you can do even better by offering the sub-concepts of object-oriented programming a la carte. Overloading, for example, is not intrinsically tied to classes. We'll see."
I think a similar thing applies to modules. They solve a variety of different problems (hiding state, integrating code etc.) which might be best solved by individual, powerful abstractions. Of course, you can still combine these all together and call it a module system, but you could also combine them with other things and create something totally different, and that's the power of a la carte abstractions.
For example, as I and a few others pointed out, you can use with to hide local definitions from the users of your 'module'.
But this has a problem: forward reference.
(with (local-def-1 [+ _ 1]
(def public-def (x)
Without forward reference, you can't have mutually recursive private functions. But that can be fixed by creating a macro that allows forward reference:
(with (foo [bar _]
bar [+ 1 _])
=> Error: "reference to undefined identifier: _bar"
But look what just happened... I invented a new abstraction that could have all kinds of uses. As you can see, encapsulation is not intrinsically tied to modules any more than overloading is intrinsically tied to classes.
(forward-with (foo [bar _]
bar [+ 1 _])
By addressing one of the problems that modules are supposed to solve, instead of addressing the problem of creating modules, I've produced something of general use. That's the power of a la carte thinking. If we keep trying this, we may find out that we don't need modules at all. To quote PG again:
"I personally have never needed object-oriented abstractions. Common Lisp has an enormously powerful object system and I've never used it once. I've done a lot of things (e.g. making hash tables full of closures) that would have required object-oriented techniques to do in wimpier languages, but I have never had to use CLOS.
Maybe I'm just stupid, or have worked on some limited subset of applications. There is a danger in designing a language based on one's own experience of programming. But it seems more dangerous to put stuff in that you've never needed because it's thought to be a good idea."
Replace 'object-oriented' with 'modules' and you'll see what I'm getting at.