Re: Using macro to generate part of fn
On 19 Sep 2010, at 07:21, Stuart Campbell wrote: In this method, the first two parameters may be null. So, my fn looks like this: (defn exported-keys ([table] (exported-keys nil table)) ([schema table] (exported-keys nil schema table)) ([catalog schema table] (fetch-metadata-rs .getExportedKeys catalog schema table))) I was trying to automatically generate the final function body since it duplicates the parameter list, and I expect to have a lot of these kinds of methods. Although, it's not too bad as it is (I've already pulled some common bits into fetch-metadata-rs). You could have a macro (defmacro make-wrapper [name method args] ...) and call it (make-wrapper exported-keys getExportedKeys catalog schema table) or something like that. You might have to add some indication about the order in which the arguments become optional if that's not always the same. The essential point is to generate the whole function from one macro, rather than try to generate pieces of the function body by some macro. 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 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
Re: Using macro to generate part of fn
On 18 Sep 2010, at 07:15, Stuart Campbell wrote: In the following contrived example, I get an error when macroexpanding (defn foo ...): (defmacro special-fn-spec [] '([bar baz] (println bar baz))) (defn foo ([bar] (foo bar :default)) (special-fn-spec)) The error is: Parameter declaration special-fn-spec should be a vector [Thrown class java.lang.IllegalArgumentException] I'm a bit confused about the order in which things are happening here. My assumption was that (special-fn-spec) would be evaluated before the fn definition. Is there a way to do something like this? Macroexpansion is part of the expression evaluation mechanism. In your example (defn foo ([bar] (foo bar :default)) (special-fn-spec)) the whole defn-form is macroexpanded first, yielding something like (def foo (fn ([bar] (foo bar :default)) (special-fn-spec)) Then the fn form is evaluated, yielding a compiled function. At that point, the compiler checks its syntax, and finds two bodies, one well- formed (arg list followed by expression) and a second ill-formed one (just an expression). The function bodies are *not* macroexpanded because they are not evaluated either. The only other subform of your example that is ever macroexpanded is (foo bar :default). There are a couple of ways to generate function bodies programmatically, but it is difficult to give useful advice without knowing what you need this for. 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 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
Re: Using macro to generate part of fn
Macroexpansion is part of the expression evaluation mechanism. In your example (defn foo ([bar] (foo bar :default)) (special-fn-spec)) the whole defn-form is macroexpanded first, yielding something like (def foo (fn ([bar] (foo bar :default)) (special-fn-spec)) Then the fn form is evaluated, yielding a compiled function. At that point, the compiler checks its syntax, and finds two bodies, one well-formed (arg list followed by expression) and a second ill-formed one (just an expression). The function bodies are *not* macroexpanded because they are not evaluated either. The only other subform of your example that is ever macroexpanded is (foo bar :default). There are a couple of ways to generate function bodies programmatically, but it is difficult to give useful advice without knowing what you need this for. Konrad. Thanks Konrad, that makes sense. I suppose I was a bit confused about when macroexpansion occurs. My real use-case involves wrapping a Java object, which has a number of methods with varying numbers of optionally nullable parameters. E.g. DatabaseMetaData#getExportedKeys(String, String, String) In this method, the first two parameters may be null. So, my fn looks like this: (defn exported-keys ([table] (exported-keys nil table)) ([schema table] (exported-keys nil schema table)) ([catalog schema table] (fetch-metadata-rs .getExportedKeys catalog schema table))) I was trying to automatically generate the final function body since it duplicates the parameter list, and I expect to have a lot of these kinds of methods. Although, it's not too bad as it is (I've already pulled some common bits into fetch-metadata-rs). Not sure if that makes sense or not... ? Cheers, Stuart -- 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
Using macro to generate part of fn
Hello, In the following contrived example, I get an error when macroexpanding (defn foo ...): (defmacro special-fn-spec [] '([bar baz] (println bar baz))) (defn foo ([bar] (foo bar :default)) (special-fn-spec)) The error is: Parameter declaration special-fn-spec should be a vector [Thrown class java.lang.IllegalArgumentException] I'm a bit confused about the order in which things are happening here. My assumption was that (special-fn-spec) would be evaluated before the fn definition. Is there a way to do something like this? Thanks Stuart -- 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