[Openmcl-devel] multiple read-time conditionals, puzzlement

Ron Garret ron at flownet.com
Mon Mar 13 09:14:23 PDT 2023


Yep, definitely a bug.  CCL's behavior is inconsistent:

Clozure Common Lisp Version 1.12 (v1.12) DarwinX8664
? (list #+ccl #-ccl #+ccl 1 2 3)
(3)
? (list #-nil #+nil #-nil 1 2 3)
(2 3)

It's a really weird bug too:

? (get-dispatch-macro-character #\# #\+)
#<Compiled-function CCL::READ-CONDITIONAL #x300000562BFF>
? (get-dispatch-macro-character #\# #\-)
#<Compiled-function CCL::READ-CONDITIONAL #x300000562BFF>
? (trace CCL::READ-CONDITIONAL)
NIL
? #+ccl 1
1
? (trace ccl::read-feature)
NIL
? #+ccl 1

0> Calling (CCL::READ-FEATURE #<CCL::RECORDING-CHARACTER-INPUT-STREAM #x3020004F2E6D>) 
<0 CCL::READ-FEATURE returned #\+
1

If you look at the source, the only place READ-FEATURE is called is in READ-CONDITIONAL, and yet the former is running but the latter is not.  We can even double-check to see that this is not a problem with TRACE:

? (in-package :ccl)
#<Package "CCL">
? (defun read-conditional (stream subchar int)
  (print "Entering READ-CONDITIONAL")
  (cond ((eq subchar (read-feature stream))
         (multiple-value-bind (form note) (read-internal stream t nil t)
           (values form (and note (list note)))))
        (t (let* ((*read-suppress* t))
             (read stream t nil t)
             (values)))))
;Compiler warnings :
;   In READ-CONDITIONAL: Unused lexical variable INT
READ-CONDITIONAL
? #+ccl 1

0> Calling (READ-FEATURE #<RECORDING-CHARACTER-INPUT-STREAM #x3020004E03BD>) 
<0 READ-FEATURE returned #\+
1

This is apparently a common bug.  ECL gets it wrong too:

ECL (Embeddable Common-Lisp) 21.2.1 (git:UNKNOWN)
> (list #+ecl #-ecl #+ecl 1 2 3)
(3)
> (list #-nil #+nil #-nil 1 2 3)
(3)


At least ECL is consistent.  SBCL gets it right:

This is SBCL 2.3.2, an implementation of ANSI Common Lisp.
* (list #+sbcl #-sbcl #+sbcl 1 2 3)
(2 3)
* (list #-nil #+nil #-nil 1 2 3)
(2 3)

Allegro warns that its behavior changed between implementations, and that you should double-check to make sure that your code does what you intend.

Personally, I think this situation is a tar pit, and that nested #+ and #- reader macros should just be avoided.

rg

> On Mar 13, 2023, at 5:51 AM, Tim McNerney <mc at media.mit.edu> wrote:
> 
> Nice investigating. If you want my educated opinion, I think you found a misleading example (#+f #+f x y), explored it to a reasonable extent, and discovered a CCL reader bug:  
> 
>     (setf *features* '(:a :b :c)) followed by '(#+a #-b #+c a b c) reading as (C)
> 
> --Tim
> 
>> On Mar 13, 2023, at 06:06, Arthur Cater <arthur.cater at ucd.ie> wrote:
>> 
>> Reading a bit of ccl’s sources I came across something that surprised me, and I thought it was neat. It was of the form
>> 
>>  #+feat #+feat
>> :keyword argument
>> 
>> which I thought nicer than the sort of thing I’d been doing, namely  #+feat :keyword #+feat argument
>> 
>> 
>> But it set me thinking, and experimenting, and now I’m puzzled, and I wonder if anyone can explain this to me.
>> 
>> 
>> 
>> ? 
>> NIL
>> ? (setf *features* '(:a :b :c))
>> (:A :B :C)
>> 
>> ? '(#+a #+a a b c)
>> (A B C)
>> 
>> ? '(#+a #-b a b c)
>> (B C)
>> 
>> ? '(#+a #+b #-c a b c)
>> (B C)
>> 
>> ? '(#+a #-b #+c a b c)
>> (C)
>> ? 
>> 
>> 
>> I thought I understood what was going on until this last one. Why does #-b cause both A and B to be skipped?
>> 
>> Arthur
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20230313/d0f2c46d/attachment-0001.htm>


More information about the Openmcl-devel mailing list