My understanding is that all of the drawbacks mentioned below are a consequence of Clojure using a single-pass compiler. Feel free to correct my misunderstandings, which no doubt exist.
0. Provisos: I don't want Clojure to include every feature that anyone wants. I don't even want it to include every feature that I want. The feature that I most want is what Clojure provides, which is a small set of elegant, flexible functions that allow one to do a lot with a little bit of code, without the language being cluttered up by a confusing set of non-orthogonal, confusingly named features. I'm immensely grateful to Rich and others who've worked on the design and implementation of Clojure. The follow is not an attack or a criticism, but a statement of reasons for what seems like a small change in a language that I love using. 1. The world contains cyclic dependencies. Not all relationships are hierarchical. 2. Fortunately, Clojure allows cyclic dependencies. They're completely unproblematic in many cases due to dynamic typing. Clojure only forbids cyclic dependencies when the dependency *explicitly* involves something that can be interpreted as a Java class, as defined, for example, by defrecord. This seems like an arbitrary distinction. 3. Allowing cyclic dependencies to work in some cases but not in others is confusing, and can lead to puzzling behavior: - If I add type hints, what was not a forbidden cyclic dependendency can suddenly become one and fail to compile. - If I add forbidden cyclic dependency to one source file, and that source file depends on a file that's already been compiled, the first, newly-modified source file may compile and the program may run without trouble--until I delete the second class file or or try to compile on a different machine on which some of the source files have not been compiled yet. (So I can give my coworker code that worked on my machine but breaks on hers, even though we have the same source code and use the same libraries. I may also have made other code depend on the recently-added functions that embody the cyclic dependency; when I realize what's gone wrong, I'll have to go back and fix all of that code that depends on the offending functions in order to fix the problem.) 4. One shouldn't shouldn't have to organize code into source files so that conceptually very distinct things are required to be in the same file, or at least in the same namespace, in order to avoid forbidden cyclic dependencies. One shouldn't have to create huge source files unnecessarily. And whether code has to be organized like that shouldn't depend on whether type hints are added: One shouldn't have to turn well-organized code into poorly organized code just for the sake of optimization. (That should be the compiler's job.) 5. Some cyclic dependencies won't compile even if all of the code is in one file. If I have functions that refer to each other, I can add a declare statement, but there's no way to do the same thing for types. The following won't compile no matter how I rearrange the definitions: (ns Foo) (defprotocol XP (make-Y [this])) (defprotocol YP (make-X [this])) (defrecord X [x] XP (make-Y [this] (Y. x))) (defrecord Y [y] YP (make-X [this] (X. y))) A related point is that it may be necessary to rearrange code in a file in awkward, unintuitive ways in order to get it to compile. This compounds the problem of putting a lot of code in one file. 6. Changing to two-pass compilation wouldn't add any functions or datatypes to the language, so there's no sense in which it clutters up the language. And it's hard to believe that a two-pass compiler would be very slow compared to the existing compiler, although I don't know much about compilers. From the programmer's point of view, changing to a single-pass compiler is a trivial change, and breaks no code. These points concern ways in which coding in Clojure becomes inconvenient, awkward, or bug-prone. In another language, I might not mind as much. I might just think that programming requires care and skill, and I would take pride in my ability to work around such problems, and in the specialized knowledge I've gained that allows me to do so. With Clojure, I expect more, I guess. Honestly, I don't expect the single-pass compilation to go away, but I don't understand why it persists. The preceding points should be pretty obvious to Rich and other members of the core Clojure team. I know that some of them have been made before, but I haven't seen all of them made. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.