[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gall: Bug Report]
Here are some comments on -portions- of the two long messages from Nick Gall.
!section 9.1(6) Nick Gall 85-03-19
!version Digital Press 1984
!topic Pervasiveness of declarations over FLET and LABELS
Example:
(defun the-many-function-names-foo (x)
(declare (inline foo))
(foo x) ; First call of FOO
(flet ((foo (y z) (zap z y)))
(foo x x)) ; Second call of FOO
(foo x)) ; Third call of FOO
....
Declarations concerning function names should be treated as
special variable declarartions are: references are pervasively
affected, but not bindings.
Agreed. There are a number of areas in the language where the
implications of adding FLET and LABELS (thus adding local function
definitions) were not immediately obvious and therefore were not
reflected in other parts of the manual.
!section 9.1(12) Nick Gall 85-03-19
!version Digital Press 1984
!topic Non-Top-Level use of PROCLAIM
Can PROCLAIM be used, other than at top-level? Since DEFVAR,
etc., are proclamations and can be used at other than top-level,
the answer to this question seems to be `yes'.
Agreed.
Is PROCLAIM a `declaration', i.e., must it appear only where a
declaration is allowed? Since it is allowed at top-level (unlike
DECLARE), and it is a function, and since the other proclaiming
forms (e.g. DEFVAR, etc.) could not be considered declarations
(since they perform evaluation and assignment), the answer must
be no.
Agreed.
Then what is the effect of using PROCLAIM (or one one the other
proclaiming forms) in the middle of a function? For example:
(defun foo (a) (zap a) (proclaim '(special a)) (zark a))
Does the first reference to A refer to the local binding? Does
the second reference refer to the global?
PROCLAIM is merely a function, and has effect when it is called, not
when a call to it is compiled. Your example might be rewritten as
(defun foo (a)
(zap a)
(eval-when (compile)
(proclaim '(special a)))
(zark a))
were EVAL-WHEN permitted inside a function body (it is not; see p.66).
Of course you could write a macro that evaluates the PROCLAIM at macro
expansion time. If you did so, you could properly be castigated for
using incomprehensible programming style, and I presume your program
would execute differently in different Common Lisp compilers and
interpreters.
Some mention of the effects of the non-top-level use of PROCLAIM
and the other proclaiming forms should be made.
On p.66 it says that DEFVAR is not allowed elsewhere than top-level.
PROCLAIM is the only function (rather than special form) that makes
declarations, and presumably the declarations it makes when it is
called take effect "immediately", but the exact definition of "immediately"
might be implementation-dependent. For example, it is implementation-
dependent whether PROCLAIM affects interpreted functions that have already
been defined.
-----------------------------------------------------------------
!section 7.5(14) Nick Gall 85-03-19
!version Digital Press 1984
!topic Scope and Extent of local function names
NOTE: See 9.2 (ftype, function, inline).
Example:
(DEFUN CREATE-MAKEP (MAKE)
(FLET ((CAR (SYMBOL) (GET SYMBOL 'AUTOMOBILE)))
#'(LAMBDA (OWNER) (EQ MAKE (CAR OWNER)))))
(SETQ FOO (CREATE-MAKEP 'HONDA))
(FUNCALL FOO 'BILL) => ?????
Question: What does CAR refer to when it is used in the closure
returned by CREATE-MAKEP? I.E., What is the scope and
extent of the binding of a local function name to a
functional object?
Section 7.1(1) states that "There are two spaces of variables in
Common Lisp, in effect: ordinary variables and function names."
And the function name binding control structures appear in the
section entitled "Establishing New Variable Bindings".
Lexical function name bindings and lexical variable name bindings are
treated identically. This should, of course, be discussed in chapter 3.
See above comment about the implications of FLET and LABELS not having
been fully thought out and reflected in the manual.
I suggest that Common Lisp go all the way, and allow a
SPECIAL-FUNCTION-NAME declaration that would be analogous to the
SPECIAL declaration for "ordinary" variables.
Such a concept would make the idea of
ordinary-variable/function-name binding and assignment much more
consistent.
As I recall this was considered and rejected on the basis that it would
be confusing and wouldn't give any real increase in expressive power
(since FUNCALL of a special variable could be used). I agree with that
decision, even though our implementation has always had the feature.
The only place where we use it is in a crock that could just as well be
done some other way.
-----------------------------------------------------------------
!section 10.3(9) Nick Gall 85-03-19
!version Digital Press 1984
!topic Which bindings are copied by COPY-SYMBOL?
"the initial value and function-definition of the new symbol
will be the same as those of SYM..."
Does this mean that the (dynamic) value of the variable
referred to by SYM, at the point where COPY-SYMBOL symbol is
invoked, is copied? Or, does it mean that the `initial', i.e.
global value of the special variable named by SYM is copied?
Although the wording seems to suggest the latter, it should be
made clearer.
The word "initial" was meant to refer to the new symbol, not the old
symbol, I believe. Probably no one realized the English could be
regarded as ambiguous.
The same questions and suggestion applies to the
function-definition copied by COPY-SYMBOL.
-----------------------------------------------------------------
!section 15.5(8) Nick Gall 85-03-19
!version Digital Press 1984
!topic Is (TAILP NIL list) true or false for every list?
False.
By the way, the index entry for TAILP contains a typographical error and
furthermore the function is documented in the wrong section (it's hard
to see a justification for regarding it as an operation on sets).
"...TAILP is true if (NTHCDR n list) is sublist, for some value
of N." According to this definition NIL is a sublist of every
list, since the (NTHCDR (LENGTH list) list) is NIL for every
LIST.
Yes, this side comment in the text would better have been omitted.
-----------------------------------------------------------------
!section 20.1(7) Nick Gall 85-03-19
!version Digital Press 1984
!topic Is *APPLYHOOK* funcalled for special forms?
"The variable *APPLYHOOK* ... is used when a function is about to
be applied to arguments." Does `function' refer to a functional
object which is in fact a function (i.e., its args. are evaled
before it is called), or does it refer to any functional object
(e.g., `special' functional objects)?
Special forms are excluded.
Later in the paragraph, it is stated that,
The apply hook function is used only for application of
ordinary functions within eval. It is not used for
applications via apply, or funcall, for applications by such
functions as map or reduce, or for invocation of
macro-expansion functions...
This paragraph does not really address the "application of
ordinary functions within eval" but rather the "ordinary
application of functions by eval."
I disagree (but this may be an ambiguity of English).
Also it does not clarify the
action taken for special forms.
Indeed, it ought to say something like "linkage from EVAL to special forms."
Part of the problem is that there is no way, in Common Lisp, to describe
the intercommunication between EVAL and special forms, since it is
implementation-dependent and the language provides no way for the user
to add new special forms. This is not a deficiency in the language (in
my opinion), just something that makes it hard to fit special forms into
that paragraph of documentation.
-----------------------------------------------------------------
!section 20.1(last-1) Nick Gall 85-03-19
!version Digital Press 1984
!topic Is nil declared by defconstant?
...all constant symbols declared by DEFCONSTANT, such as NIL,
T, and PI.
If NIL is declared by DEFCONSTANT then it can legally be
redefined according to section 5.1.2(last):
Constant symbols defined by DEFCONSTANT ... may be redefined,
if necessary, by using DEFCONSTANT again[].
Is such an interpretation correct?
I do not believe that system-supplied constants can legally be redefined.
-----------------------------------------------------------------
!section 4.8(1) Nick Gall 85-03-19
!version Digital Press 1984
!topic The meaning of the word `convert'
Does coerce `convert' (i.e., change the type bits) and return the
original object (or the pointer if typed pointers are supported)
when possible (e.g., coercing a string to an array of
(unsigned-byte 8) in some implementations); or does coerce ALWAYS
create and return a new `equivalent' object; or does the Common
Lisp spec. not define this?
Common Lisp does not specify sharing or non-sharing of storage between
the argument and result of COERCE. I don't see how it could, since this
is necessarily very implementation-dependent. But the documentation
could be clearer.
!section 11.7 Nick Gall 85-03-20
!version Digital Press 1984
!topic INTERN's effect on an accessible symbol's owner.
As a verb, to `intern' a symbol in a package means to
cause the symbol to be interned (sic) in the package if
it was not already; this function is performed by the
function INTERN. If the symbol was previously unowned,
then the package it is being interned in becomes its
owner (home package)...
CLRM Section 11.0 (pg. 172)
I interpret this passage in the following way:
;; Current package is USER
* (setf p1 (make-package 'p1 :use '()))
{printed rep. of p1}
* (import 'p1::xyzzy)
T
* (symbol-package 'xyzzy)
{printed rep. of p1}
* (unintern 'xyzzy p1)
T
* (symbol-package 'xyzzy)
NIL
* (intern "XYZZY")
XYZZY
:INTERNAL
* (symbol-package 'xyzzy)
{printed rep. of user}
In other words, INTERN ensures that the symbol that it returns
as its first value has a home package.
Is this interpretation correct?
I think the mention of accessible but unowned symbols on page 172 (in the
discussion of home packages) shoots down your example. The result of the
last call to SYMBOL-PACKAGE is probably undefined.
------------------------------------------------------------
!section 11.7 Nick Gall 85-03-20
!version Digital Press 1984
!topic UNINTERNing a shadowing-symbol
UNINTERN:
When uninterning a shadowing symbol (call it foo), UNINTERN
collects all inherited symbols with the same print-name
as foo, including foo (assuming foo was inherited). If the name
conflict is only between foo and one other symbol, what sense
does it make to signal a name conflict error and give the user a
choice between shadow-importing foo and the other symbol. If the
user chooses foo, it is no different from aborting from the
error.
In the above case, shouldn't UNINTERN just automatically
shadow-import the other symbol?
Surely it is a bad idea to guess the user's intent in this pathological
case, rather than asking. I suppose it would be legal for a debugger
not to offer the redundant option of shadowing-importing foo again,
although that doesn't seem like a feature of great importance.
I hope someone is listening to comments on unclarities in the manual,
such as Gall's, and that someday a revised and improved manual will
be issued. The Common Lisp community is hardly in possession of the
same resources as the Ada community, so I don't think we can realistically
expect as precise a specification as Ada enjoys.