A while ago I uploaded an implementation of monads in Clojure to the group's file section. I have now replaced it by a more or less complete rewrite. This rewrite was motivated by one serious problem with the original implementation, plus a number of minor points that I was not happy with. I have also integrated some ideas from Jim's alternative monad implementation. The new implementation has replaced the original one at
http://clojure.googlegroups.com/web/monads.clj In my original implementation, I had used keywords for the monad operations. These keywords were replaced by their definitions inside a given monad using a recursive symbol replacement in the form to be evaluated. This approach has a major problem: it doesn't combine correctly with macros. If a macro expands into a form containing monad operation keywords, they are not replaced at all, because my symbol replacement code sees only the original form. The new implementation uses plain functions for the monad operations. The with-monad form expands into a straightforward let form that binds the operations to their names. Generic monad operations such as lift are implemented as functions that take the four basic monad definitions as additional parameters. These functions are wrapped by macros that add these parameters to the argument list. In the new implementation, all form manipulation is done by macros, and there is much less of it: it no longer has a fundamental role, but just provides nicer syntax. To pursue my original idea of a replacement-based implementation, one would need something like Common Lisp's symbol-macrolet, which is however not trivial to implement. It requires either an integration with the compiler's macro expansion mechanism, or a separate implementation of full macro expansion, including subforms, of an arbitrary form. With the new monad implementation, client modules can: - define new monads (monad and defmonad) - define new generic monad operations (defmonadfn) - execute code using a monad (with-monad) - define functions that internally use a specific monad (define the function inside a with-monad block) - use monad comprehension syntax (domonad) Some minor changes: - All monad operations have names starting with m-. - There is a single m-lift that takes its arity as an argument. - m-plus takes an arbitrary number of arguments and respects lazy evaluation. Konrad. --~--~---------~--~----~------------~-------~--~----~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---