On Tue, Dec 23, 2008 at 10:15 AM, Adam Harrison (Clojure) <[email protected]> wrote: > > > Hi folks, > > I have been trying to work out how best to validate the structure of > arguments passed into macros. It would appear that there are several > ways of tackling this and I was wondering which is considered best > practice. As an example, lets say I want a macro, 'print-even' which > prints its arguments if they are even in number and throws an exception > otherwise (sorry for the poor example but it's illustrative). I can see > at least three implementations: > > 1) Defer all the work until the expanded macro code is executed: > > (defmacro print-even [& args] > `(if (even? (count '~args)) > (print ~...@args) > (throw (Exception. "Uneven")))) > > 2) Perform the even? check at macro time, but leave throwing the > exception until runtime: > > (defmacro print-even [& args] > (if (even? (count args)) > `(print ~...@args) > `(throw (Exception. "Uneven")))) > > 3) Throw the exception at macro time: > > (defmacro print-even [& args] > (if (even? (count args)) > `(print ~...@args) > (throw (Exception. (format "Uneven (%d arguments)" (count args))))) > > > Intuitively (3) feels like the right choice for two reasons: > > - It does as much of the work as possible up front > - Given that defmacro is effectively extending the syntax of the > language, you could view calling print-even with an odd number of > arguments as a syntax error which seems best raised as early as possible > > This has an obvious flaw though - the caller may expect to be able to > supply an expression which they want evaluated: > > (print-even (range 1 3)) >
It is that expectation which is flawed. You can't substitute: (print-even (range 1 3)) for (print-even 1 2) In a macro or a function. Functions/macros don't auto-apply themselves when taking & args. (defn foo [& args] args) (foo 1 2) -> (1 2) (foo (range 1 3)) -> ((1 2)) Rich --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] 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 -~----------~----~----~----~------~----~------~--~---
