From: Heiko Schaefer
Subject: Macro does not know gobal variable
Date: 
Message-ID: <dq86ro$jhv$1@news.hispeed.ch>
Dear Lispers,

I am not a lisp guru, so I ran into the following problem:

(defparameter *epsilon* 1d-12 
  "Default accuracy used for double comparison and other numerics.")

(defmacro is-null (x  &key (accuracy *epsilon*)) 
  "Check whether the argument (a double) is near enough 0
to be treated as 0. The accuracy can be given as second argument."
  `(<= (abs ,x) ,accuracy))

(defun g (a)
  (and 
   (is-null a)))   ;;; <- error while compiling, *epsilon* not known

If I compile this code, I get the error that *epsilon* is not known and
I think I understand why: during compile time the macro does not have
access to the lexical environment in which *epsilon* is defined, right?

How do I get it to work correctly?

Thanks,
Heiko

From: André Thieme
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <1137157375.983689.311030@g44g2000cwa.googlegroups.com>
Under sbcl 0.9.8 this compiles fine for me. I can enter the three forms
on the repl in the order you posted them and it works. Or I can put
them into a file and do a compile-file on it - this works too.

What Lisp are you using?
Does it help if you use defconstant?


André
--
From: Kenny Tilton
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <8UNxf.1056$SD.857@news-wrt-01.rdc-nyc.rr.com>
Heiko Schaefer wrote:
> Dear Lispers,
> 
> I am not a lisp guru, so I ran into the following problem:
> 
> (defparameter *epsilon* 1d-12 
>   "Default accuracy used for double comparison and other numerics.")
> 
> (defmacro is-null (x  &key (accuracy *epsilon*)) 
>   "Check whether the argument (a double) is near enough 0
> to be treated as 0. The accuracy can be given as second argument."
>   `(<= (abs ,x) ,accuracy))
> 
> (defun g (a)
>   (and 
>    (is-null a)))   ;;; <- error while compiling, *epsilon* not known
> 
> If I compile this code, I get the error that *epsilon* is not known and
> I think I understand why: during compile time the macro does not have
> access to the lexical environment in which *epsilon* is defined, right?

yes and no. time is the problem, not lexical environment.

> 
> How do I get it to work correctly?

I think you want:

(eval-when (:compile-toplevel :load-toplevel :execute)
     (defparameter ....))


kt
From: Heiko Schaefer
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <dq8aja$ku7$1@news.hispeed.ch>
Thanks a lot for you help, I will need to read up on
compile time issues. 

Heiko

