melisgl / named-readtables

The official repo of named-readtables.
Other
66 stars 15 forks source link

Surprising `(:merge nil)` clause behaviour in `defreadtable` #29

Closed zacque0 closed 1 year ago

zacque0 commented 1 year ago

Hi,

It's not obvious that the (:merge nil) clause in defreadtable is equivalent to (:merge :standard) and (:merge :common-lisp).

[1] As a user, I expect (defreadtable abc (:merge nil)) as merging empty readtable to an initial empty readtable, thus should result in an empty readtable, like the arithmetic 0 + 0 = 0.

[2] Thus, to obtain an empty readtable with defreadtable, I have to either use(:merge) or omit the :merge clause all together.

Is this behaviour going to change (to as described by [1] above), or am I expected to work around this issue (with workarounds as described in [2])?

Thanks!

Version: Git commit d5ff162

Codes to illustrate the issue:

(in-package :named-readtables)

;; Standard readtable?
(defreadtable abc (:merge nil))

(defun read-abc ()
  (let ((*readtable* (find-readtable 'abc)))
    (read)))

#| Sample output:
CL-USER> (read-abc)
(a b c)
(A B C)
|#

;; Standard readtable
(defreadtable abc2 (:merge :standard))

(defun read-abc2 ()
  (let ((*readtable* (find-readtable 'abc2)))
    (read)))

#| Sample output:
CL-USER> (read-abc2)
(a b c)
(A B C)
|#

;; Standard readtable
(defreadtable abc3 (:merge :common-lisp))

(defun read-abc3 ()
  (let ((*readtable* (find-readtable 'abc3)))
    (read)))

#| Sample output:
CL-USER> (read-abc3)
(a b c)
(A B C)
|#

;; Empty readtable
(defreadtable abc4 (:merge))

(defun read-abc4 ()
  (let ((*readtable* (find-readtable 'abc4)))
    (read)))

#| Sample output:
CL-USER> (read-abc4)
(a b c)
|(A|
|#
melisgl commented 1 year ago

The documentation (https://github.com/melisgl/named-readtables#33-preregistered-readtables) says that

- NIL, :STANDARD, and :COMMON-LISP designate the standard readtable.

Apart from brevity, I'm not sure what the reason was for including NIL here. Since it's a documented feature that's been out there for many years, I'd very reluctant to change it. And even if that was changed, (:merge nil) would be an error because :merge is to be followed by a list of readtable designators spliced into the same list as in (:merge . designators), e.g. (:merge :this :and :that).

zacque0 commented 1 year ago

The documentation (https://github.com/melisgl/named-readtables#33-preregistered-readtables) says that

- NIL, :STANDARD, and :COMMON-LISP designate the standard readtable.

My bad, I read too deep from DEFREADTABLE into the MERGE-READTABLES-INTO and MAKE-READTABLE APIs section, and missed the NIL in this sentence.

Apart from brevity, I'm not sure what the reason was for including NIL here. Since it's a documented feature that's been out there for many years, I'd very reluctant to change it. And even if that was changed, (:merge nil) would be an error because :merge is to be followed by a list of readtable designators spliced into the same list as in (:merge . designators), e.g. (:merge :this :and :that).

I see, thanks for your comment!