Sorry for the length of this post--I feel I have to spell out the details in order to head off irrelevant responses. I'm saving you the trouble of reading a long chain posts just focused on misunderstandings.
For anything below, I'd be happy to find out that I'm wrong, confused, misguided, etc. I've started using MASON, a library for agent-based models (ABMs) written in Java. Using gen-class to follow the MASON model works pretty well, even if the result is somewhat "Java-esque" Clojure. Using MASON in the normal way involves cyclic dependencies. This is no problem if I let Clojure figure out the types at runtime--but I can get a speed improvement of 11 times the original speed if I add type hints, after a bit of code reorganization to avoid almost all of the cyclic type dependencies. And by adding one additional type hint--more on this below--I get a further 6.5X speed improvement, for a total improvement due to type hints of roughly 70X. Note that speed often matters for ABMs that involve stochastic effects; it's typically necessary to run the same simulation many times, and it's useful to be able to do the needed runs in minutes or hours rather than days. However, the last type hint involves a cyclic type dependency. It doesn't generate a cyclic dependency error, but gives class not found errors no matter which of two interdependent classes is compiled first. My solution is to delete the type hint, compile all of the Clojure files, add the type hint back, and recompile that one modified file. That's how I get the full 85X speed improvement. (*That* is an ugly solution.) The cyclic dependencies are due to decisions by MASON's designers that seem entirely reasonable for an agent-based modeling framework--even if I would do things differently--and *have* done things differently (in a narrowly-focused, application-specific ABM framework that's purely functional except for reporting). ****** So: In order to use a well-designed Java library, I have to choose between slow code or awkward workarounds for a cyclic dependency. ****** Let me emphasize that I *do not* think that Clojure should incorporate every feature that someone thinks useful. I certainly don't think that Clojure should provide every feature offered by Java. Ugh. I love Clojure because it doesn't include everything plus the kitchen sink, but instead provides a small set of flexible, simple, well-thought out functions. However, the lack of cyclic dependencies is not the absence of a substantial language feature. It's an arbitrary limitation placed on compile time that's not present at run time. Allowing cyclic dependencies wouldn't make Clojure less simple or elegant, because it wouldn't really add anything to the language. (Yes, if cyclic dependencies are allowed, then people can abuse them. People can also abuse type hints, interwoven side effects and laziness, macros, and non-idiomatic coding styles. The Clojure community teaches routinely teaches novices how to avoid these mistakes.) (If cyclic dependencies are really considered so harmful, one could hide them behind a special compiler option that emits a warning when used.) --------------------------- Optional reading: Why there's a cyclic dependency in MASON simulations. MASON simulations typically consist of (a) One or more "agents", which implement an interface (Steppable) with a single method, step(). (b) An instance of a class that extends SimState, which contains a scheduler that repeatedly calls step() in every agent that's registered with it. The agents have to interact with each other, and the way that they find out about each others' states is typically through the the SimState object that's automatically passed to step(). The point is that the only way for teach Student to know about other instances of Students is by knowing about an object that also has to know about Students. There's the cycle. (An alternative might be to have each Student maintain a collection of all other Students, but that's ugly and unnecessary.) I use gen-class in order to implement Steppable and to extend SimState. The type hint that I delete and restore is for the second argument to the step() function required by Steppable: (defn -step [^students.Student this ^students.StudentsSimState sim-state] -- 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.