#;
isn't a macro, it's what Common lisp would call a readmacro: what it does is defined at read time, not later than that. Read macros which aim to completely suppress input are mildly perilous because there needs to be a way of saying 'read the following thing, but ignore it', and that's only possible if any other readmacros behave well: there's nothing to stop someone defining a readmacro which produces some side-effect even if reading is suppressed.
However, well-behaved readmacros (which includes all of the standard ones and the rest of the standard reader) in CL won't do that: they'll listen to whether reading is being suppressed, and behave accordingly.
CL allows you to do this as standard by using its conditionalisation on features, and in particular #+(or) <expr>
will always skip <expr>
.
But you can define your own: #;
is not predefined so you can define it:
(set-dispatch-macro-character
## #;
(lambda (stream char n)
(declare (ignore char))
(let ((*read-suppress* t))
(dotimes (i (or n 1) (values))
(read stream)))))
After this, or at least with a better tested version of this, then #; <expr>
(or obviously #;<expr>
) will read as whitespace, and #2; ... ...
will skip two following expressions:
> (let ((x #;1 #2; 2 3 4)) x)
4
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…