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)) With definition (3) this throws an 'Uneven' exception because we're counting the length of the unevaluated argument list. I suppose you could 'eval args' at macro time, but that may not always be wise :) Presumably though it would be OK to (count args) at macro time if you didn't intend then to evaluate args in the print branch, which may result in a list of different length. Or is it considered bad form to throw exceptions at macro time, and hence definition (1) should always be used? Best Regards, Adam. --~--~---------~--~----~------------~-------~--~----~ 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 clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---