Re: Using macro to generate part of fn

2010-09-19 Thread Konrad Hinsen

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

2010-09-18 Thread Konrad Hinsen

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

2010-09-18 Thread Stuart Campbell

 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

2010-09-17 Thread Stuart Campbell
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