On Thu, Jun 11, 2009 at 3:35 AM, Wrexsoul<d2387...@bsnow.net> wrote: > > On a side note, I've noticed a few issues with clojure > that could use a bit of sprucing up, no disrespect > intended: > > * If REPL code goes into infinite loop, only escape is to > reset the REPL, which loses everything. Perhaps make > ctrl-C interrupt and return to prompt? It could throw > InterruptedException into the running code, or Error, > or something.
See 'clojure.contrib.repl-utils/add-break-thread!' > * No apparent way to change imports on-the-fly in REPL, > have to recompile all dependencies, close REPL, and > reopen REPL. Tedious. I'm not sure what you mean by this. user=> (File. "/tmp") java.lang.IllegalArgumentException: Unable to resolve classname: File (NO_SOURCE_FILE:31) user=> (import 'java.io.File) java.io.File user=> (File. "/tmp") #<File /tmp> > * Compiler diagnostics could use some improvement. Many are cryptic, > not clearly indicating the nature of the original > problem. Line number isn't always given if a REPL > expression triggered the exception, even if the actual > error is in a .clj file. Given many functions and > expressions on some lines, column number would be useful > too. Feel free to suggest specific improvements to specific error messages. It would be most helpful if such reports included an example to generate the message and maybe a suggestion for what the message should be. > * One especially cryptic error: undefined symbol > clojure.core/unquote (or unquote-splicing). This looks > like library misconfiguration but comes from forgetting > the back-tick in some macro somewhere. This is actually pointing you toward a feature! :-) You can define unquote yourself. This can be useful for creating your own DSLs. Here is an example. Not a useful example, mind you, but just a demonstration of how you could bind unquote yourself: (binding [unquote #(* 4 %)] (+ ~1 ~2)) returns: 12 > * Documentation of some useful things is still lacking > there. For example, I discovered .hasRoot via > (macroexpand-1 '(defonce *foo* nil)) after coming up > empty browsing "vars and environment" and inc-searching > the whole api page for "var". Posting the Javadocs for > the classes of core Clojure objects, e.g. IFn, ISeq, > and IPersistentCollection, would probably go a long way > towards alleviating that, as I have no doubt that > .hasRoot and plenty of similar things are in those. :) Be careful using undocumented APIs. They can be useful, but may change and break your code without the same kind of warnings that you would see when documented APIs change in breaking ways. I'm glad you found defonce. Since it *is* a documented API, it may be worth figuring out how to use it instead of .hasRoot(). A couple other comments on your code: > (defmacro thread [& body] > `(Thread. (proxy [Runnable] [] (run [] ~...@body)))) Clojure functions already implement Runnable, so can be written: (defmacro thread [& body] `(Thread. (fn [] ~...@body))) So here's an alternate definition of defdaemon that avoids .hasRoot and doesn't need the thread macro: (defmacro defdaemon [nm & body] `(do (defonce ~nm nil) (when ~nm (.interrupt ~nm)) (def ~nm (doto (Thread. (fn [] ~...@body)) (.setDaemon true) (.start))))) > (defmacro do-asynch-periodically [nm interval & body] > `(defdaemon ~nm > (loop [] > (Thread/sleep (* 1000 ~interval)) > ~...@body > (recur)))) The 'recur' will loop to the enclosing function if no 'loop' is given, so in this case you could leave out the 'loop'. --Chouser --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---