DEFCLASS slot names and symbol macros
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Confirmed
|
Medium
|
Unassigned |
Bug Description
CLHS says of DEFCLASS slot names: "The slot-name argument is a symbol that is syntactically valid for use as a variable name."
In SBCL:
CL-USER> (define-
FOO
CL-USER> (let ((foo 23)) foo)
23
CL-USER> (defclass test-1 () (foo))
; Evaluation aborted.
CL-USER> (princ (nth-value 1 (ignore-errors (eval '(defclass test-1 () (foo))))))
In DEFCLASS TEST-1, the slot name FOO is a constant.
#<SB-INT:
CL-USER> (symbol-macrolet ((bar 42))
(let ((bar 13))
bar))
13
CL-USER> (princ (nth-value 1 (ignore-errors (eval
In DEFCLASS TEST-1, the slot name BAR is a constant.
#<SB-INT:
In other words: symbol macro names are valid variable names, and should be also valid slot names.
tags: | added: pcl |
Changed in sbcl: | |
assignee: | nobody → Roman Marynchak (roman-marynchak) |
status: | Confirmed → In Progress |
This issue is quite interesting.
The function to look at is CHECK-SLOT- NAME-FOR- DEFCLASS, from src/pcl/ defclass. lisp. With the workaround, it looks like this:
(cond ((not (symbolp name))
(slot- name-illegal "not a symbol"))
((keywordp name)
(slot- name-illegal "a keyword"))
+ ((or (eq name t) (eq name nil))
+ (slot-name-illegal "a constant"))
- ((constantp name env)
- (slot-name-illegal "a constant"))
...
The workaround idea is to check only for T and NIL, and allow other constants to be used as slots names. The disadvantage is that there will be a failure within WITH-SLOTS when trying to bind these slot names (they will conflict with the constants names which are also visible there). However, when one does not use WITH-SLOTS, things work well.
There is the possibility for the better fix, where a symbol is checked to have a constant expansion, but it is not declared with DEFCONSTANT. Also, note that symbols which have the expansion set with define-symbol-macro or symbol-macrolet do not conflict with the same slots names within WITH-SLOTS.
The question now is: should we prefer a failure within DEFCLASS or a failure within WITH-SLOTS, when a slot name is also a constant's name? Note that
(defclass foo () (bar))
(defconstant bar 1)
always works fine (with the workaround and without it), but
(defconstant bar 1)
(defclass foo () (bar))
fails without the above workaround. Both of them eventually fail when trying (with-slots (bar) (make-instance 'foo) bar).
Please share your opinions! For some additional info, please see the talk on #sbcl: http:// ccl.clozure. com/irc- logs/sbcl/ 2010-11/ sbcl-2010. 11.14.txt