Hi,
I think I must not be understanding something basic about macro expansion.
I've reduced a more complex failure with macros that I am having to this simple example:
; Define a function. (define (inc x) (+ 1 x))
;Define a macro using the function. (define-macro (macro-inc x) (inc x))
; This works okay. (define two (inc 1))
; This fails on load with: ; *** ERROR IN #<procedure #2>, "macro-test.scm"@5.30 -- Unbound variable: inc (define macro-two (macro-inc 1))
If I try to load this in to gsc (or if I import in to bsc), then when I try and use (expand) macro-inc (as shown in the last line), I get an error. It's as if I'm not allowed to use functions I have defined in the expansion of a macro?
Thanks, Benjohn
Afficher les réponses par date
You want:
(define-macro (macro-inc x) (list 'inc x))
(list 'inc x) evaluates at macro-expansion-time as (inc x), which at runtime evaluates to what you want.
The code you wrote does work when entered in interactive mode (gsi); I seem to recall there being a thread in the past month or two about why that might be. I think the gist was that when running non-interactively, gsc does separate passes for macro-expansion, then evaluation. In the macro-expansion pass, it doesn't yet know about functions defined in that file, so calling those functions directly like you did results in an error. On the other hand, in interactive mode, each line gets its own macro-expansion and evaluation pass. So by the time we get to your (define two (macro-inc 1)) line, the macro-expansion pass recognizes 'inc', defined (in the evaluation pass) of an earlier line.
I hope I got that right, -- Matt
On Sat, Jun 18, 2011 at 8:11 AM, Benjohn Barnes benjohn@fysh.org wrote:
Hi,
I think I must not be understanding something basic about macro expansion.
I've reduced a more complex failure with macros that I am having to this simple example:
; Define a function. (define (inc x) (+ 1 x))
;Define a macro using the function. (define-macro (macro-inc x) (inc x))
; This works okay. (define two (inc 1))
; This fails on load with: ; *** ERROR IN #<procedure #2>, "macro-test.scm"@5.30 -- Unbound
variable: inc
(define macro-two (macro-inc 1))
If I try to load this in to gsc (or if I import in to bsc), then when I try and use (expand) macro-inc (as shown in the last line), I get an error. It's as if I'm not allowed to use functions I have defined in the expansion of a macro?
Thanks, Benjohn
-- benjohn@fysh.org - Twitter @benjohnbarnes - Skype benjohnbarnes - Mobile +44 (0) 7968 851 636
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
2011/6/18 Matthew Koichi Grimes mkg@cs.nyu.edu
You want:
(define-macro (macro-inc x) (list 'inc x))
or same thing: (define-macro (macro-inc x) `(inc ,x))
(list 'inc x) evaluates at macro-expansion-time as (inc x), which at runtime
evaluates to what you want.
The code you wrote does work when entered in interactive mode (gsi); I seem to recall there being a thread in the past month or two about why that might be. I think the gist was that when running non-interactively, gsc does separate passes for macro-expansion, then evaluation. In the macro-expansion pass, it doesn't yet know about functions defined in that file, so calling those functions directly like you did results in an error. On the other hand, in interactive mode, each line gets its own macro-expansion and evaluation pass. So by the time we get to your (define two (macro-inc 1)) line, the macro-expansion pass recognizes 'inc', defined (in the evaluation pass) of an earlier line.
I hope I got that right, -- Matt
On Sat, Jun 18, 2011 at 8:11 AM, Benjohn Barnes benjohn@fysh.org wrote:
Hi,
I think I must not be understanding something basic about macro expansion.
I've reduced a more complex failure with macros that I am having to this simple example:
; Define a function. (define (inc x) (+ 1 x))
;Define a macro using the function. (define-macro (macro-inc x) (inc x))
; This works okay. (define two (inc 1))
; This fails on load with: ; *** ERROR IN #<procedure #2>, "macro-test.scm"@5.30 -- Unbound
variable: inc
(define macro-two (macro-inc 1))
If I try to load this in to gsc (or if I import in to bsc), then when I try and use (expand) macro-inc (as shown in the last line), I get an error. It's as if I'm not allowed to use functions I have defined in the expansion of a macro?
Thanks, Benjohn
-- benjohn@fysh.org - Twitter @benjohnbarnes - Skype benjohnbarnes - Mobile +44 (0) 7968 851 636
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On 18 Jun 2011, at 17:13, Matthew Koichi Grimes wrote:
You want:
(define-macro (macro-inc x) (list 'inc x))
(list 'inc x) evaluates at macro-expansion-time as (inc x), which at runtime evaluates to what you want.
The code you wrote does work when entered in interactive mode (gsi); I seem to recall there being a thread in the past month or two about why that might be. I think the gist was that when running non-interactively, gsc does separate passes for macro-expansion, then evaluation. In the macro-expansion pass, it doesn't yet know about functions defined in that file, so calling those functions directly like you did results in an error. On the other hand, in interactive mode, each line gets its own macro-expansion and evaluation pass. So by the time we get to your (define two (macro-inc 1)) line, the macro-expansion pass recognizes 'inc', defined (in the evaluation pass) of an earlier line.
This makes sense, thank you. I think that means that I cannot easily do what I want to do.
Background: I have a library that defines several functions on intervals. If you perform these functions elementwise on a vector, then you can create many equivalent functions on n dimensional rectangles, and an n dimensional rectangle can be represented by a vector of intervals, etc.
I have a function that takes a function on scalars and turns it in to an elementwise function on vectors (which is useful for implementing vector addition, subtraction, and lots of other vector functions).
I would like to write a macro that will take the interval functions I have and build rectangle equivalents of them by slightly renaming the functions and binding these names to vectorised (elementwise) equivalents of the interval functions. Here's the macro I've written (that gives an error on usage indicating that string-find-replace isn't defined):
; Macro to define rectangle function from function in intervals by vectorising them. (define-macro (define-rectangle-function-from-interval-function func-name) `(define ,(string->symbol (string-find-replace (symbol->string func-name) "interval" "rectangle")) ,(vector-make-elementwise-function func-name) ) )
The function, string-find-replace is a function I've supplied in an imported file. It is in turn implemented in terms of srfi 13 functions. I'm using black hole.
So – I guess my real question is "how should I have a macro where I use functions I've written in the macro expansion?" :-)
Thanks, Benjohn
On 2011-06-18, at 5:17 PM, Benjohn Barnes wrote:
So – I guess my real question is "how should I have a macro where I use functions I've written in the macro expansion?" :-)
You could try something along these lines:
https://mercure.iro.umontreal.ca/pipermail/gambit-list/2009-August/003781.ht...
Marc
On Saturday, 18 June 2011 at 14:11, Benjohn Barnes wrote:
I think I must not be understanding something basic about macro expansion.
I've reduced a more complex failure with macros that I am having to this simple example:
; Define a function. (define (inc x) (+ 1 x))
;Define a macro using the function. (define-macro (macro-inc x) (inc x))
; This works okay. (define two (inc 1))
; This fails on load with: ; *** ERROR IN #<procedure #2>, "macro-test.scm"@5.30 -- Unbound variable: inc (define macro-two (macro-inc 1))
As others have pointed out, this is works in the REPL, because each expression gets macroexpanded and evaluated before the next expression is macroexpanded. A different way to explain why this happens is to observe the fact that (load) and (include) works as if you'd have written
(begin (define (inc x) (+ 1 x)) (define-macro (macro-inc x) (inc x)) (define two (inc 1)) (define macro-two (macro-inc 1)))
, which gives the "Unbound variable: inc" error even in the REPL, because the entire begin form is macro expanded before any of it is evaluated.
The interaction between run-time and compile time, especially in an environment with a REPL, is quite complicated. The solution Marc linked to is the preferred way to do it in vanilla Gambit.
The way to do this in Black Hole is to separate the code that is needed at compile time into a separate module. Here's a Black Hole version of your example:
t[master]$ cat > inc.scm (define (inc x) (+ 1 x))
t[master]$ cat > example.scm (syntax-begin (import inc)) (import inc) (define-macro (macro-inc x) (inc x)) (define two (inc 1)) (define macro-two (macro-inc 1))
t[master]$ bsc Loaded Black Hole. Gambit v4.6.1
(import example) two
2
macro-two
2
The important part of this is (syntax-begin (import inc)). It imports inc into the macro namespace. Without it, macro-inc wouldn't have worked.
Because inc is also used at runtime, it has to be imported as usual as well.
A caveat: syntax-begin has turned out to be really tricky to implement right, and I might remove it in favor of a more intelligent import form that automatically infers which phases it has to import to. I don't recommend putting anything but import forms in it.
/Per
On 19 Jun 2011, at 23:04, Per Eckerdal wrote:
*snip*
The way to do this in Black Hole is to separate the code that is needed at compile time into a separate module. Here's a Black Hole version of your example:
t[master]$ cat > inc.scm (define (inc x) (+ 1 x))
t[master]$ cat > example.scm (syntax-begin (import inc)) (import inc) (define-macro (macro-inc x) (inc x)) (define two (inc 1)) (define macro-two (macro-inc 1))
t[master]$ bsc Loaded Black Hole. Gambit v4.6.1
(import example) two
2
macro-two
2
*snip*
Thank you Per, that works! Great stuff.
Also, thank you Mark for the solution in vanilla Gambit.