chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Bug with #!optional in Chicken 4.8.0


From: John Croisant
Subject: Re: [Chicken-users] Bug with #!optional in Chicken 4.8.0
Date: Tue, 16 Oct 2012 18:24:14 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:16.0) Gecko/20121010 Thunderbird/16.0.1

On 10/15/12 10:51 AM, Felix wrote:
[...] It can be considered a bug, indeed. The problem is that we have to pass
an additional argument to parameter-functions to mark the situation
when a parameter gets "restored". "parameterize" expands into something
like

   (let ((param1 ...) ...)
     (let ((old-value1 #f) ...)
       (dynamic-wind
         (lambda ()
           <set old-valueN to value of paramN>)
        (lambda ()
          <body>)
        (lambda ()
          <restore value of paramN>))))

The restoration can not simply by "(paramN <oldval>)", since we must
avoid calling the guard procedure (if it exists). Being too lazy / too
afraid to change the implementation of parameter procedures (which is
relatively complicated, including threading issues, as parameters are
thread-local), and because I saw the opportunity to cut a tiny bit of
runtime by simply omitting the check for surplus arguments (as is done
in various old-school Lisp dialects, in C (or undeclared procedures,
or procedures with "..."), in Lua, and in a number of other scripting
languages), I decided to drop the check completely. The parameterize-
issue is now handled by simply passing an extra flag argument that
indicates "restoration". Parameter-like procedures that take a single
optional argument will be handled transparently - they simply ignore
the second flag argument, which is fine, as they don't have a guard
procedure.

I hope this explanation is not too confusing. If it is, I'll try to
give more examples.

Note that R5RS only requires "rest"-arguments, which, by definition,
can be of arbitrary length. Chicken's "#!optional" just builds on top
of R5RS' rest-parameters, BTW.

I had a lot to say about rest args and optional args being two different things from a user's perspective, and each one has different uses and expected behavior. But, I think I have already talked too much about why the old behavior should be restored. So instead, I will just suggest a possible technical solution. :-)

Here is how I understand the situation: in order to avoid unnecessary computation, we want to avoid invoking the guard procedure when the old parameter value is restored at the end of parameterize. So, we need parameter-functions to accept a second arg, which is a flag to tell it to bypass the guard procedure.

So I wonder: is there any problem with simply adding support for a second arg to the parameter-functions, without removing the arg check for all procedures that use #!optional? Even in Chicken 4.7, parameter-functions silently accept extra arguments, so there would be no user-visible change in the way parameter-functions are called.

The only bad effect I could see, would be that Chicken users might think the ability to bypass the guard procedure is a real feature of Chicken, instead of a hack to make parameterize more efficient. But, that problem could be avoided by checking that "bypass guard" argument is a certain unexported symbol (maybe even a gensym) that Chicken users would not (normally) have access to. To put it into pseudocode, a parameter-function might behave something like this:

|  (lambda args
    (case (length args)
      ((0) (get-this-parameter-value))
      ((1) (set-this-parameter-value (guard-procedure (car args))))
      (else (if (eq? ##bypass-parameter-guard## (cadr args))
                (set-this-parameter-value (car args))
(set-this-parameter-value (guard-procedure (car args)))))))||
|
This is still a hack, but at least it is just a small hack which affects only parameterize, and only in the intended way (bypassing the guard procedure when restoring their value). Then, the old behavior of #!optional can be safely restored.

Maybe I have misunderstood something, and this solution would not work for some reason. If so, please help me understand.

- John



reply via email to

[Prev in Thread] Current Thread [Next in Thread]