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.

Reply via email to