On 2006-01-13, Kenny Tilton <·············@nyc.rr.com> wrote:
> Heiko Schaefer wrote:
>> Dear Lispers,
>> 
>> I am not a lisp guru, so I ran into the following problem:
>> 
>> (defparameter *epsilon* 1d-12 
>>   "Default accuracy used for double comparison and other numerics.")
>> 
>> (defmacro is-null (x  &key (accuracy *epsilon*)) 
>>   "Check whether the argument (a double) is near enough 0
>> to be treated as 0. The accuracy can be given as second argument."
>>   `(<= (abs ,x) ,accuracy))
>> 
>> (defun g (a)
>>   (and 
>>    (is-null a)))   ;;; <- error while compiling, *epsilon* not known
>> 
>> If I compile this code, I get the error that *epsilon* is not known and
>> I think I understand why: during compile time the macro does not have
>> access to the lexical environment in which *epsilon* is defined, right?
>
> yes and no. time is the problem, not lexical environment.
>
>> 
>> How do I get it to work correctly?
>
> I think you want:
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
>      (defparameter ....))
>
>
> kt
From: Kenny Tilton
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <v5Qxf.74$yE4.8@news-wrt-01.rdc-nyc.rr.com>
Heiko Schaefer wrote:
> Thanks a lot for you help, I will need to read up on
> compile time issues. 

I should have given you a head start:

There is compiling, and then there is loading as a subsequent step,at 
which time the compiled stuff gets known to the Lisp runtime.

A handy exception is macros, which must be made available to code 
/following/ the macro in the same source file, since that would be a 
typical thing for a programmer to do.

The only thing I am not sure of (not actually being an expert on these 
matters) was whether the mistiming would become evident had you merely 
defined is-null, but not used it in the rest of the source.

You can try again (in a fresh session!) without G and see if you get 
away with it.

kt

> 
> Heiko
> 
> On 2006-01-13, Kenny Tilton <·············@nyc.rr.com> wrote:
> 
>>Heiko Schaefer wrote:
>>
>>>Dear Lispers,
>>>
>>>I am not a lisp guru, so I ran into the following problem:
>>>
>>>(defparameter *epsilon* 1d-12 
>>>  "Default accuracy used for double comparison and other numerics.")
>>>
>>>(defmacro is-null (x  &key (accuracy *epsilon*)) 
>>>  "Check whether the argument (a double) is near enough 0
>>>to be treated as 0. The accuracy can be given as second argument."
>>>  `(<= (abs ,x) ,accuracy))
>>>
>>>(defun g (a)
>>>  (and 
>>>   (is-null a)))   ;;; <- error while compiling, *epsilon* not known
>>>
>>>If I compile this code, I get the error that *epsilon* is not known and
>>>I think I understand why: during compile time the macro does not have
>>>access to the lexical environment in which *epsilon* is defined, right?
>>
>>yes and no. time is the problem, not lexical environment.
>>
>>
>>>How do I get it to work correctly?
>>
>>I think you want:
>>
>>(eval-when (:compile-toplevel :load-toplevel :execute)
>>     (defparameter ....))
>>
>>
>>kt
From: Edi Weitz
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <ur77cmfnx.fsf@agharta.de>
On Fri, 13 Jan 2006 12:36:08 +0000 (UTC), Heiko Schaefer <··············@swissonline.ch> wrote:

> (defmacro is-null (x  &key (accuracy *epsilon*)) 
>   "Check whether the argument (a double) is near enough 0
> to be treated as 0. The accuracy can be given as second argument."
>   `(<= (abs ,x) ,accuracy))

Try this instead:

  (defmacro is-null (x  &key (accuracy '*epsilon*)) 
    `(<= (abs ,x) ,accuracy))

