From: ··········@neodesic.com
Subject: special variable question
Date: 
Message-ID: <6u94gl$kkg$1@nnrp1.dejanews.com>
Here's a little output from a dribble file:

? (defvar *test* 'global)
*TEST*
? (defmacro define-test-function (name)
  `(defun ,name () ',*test*))
DEFINE-TEST-FUNCTION
? (define-test-function test1)
TEST1
? (test1)
GLOBAL
? (let ((*test* 'local))
    (define-test-function test2)
    (values))
? (test2)
GLOBAL

Question: Why doesn't (test2) return LOCAL?

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum

From: Steve Gonedes
Subject: Re: special variable question
Date: 
Message-ID: <m2sohjiyej.fsf@KludgeUnix.com>
··········@neodesic.com writes:

< Here's a little output from a dribble file:
< 
< ? (defvar *test* 'global)
< *TEST*
< ? (defmacro define-test-function (name)
<   `(defun ,name () ',*test*))
< DEFINE-TEST-FUNCTION
< ? (define-test-function test1)
< TEST1
< ? (test1)
< GLOBAL
< ? (let ((*test* 'local))
<     (define-test-function test2)
<     (values))
< ? (test2)
< GLOBAL
< 
< Question: Why doesn't (test2) return LOCAL?

You took the value of *test* and not the symbol *test*, which results
in the symbol GLOBAL being quoted. Maybe this will help clear it up.

(defmacro define-test-function (name)
  (list 'defun name () (list 'quote *test*)))

(define-test-function one)
=> ONE

(function-lambda-expression #'one)
=> (LAMBDA NIL (BLOCK ONE 'GLOBAL))


You probably wanted to do something like this:

(defmacro define-test-function (name)
  (list 'defun name () (quote *test*)))

or

(defmacro define-test-function (name)
  (list 'defun name () '*test*)).

(define-test-function one)
=> ONE

(function-lambda-expression #'one)
=> (LAMBDA NIL (BLOCK ONE *TEST*)).

Which is the same as,

(defmacro define-test-function (name)
  `(defun ,name () *test*)).

(define-test-function one)
=> ONE

(let ((*test* "one"))
      (one))
=> "one"

You can pretty-print the expanded forms,

(let ((name 'one))
  (format t "~%;; `(defun ,name () *test*)")
  (pprint (macroexpand-1 `(defun ,name () *test*)))
  (format t "~2%;; `(defun ,name () ',*test*)")
  (pprint (macroexpand-1 `(defun ,name () ',*test*)))),

but this is mey not help too much since defun is probably a macro.
Your implementation should have some way to recursively expand macros
so that you can see what's going.
From: John Wiseman
Subject: Re: special variable question
Date: 
Message-ID: <arxbto7u58j.fsf@gargoyle.cs.uchicago.edu>
··········@neodesic.com writes:

> Here's a little output from a dribble file:
> 
> ? (defvar *test* 'global)
> *TEST*
> ? (defmacro define-test-function (name)
>   `(defun ,name () ',*test*))
> DEFINE-TEST-FUNCTION
> ? (define-test-function test1)
> TEST1
> ? (test1)
> GLOBAL
> ? (let ((*test* 'local))
>     (define-test-function test2)
>     (values))
> ? (test2)
> GLOBAL
> 
> Question: Why doesn't (test2) return LOCAL?

This puzzled me too for a while, but it's actually pretty easy.

Because macroexpansion of (define-test-function test2) is not
occurring inside the body of the let.

Maybe it would help to imagine what code would be produced by
compiling the (let ...):

1: (setq function
	 (compile nil
		  #'(lambda ()
		      (let ((*test* 'local))
			(define-test-function test2)))))

2: (funcall function)

During step 1, the define-test-function is expanded.  The compiled
lambda does not contain code to do the macroexpansion when it is
executed.  The code inside the lambda was not executed during
compilation; in particular, *test* was not bound.

In step 2 the code runs, *test* is bound, etc.


While this describes the behavior you're seeing, I'm sure the standard
allows for implementations that do some kind of tricky deferred
macroexpansion that might cause (test2) to return LOCAL.  According to
CLtL2, "Macros should be written so as to depend as little as possible
on the execution environment to produce a correct expansion."


John