From: Matthew Economou
Subject: Q: optional arguments default values: evaluated when?
Date: 
Message-ID: <w4od7tly9vn.fsf@nemesis.irtnog.org>
SET-MACRO-CHARACTER has an optional argument READTABLE, which, if left
unspecified, defaults to the current readtable (i.e. the current value
of *READTABLE*).

If I were to define SET-MACRO-CHARACTER in the following way

(DEFUN SET-MACRO-CHARACTER (CHAR NEW-FUNCTION &OPTIONAL (READTABLE *READTABLE*))
  ...)

would READTABLE be bound to the current value of *READTABLE*, that is,
whatever the value of *READTABLE* is at the time SET-MACRO-CHARACTER
is called; or is READTABLE bound to the value of *READTABLE* at the
time of definition?

(If READTABLE above gets bound to the value of *READTABLE* when the
DEFUN is EVAL'ed/LOAD'ed, I would expect to get the correct behavior
with this code, instead of the above:

(DEFUN SET-MACRO-CHARACTER (CHAR NEW-FUNCTION &OPTIONAL READTABLE)
  (LET ((READTABLE (IF (NULL READTABLE)
                       *READTABLE*
                     READTABLE)))
    ...))

But I wonder if the first definition does the equivalent thing.)

-- 
"Well, the last time I was there, I didn't see very much of it, for some
reason.  I later learnt that "Drink Canada Dry" is an advertising slogan, not a
personal challenge." --Oracularity #1014-05

From: Chris Riesbeck
Subject: Re: Q: optional arguments default values: evaluated when?
Date: 
Message-ID: <riesbeck-0811991600120001@riesbeck.ils.nwu.edu>
In article <···············@nemesis.irtnog.org>, Matthew Economou
<········@irtnog.org> wrote:

>If I were to define SET-MACRO-CHARACTER in the following way
>
>(DEFUN SET-MACRO-CHARACTER (CHAR NEW-FUNCTION &OPTIONAL (READTABLE
*READTABLE*))
>  ...)
>
>would READTABLE be bound to the current value of *READTABLE*, that is,
>whatever the value of *READTABLE* is at the time SET-MACRO-CHARACTER
>is called; or is READTABLE bound to the value of *READTABLE* at the
>time of definition?

The easiest way to think about it is that *nothing* gets evaluated
at define-time. It can't be, since the needed values may not exist yet,
e.g.,

  (defun baz (&optional (x (foo))) ...)

should work even if foo isn't defined yet.

Don't let scoping issues confuse you. The reason

  (let ((x 1))

    (defun baz (&optional (y x)) ...)
   )

works is not because x is evaluated at define-time, but because
CL remembers where the x came from and still has a pointer to
the environment where x is defined when baz is called.
From: Erik Naggum
Subject: Re: Q: optional arguments default values: evaluated when?
Date: 
Message-ID: <3151027418201097@naggum.no>
* Matthew Economou <········@irtnog.org>

  your subject question is precise enough for an answer, so the complex and
  possibly confusing example has been elided.  the default value of an
  optional argument is evaluated in the lexical scope of any previously
  specified arguments, and any free variables are referenced as per the
  usual rules:

((lambda (foo &optional (bar foo) (zot bar)) (list foo bar zot)) t)
==> (t t t)

  or, quoting from the standard:

3.4.1.2 Specifiers for optional parameters

If &optional is present, the optional parameter specifiers are those
following &optional up to the next lambda list keyword or the end of the
list.  If optional parameters are specified, then each one is processed as
follows.  If any unprocessed arguments remain, then the parameter variable
var is bound to the next remaining argument, just as for a required
parameter.  If no arguments remain, however, then init-form is evaluated,
and the parameter variable is bound to the resulting value (or to nil if no
init-form appears in the parameter specifier).  If another variable name
supplied-p-parameter appears in the specifier, it is bound to true if an
argument had been available, and to false if no argument remained (and
therefore init-form had to be evaluated).  Supplied-p-parameter is bound
not to an argument but to a value indicating whether or not an argument had
been supplied for the corresponding var.

#:Erik
-- 
  Attention Microsoft Shoppers!  MS Monopoly Money 6.0 are now worthless.