The more interesting question is: Why do you think you need a macro
here?  A function would do the same thing (without you trying to
figure out what's wrong with your macro).

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Espen Vestre
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <m1bqygl12j.fsf@mordac.netfonds.no>
Heiko Schaefer <··············@swissonline.ch> writes:

> Dear Lispers,
> 
> I am not a lisp guru, so I ran into the following problem:
> 
> (defparameter *epsilon* 1d-12 
>   "Default accuracy used for double comparison and other numerics.")
> 
> (defmacro is-null (x  &key (accuracy *epsilon*)) 
>   "Check whether the argument (a double) is near enough 0
> to be treated as 0. The accuracy can be given as second argument."
>   `(<= (abs ,x) ,accuracy))
> 
> (defun g (a)
>   (and 
>    (is-null a)))   ;;; <- error while compiling, *epsilon* not known
> 
> If I compile this code, I get the error that *epsilon* is not known and
> I think I understand why: during compile time the macro does not have
> access to the lexical environment in which *epsilon* is defined, right?

The explanation is rather that defparameter does not evaluate its
initial-value form at compile time, so at the time the macro is
expanded, *epsilon* is not yet known. You can enclose it in a proper
eval-when clause to control its evaluation.
-- 
  (espen)
From: Edi Weitz
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <uirsomdog.fsf@agharta.de>
On 13 Jan 2006 14:17:08 +0100, Espen Vestre <·····@vestre.net> wrote:

> The explanation is rather that defparameter does not evaluate its
> initial-value form at compile time, so at the time the macro is
> expanded, *epsilon* is not yet known. You can enclose it in a proper
> eval-when clause to control its evaluation.

To the OP: Note that Espen's approach and mine (see other message)
result in different semantics.  If you wrap the DEFPARAMETER form with
an EVAL-WHEN the value of *EPSILON* at macro-expansion time will be
hard-coded into the macro.  If you instead quote *EPSILON* in the
macro's parameter list the value of *EPSILON* at run time will be
used.

  CL-USER 1 > (defparameter *foo* 42)
  *FOO*

  CL-USER 2 > (defmacro bar (&optional (baz *foo*)) `(print ,baz))
  BAR

  CL-USER 3 > (macroexpand '(bar))
  (PRINT 42)
  T

  CL-USER 4 > (defmacro bar (&optional (baz '*foo*)) `(print ,baz))
  BAR

  CL-USER 5 > (macroexpand '(bar))
  (PRINT *FOO*)
  T

HTH,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Espen Vestre
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <m13bjskwf4.fsf@mordac.netfonds.no>
Edi Weitz <········@agharta.de> writes:

> To the OP: Note that Espen's approach and mine (see other message)
> result in different semantics.  If you wrap the DEFPARAMETER form with
> an EVAL-WHEN the value of *EPSILON* at macro-expansion time will be
> hard-coded into the macro.  If you instead quote *EPSILON* in the
> macro's parameter list the value of *EPSILON* at run time will be
> used.

Good point, it didn't occur to me that he might have wanted the
semantics given by your approach, but on second reading of the O.P., I
think the best answer to the question actually is in your second
comment: That he really wants a function, not a macro.
-- 
  (espen)
From: Heiko Schaefer
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <dq8hcr$s1t$1@news.hispeed.ch>
Very interesting! I would prefer the hard coding into the macro.
I use a macro because I want to avoid a function call for every
double number comparison, it really is a abbreviation for a
common form. Hard coding epsion is fine here.

Heiko


On 2006-01-13, Espen Vestre <·····@vestre.net> wrote:
> Edi Weitz <········@agharta.de> writes:
>
>> To the OP: Note that Espen's approach and mine (see other message)
>> result in different semantics.  If you wrap the DEFPARAMETER form with
>> an EVAL-WHEN the value of *EPSILON* at macro-expansion time will be
>> hard-coded into the macro.  If you instead quote *EPSILON* in the
>> macro's parameter list the value of *EPSILON* at run time will be
>> used.
>
> Good point, it didn't occur to me that he might have wanted the
> semantics given by your approach, but on second reading of the O.P., I
> think the best answer to the question actually is in your second
> comment: That he really wants a function, not a macro.
From: Edi Weitz
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <uhd88m8tj.fsf@agharta.de>
On Fri, 13 Jan 2006 15:35:55 +0000 (UTC), Heiko Schaefer <··············@swissonline.ch> wrote:

> Very interesting! I would prefer the hard coding into the macro.  I
> use a macro because I want to avoid a function call for every double
> number comparison, it really is a abbreviation for a common
> form. Hard coding epsion is fine here.

Rule #5 (w.r.t. premature optimization): Don't use macros for
optimization purposes.

  (declaim (inline is-null))
  (defun is-null (x &key (accuracy *epsilon*)) 
    (<= (abs x) accuracy))

In fact, with proper settings I would expect most Lisp compilers to
inline this small function even without the declaration above.

In case you're wondering what the first four rules are:

  Rule #1: Don't optimize.

  Rule #2: Don't optimize.

  Rule #3 (for experts only): Don't optimize yet.

  Rule #4: Profile your code before you try to optimize it.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Heiko Schaefer
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <dqbh55$t6m$1@news.hispeed.ch>
Yup, you are right, a Knuth quote I used myself...

On 2006-01-13, Edi Weitz <········@agharta.de> wrote:
> On Fri, 13 Jan 2006 15:35:55 +0000 (UTC), Heiko Schaefer <··············@swissonline.ch> wrote:
>
>> Very interesting! I would prefer the hard coding into the macro.  I
>> use a macro because I want to avoid a function call for every double
>> number comparison, it really is a abbreviation for a common
>> form. Hard coding epsion is fine here.
>
> Rule #5 (w.r.t. premature optimization): Don't use macros for
> optimization purposes.
>
>   (declaim (inline is-null))
>   (defun is-null (x &key (accuracy *epsilon*)) 
>     (<= (abs x) accuracy))
>
> In fact, with proper settings I would expect most Lisp compilers to
> inline this small function even without the declaration above.
>
> In case you're wondering what the first four rules are:
>
>   Rule #1: Don't optimize.
>
>   Rule #2: Don't optimize.
>
>   Rule #3 (for experts only): Don't optimize yet.
>
>   Rule #4: Profile your code before you try to optimize it.
>
> Cheers,
> Edi.
>
From: Espen Vestre
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <m1y81kjfa0.fsf@mordac.netfonds.no>
Heiko Schaefer <··············@swissonline.ch> writes:

> Very interesting! I would prefer the hard coding into the macro.
> I use a macro because I want to avoid a function call for every
> double number comparison, it really is a abbreviation for a
> common form.

For this kind of application, CL has inline declarations.

For instance, you could write:

-----------------
(defparameter *epsilon* 1d-12 
  "Default accuracy used for double comparison and other numerics.")

(declaim (inline is-null))

(defun is-null (x  &key (accuracy *epsilon*))
  "Check whether the argument (a double) is near enough 0
to be treated as 0. The accuracy can be given as second argument."
  (<= (abs x) accuracy))

(defun g (a)
  (and 
   (is-null a)))
-------------------

If your compiler supports inlining, you should see the body of is-null
being inlined if you disassemble g.
-- 
  (espen)
From: Barry Margolin
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <barmar-5B709B.21202213012006@comcast.dca.giganews.com>
In article <············@news.hispeed.ch>,
 Heiko Schaefer <··············@swissonline.ch> wrote:

> Very interesting! I would prefer the hard coding into the macro.
> I use a macro because I want to avoid a function call for every
> double number comparison, it really is a abbreviation for a
> common form. Hard coding epsion is fine here.

Then why did you use DEFPARAMETER rather than DEFCONSTANT?  DEFPARAMETER 
implies that the user might want to change it.  But if the macro grabs 
the value at compile time, changing the parameter won't affect any 
callers unless they're recompiled.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Stefan Nobis
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <87oe2gb6be.fsf@snobis.de>
Heiko Schaefer <··············@swissonline.ch> writes:

> If I compile this code, I get the error that *epsilon* is not known and
> I think I understand why: during compile time the macro does not have
> access to the lexical environment in which *epsilon* is defined, right?

I'm also no export. As far as I understand this, the compiler might
not be evaluation the defparameter form at macro expansion time. So I
would assume eval-when may help:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter ...))

-- 
Stefan.
From: Pascal Bourguignon
Subject: Re: Macro does not know gobal variable
Date: 
Message-ID: <87psmw3ttl.fsf@thalassa.informatimago.com>
Heiko Schaefer <··············@swissonline.ch> writes:
> (defun g (a)
>   (and 
>    (is-null a)))

Apart from the good advices given in the thread (use a function, not a
macro; don't bother optimizing so soon), I think the name IS-NULL is
ill choosen.

The only NULL value in lisp is NIL, so IS-NULL, for 99.9999999% of the
lisp programmers (that is, everybody but perhaps you), will be
understood to be: (defun is-null (x) (null x)).

Next, predicates are usually named with a postfix "P" or "-P", not a
prefix "IS-".

I'd propose:

CLOSE-TO-ZERO-P
ALMOST-ZERO-P
FP-ZEROP      ; Floating Point ZEROP
FP:ZEROP      ; you may have other floating point specific functions...
~ZEROP
≅ZEROP        ; if you have unicode



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Remember, Information is not knowledge; Knowledge is not Wisdom;
Wisdom is not truth; Truth is not beauty; Beauty is not love;
Love is not music; Music is the best." -- Frank Zappa