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: Felix
Subject: Re: [Chicken-users] Bug with #!optional in Chicken 4.8.0
Date: Mon, 15 Oct 2012 16:51:13 +0200 (CEST)

> The new behavior may not break very much currently existing software
> (although it did break some of my unit tests), but future software
> written in Chicken will start to depend on the new behavior, so
> changing the behavior back in the future *would* break existing
> software. So, we should address this soon, while the pain of changing
> back is still minimal.

Quite right, but I currently see no way to address this problem.

> 
> The old behavior was useful and valuable for (at least) two reasons:
> 
> 1. It provided clear and immediate feedback if the procedure was
> called incorrectly, making the mistake much easier/cheaper to
> fix. (Even experienced professional programmers make this kind of
> mistake sometimes.)

Correct.

> 
> 2. It was consistent with the behavior of optional args in many other
> widely-used programming languages.

True, even though this argument is IMHO weaker than the former one.
The question is, whether it is useful, or, whether it represents
a genuine problem. This is something that I can't convincingly claim,
nor can I claim the opposite. It depends.

> 
> The new behavior can be useful in some situations, but it was already
> very easy to implement: just add a rest arg to any procedure that
> should ignore extra args. On the other hand, it takes a significant
> amount of code/effort for developers to (correctly) reimplement
> argument count checking in their own libraries and applications.

Procedures with rest-arguments seriously impact procedure-call and
-entry performance, at least in the way it is currently implemented.
Changing this is quite involved and requires significant work in the
backend and considerable testing time until it can be declared
reliable. So things are a bit more complicated, at least from the
point of view of an implementor.

> 
> So, for all those reasons, I think this should be considered a bug and
> fixed as soon as possible. Perhaps if you describe the parameterize
> problem (or link to discussion about it elsewhere), someone can think
> of an alternative solution that will not require changing the behavior
> of optional args?

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.


cheers,
felix



reply via email to

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