a macro

0 views
Skip to first unread message

Sunil S Nandihalli

unread,
Oct 13, 2010, 1:55:04 AM10/13/10
to clo...@googlegroups.com
Hello Everybody,
 I think I was not clear about things in my previous email.. I am reposting simplifying things...

Variables is a macro which works in the following way..

(Variables (+ x (* 2 y)) 

returns
 [x y]

now let us say we have a function

(defn f []
  '(+ x (* 2 y)))

now I would like to do something like

(Variables (f))

which would return 
[x y]

I know if is a function and will not be evaluated before the macro expands.. may be there is a way to wrap it in a macro (since f is already defined which I would like to use) and have the macro Variables apply on the result of evaluation of f

any help is greatly appreciated.
Thanks,
Sunil.

Sunil S Nandihalli

unread,
Oct 13, 2010, 2:06:53 AM10/13/10
to clo...@googlegroups.com
as a follow up with further clarifications, I would like to mention that Variables is already a predefined macro and I don't want have to execute it at run-time since it uses mathematica and we cannot distribute mathematica to the end user.

and also please read my last sentence as 

I know f is a function and will not be evaluated before the macro expands.. may be there is a way to wrap it in a macro (since f is already defined which I would like to use) and have the macro Variables apply on the result of evaluation of f

it was a typo in my earlier email.

Robert McIntyre

unread,
Oct 13, 2010, 2:07:36 AM10/13/10
to clo...@googlegroups.com
I'm still a little confused as to what you're trying to do,
but is this what you're looking for?

(defmacro zzz [form]
(first form))

(defmacro eval-zzz [form]
`(zzz ~(eval form)))

rlm.play-all> (zzz (range 1 2))
#<core$range clojure.core$range@61e066>

rlm.play-all> (macroexpand-1 '(eval-zzz (range 5)))
(rlm.play-all/zzz (0 1 2 3 4))

rlm.play-all> (eval-zzz (range 5))
0

--Robert

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Meikel Brandmeyer

unread,
Oct 13, 2010, 2:09:45 AM10/13/10
to Clojure
Hi,

On 13 Okt., 07:55, Sunil S Nandihalli <sunil.nandiha...@gmail.com>
wrote:

> I know if is a function and will not be evaluated before the macro expands..
> may be there is a way to wrap it in a macro (since f is already defined
> which I would like to use) and have the macro Variables apply on the result
> of evaluation of f

This is not possible. Macros cannot use information which is not
available at compile time. You should investigate whether it is
possible to split the Variables macro in two parts. A function doing
the work and a convenience macro.

(defn Variables*
[form]
...)

(defmacro Variables
[form]
`(Variables* (quote ~form)))

Then you can call (Variables (+ x (* 2 y))) without quoting and
(Variables* (f)) at runtime with your function result.

Sincerely
Meikel

Laurent PETIT

unread,
Oct 13, 2010, 2:56:28 AM10/13/10
to clo...@googlegroups.com
2010/10/13 Sunil S Nandihalli <sunil.na...@gmail.com>

as a follow up with further clarifications, I would like to mention that Variables is already a predefined macro and I don't want have to execute it at run-time since it uses mathematica and we cannot distribute mathematica to the end user.

and also please read my last sentence as 

I know f is a function

Here lies the problem. The f that is passed as an argument to the call to the macro Variable is not a function. It's the plain symbol f , within a plain list . If you want the macro to interpret the symbol f as a function (or rather the datastructure '(f) as a function call, then you'll have to evaluate it from the macro (which is probably possible and justified in you case because you do not want to distribute the mathematica stuff for the runtime, but it will be available when evaluating from inside the macro at compile time => I assume you will AOT compile things, of course).

So in short: calling eval from the macro, on its argument.

HTH,

-- 
Laurent
 
and will not be evaluated before the macro expands.. may be there is a way to wrap it in a macro (since f is already defined which I would like to use) and have the macro Variables apply on the result of evaluation of f


 

it was a typo in my earlier email.

On Wed, Oct 13, 2010 at 11:25 AM, Sunil S Nandihalli <sunil.na...@gmail.com> wrote:
Hello Everybody,
 I think I was not clear about things in my previous email.. I am reposting simplifying things...

Variables is a macro which works in the following way..

(Variables (+ x (* 2 y)) 

returns
 [x y]

now let us say we have a function

(defn f []
  '(+ x (* 2 y)))

now I would like to do something like

(Variables (f))

which would return 
[x y]

I know if is a function and will not be evaluated before the macro expands.. may be there is a way to wrap it in a macro (since f is already defined which I would like to use) and have the macro Variables apply on the result of evaluation of f

any help is greatly appreciated.
Thanks,
Sunil.

Meikel Brandmeyer

unread,
Oct 13, 2010, 4:57:47 AM10/13/10
to Clojure
Hi,

On 13 Okt., 08:56, Laurent PETIT <laurent.pe...@gmail.com> wrote:

> So in short: calling eval from the macro, on its argument.

Beware the leopard!

user=> (defn f
[constant]
`(+ x# (* ~constant y#)))
#'user/f
user=> (defn variables*
[form]
(if (seq? form)
(reduce into [] (map variables* form))
(when (and (symbol? form) (nil? (resolve form)))
[form])))
#'user/variables*
user=> (defmacro variables
[form]
`(variables* (quote ~form)))
#'user/variables
user=> (defmacro dynamic?-variables
[form]
`(variables ~(eval form)))
#user/dynamic?-variables
user=> (dynamic?-variables '(+ x (* 2 y)))
[x y]
user=> (dynamic?-variables (+ x (* 2 y)))
java.lang.Exception: Unable to resolve symbol: x in this context
(NO_SOURCE_FILE:18)
user=> (dynamic?-variables (f 2))
[x__12__auto__ y__13__auto__]
user=> (let [x 2] (dynamic?-variables (f x)))
java.lang.InstantiationException: user$eval48$eval49__50
(NO_SOURCE_FILE:52)

One has to be aware of the limitations of such an approach.

Sincerely
Meikel

Sunil S Nandihalli

unread,
Oct 13, 2010, 5:19:15 AM10/13/10
to clo...@googlegroups.com
basically the following is the macro that creates a function from the expression calculated using mathematica.. it seems to be doing something still not the whole thing.. hopefully some of you may be able to help me.


(defmacro sexp2fn [sexp]
  (let [sym (eval sexp)
        vars (eval (math (Variables sexp)))]
    (println [sym vars])
    `(fn ~vars
        ~sym)))

;; when I macro expand the following 

(sexp2fn (mathematica-eval "D[x*x+x*y,x]"))

;; I get the error whose stack trace is 

Unable to resolve symbol: sexp in this context
  [Thrown class java.lang.Exception]

Restarts:
 0: [QUIT] Quit to the SLIME top level

Backtrace:
  0: clojure.lang.Compiler.resolveIn(Compiler.java:5677)


;; however if I replace the above macro with the following 

(defmacro sexp2fn [sexp]
  (let [sym (eval sexp)
        vars []]           ;(eval (math (Variables sexp)))]
    (println [sym vars])
    `(fn ~vars
        ~sym)))

;and I macro expand the same expression i get
(clojure.core/fn [] (+ (* 2 x) y))

; as you can see the arguments list is empty .. i would have liked to have [x y] over there and (math (Variables (+ (* 2 x) )y) would return [x y] but for some reason sexp is not visible .. can anybody help?

does eval have any lexical scope in which it will run or does it run in the null-lexical scope?
Sunil.

Meikel Brandmeyer

unread,
Oct 13, 2010, 5:37:11 AM10/13/10
to Clojure
Hi,

On 13 Okt., 11:19, Sunil S Nandihalli <sunil.nandiha...@gmail.com>
wrote:

> (defmacro sexp2fn [sexp]
>   (let [sym (eval sexp)
>         vars (eval (math (Variables sexp)))]
>     (println [sym vars])
>     `(fn ~vars
>         ~sym)))

Try the following:

(defn evaled-variables
[form]
(eval `(math (Variables ~form))))

(defmacro sexp2fn
[string]
(let [form (mathematica-eval string)
vars (evaled-variables form)]
`(fn ~vars ~form)))

Using my previous stubs I get:

user=> (macroexpand-1 '(sexp2fn 2))
(clojure.core/fn [x__1__auto__ y__2__auto__] (clojure.core/+
x__1__auto__ (clojure.core/* 2 y__2__auto__)))

You would call it (sexp2fn "D[x*x+x*y,x]").

Hope that helps.

Sincerely
Meikel
Reply all
Reply to author
Forward
0 new messages