alexandria issueshttps://gitlab.common-lisp.net/alexandria/alexandria/-/issues2024-01-31T09:22:22Zhttps://gitlab.common-lisp.net/alexandria/alexandria/-/issues/44Broken test for IOTA2024-01-31T09:22:22ZAlexander FedorovBroken test for IOTASee this commit: https://gitlab.common-lisp.net/alexandria/alexandria/-/commit/1e5b8e8f5392fcb025747b7ae54045517f23e074
Test `iota.fp-start-and-complex-integer-step` was designed to test that calling `iota` with the (real) float start a...See this commit: https://gitlab.common-lisp.net/alexandria/alexandria/-/commit/1e5b8e8f5392fcb025747b7ae54045517f23e074
Test `iota.fp-start-and-complex-integer-step` was designed to test that calling `iota` with the (real) float start and complex (integer) step resulted a sequence of complex numbers. It was then incorrectly fixed because it was failing on CLISP.
I believe that test was failing because of CLISP bug, not because it was broken.
`iota` uses a somewhat kludgy hack for returning a correct type as its first element: `(+ (- (+ start step) step)` as the first element in sequence.
This doesn't work on CLISP because of the following behavior:
```lisp
(+ 0.0 #C(0 2)) ; => #C(0.0 2)
```
Note the imagpart being `2` and not `2.0`.
Per https://www.lispworks.com/documentation/HyperSpec/Body/t_comple.htm
> The real part and imaginary part are either both rational or both of the same float type.
But on CLISP (including when running with `-ansi` flag):
```lisp
(complexp (complex 2.0 2)) ; => T
(type-of (realpart (complex 2.0 2))) ; => SINGLE-FLOAT
(type-of (imagpart (complex 2.0 2))) ; => (INTEGER 0 281474976710655)
```https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/43Faster WHICHEVER2024-01-30T07:53:30ZAlexander FedorovFaster WHICHEVERCurrently `whichever` builds an inline binary search tree with O(log n) complexity. Some implementations (for example sbcl) can optimize `case` with clauses being consecutive integers, which would allow for O(1) complexity.
While alexan...Currently `whichever` builds an inline binary search tree with O(log n) complexity. Some implementations (for example sbcl) can optimize `case` with clauses being consecutive integers, which would allow for O(1) complexity.
While alexandria's goal is to be portable, that doesn't mean that it should ignore possible implementation-specific optimizations. There already exists implementation-specific code: see `alexandria:emptyp`, `alexandria:simple-reader-error` or `alexandria::default-element-type` in `io.lisp`.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/42COMPOSE and its variants are probably unsafe2024-01-28T10:49:46ZTim BradshawCOMPOSE and its variants are probably unsafe[`COMPOSE`](https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/009b7e532071d9777bdbd63b82d776555da95916/alexandria-1/functions.lisp#L58) includes this expression:
```
(lambda (&rest arguments)
(declare (dynamic-extent argumen...[`COMPOSE`](https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/009b7e532071d9777bdbd63b82d776555da95916/alexandria-1/functions.lisp#L58) includes this expression:
```
(lambda (&rest arguments)
(declare (dynamic-extent arguments))
(funcall f (apply g arguments)))))
```
where `f` and `g` are unknown functions.
I think this is not safe, because
> When the function receives its arguments via &rest, it is permissible (but not required) for the implementation to bind the rest parameter to an object that shares structure with the last argument to apply.
>
> [CLHS](https://www.lispworks.com/documentation/HyperSpec/Body/f_apply.htm)
So if `g` takes an `&rest` list this may share structure with `arguments`. But a perfectly legitimate definition of `g` would be
```
(lambda (&rest args) args)
```
which could then return the list of arguments outside its dynamic extent.
I am not aware of implementations which have this behaviour for `apply`, however.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/41hash-tables keys and values should be in order, like maphash2023-12-03T10:51:12Zxi zanghash-tables keys and values should be in order, like maphash```lisp
(defun hash-table-keys (table)
"Returns a list containing the keys of hash table TABLE."
(let ((keys nil))
(maphash-keys (lambda (k)
(push k keys))
table)
(nreverse keys)))
(defu...```lisp
(defun hash-table-keys (table)
"Returns a list containing the keys of hash table TABLE."
(let ((keys nil))
(maphash-keys (lambda (k)
(push k keys))
table)
(nreverse keys)))
(defun hash-table-values (table)
"Returns a list containing the values of hash table TABLE."
(let ((values nil))
(maphash-values (lambda (v)
(push v values))
table)
(nreverse values)))
(defun hash-table-alist (table)
"Returns an association list containing the keys and values of hash table
TABLE."
(let ((alist nil))
(maphash (lambda (k v)
(push (cons k v) alist))
table)
(nreverse alist)))
(defun hash-table-plist (table)
"Returns a property list containing the keys and values of hash table
TABLE."
(let ((plist nil))
(maphash (lambda (k v)
(push k plist)
(push v plist))
table)
(nreverse plist)))
```https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/40Feature request: PARSE-BODY configurable behaviour when duplicate doc strings...2023-10-17T12:14:53ZAlexander FedorovFeature request: PARSE-BODY configurable behaviour when duplicate doc strings occurIt would be nice if it was possible to parse bodies with duplicate doc-strings.
It could be provided as an additional keyword argument that would take options like `:error` [default one as it is current behaviour], `:warn`, `:ignore`, `...It would be nice if it was possible to parse bodies with duplicate doc-strings.
It could be provided as an additional keyword argument that would take options like `:error` [default one as it is current behaviour], `:warn`, `:ignore`, `:override` [this one to take the latest doc-string instead of the first one]
Another option would be to signal a continuable error instead of just error with restarts like `ignore` and `override`.
[ I am pretty sure that "override" is not the right name here, but I don't know how to name that instead ]
To add a bit of context:
CLHS 3.4.11 says "The consequences are unspecified if more than one such documentation string is present."
To understand possible behavior I tried the following code on multiple implementations:
```lisp
(defun abcd () "a" "b" "c" "d")
(documentation 'abcd 'function)
```
Here are the results:
Implementations can
* Silently use the first string (`"a"`) as the documentation string.
CMUCL [21e], Allegro CL [FEE 10.1], ECL [21.2.1], ABCL [1.9.1], LispWorks [PE 8.0.1]
* Warn about the the first duplicate doc string (`"b"`) and uses the first one (`"a"`) as the documentation string.
SBCL [2.3.9]
* Silently use the last string (`"c"`) as the documentation string.
CCL [1.12], CLASP [2.2.0]
* Signal an uncontinuable error.
CLISP [2.49.93]https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/39SWITCH with default-only clause emits a warning2023-10-17T14:25:23ZAlexander FedorovSWITCH with default-only clause emits a warningEmits a warning that can't be avoided.
```lisp
* (alexandria:switch (t)
(t))
; in: A:SWITCH (T)
; (#:VALUE200 (IDENTITY T))
;
; caught STYLE-WARNING:
; The variable #:VALUE200 is defined but never used.
;
; compilation unit f...Emits a warning that can't be avoided.
```lisp
* (alexandria:switch (t)
(t))
; in: A:SWITCH (T)
; (#:VALUE200 (IDENTITY T))
;
; caught STYLE-WARNING:
; The variable #:VALUE200 is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
NIL
```
The internal variable should probably be declared `ignorable`.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/38tests broken on SBCL2023-10-16T01:32:21ZHraban Luyattests broken on SBCLTests are broken on SBCL since !30 because of hard-coded test package name (rt vs sb-rt).Tests are broken on SBCL since !30 because of hard-coded test package name (rt vs sb-rt).https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/37Test CURRY.3 broken on CMUCL2023-10-17T13:48:26ZRobert GoldmanTest CURRY.3 broken on CMUCLThis one I'm afraid I cannot debug or fix: I have an M1 Mac and cannot run CMUCL (which is 32-bit only). Someone should fix this or disable the tests on CMUCL.This one I'm afraid I cannot debug or fix: I have an M1 Mac and cannot run CMUCL (which is 32-bit only). Someone should fix this or disable the tests on CMUCL.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/36clasp tests don't run2023-05-02T19:21:27ZRobert Goldmanclasp tests don't runThere's something wrong with the docker image. Until that is fixed, this test should be disabled.There's something wrong with the docker image. Until that is fixed, this test should be disabled.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/35Bug in `type=`: second value computed incorrectly2023-10-18T11:36:01ZRobert GoldmanBug in `type=`: second value computed incorrectlySee [definition of type=](https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/master/alexandria-1/types.lisp#L121):
``` lisp
(defun type= (type1 type2)
"Returns a primary value of T is TYPE1 and TYPE2 are the same type,
and a ...See [definition of type=](https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/master/alexandria-1/types.lisp#L121):
``` lisp
(defun type= (type1 type2)
"Returns a primary value of T is TYPE1 and TYPE2 are the same type,
and a secondary value that is true is the type equality could be reliably
determined: primary value of NIL and secondary value of T indicates that the
types are not equivalent."
(multiple-value-bind (sub ok) (subtypep type1 type2)
(cond ((and ok sub)
(subtypep type2 type1))
(ok
(values nil ok))
(t
(multiple-value-bind (sub ok) (subtypep type2 type1)
(declare (ignore sub))
(values nil ok))))))
```
In the case where the first return is `(NIL NIL)` and the second is `(T T)`, this will return `(NIL T)`, which is incorrect -- we are not certain that the two types are unequal.
If the second value is `(NIL T)` then we should return `(NIL T)`, otherwise we should return `(NIL NIL)` since both results are uncertain.
See #34 for an example.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/34Tests TYPE=.2 and ALEXANDRIA/TESTS::TYPE=.3 fail on ABCL2024-01-25T17:40:40ZRobert GoldmanTests TYPE=.2 and ALEXANDRIA/TESTS::TYPE=.3 fail on ABCLAlexandria expects more certainty from ABCL's `subtypep` than it provides:
```
CL-USER(13): (subtypep 'list '(or null cons))
NIL
NIL
```
This one
```
CL-USER(15): (subtypep '(and symbol list) 'null)
NIL
NIL
```
If these are bugs, th...Alexandria expects more certainty from ABCL's `subtypep` than it provides:
```
CL-USER(13): (subtypep 'list '(or null cons))
NIL
NIL
```
This one
```
CL-USER(15): (subtypep '(and symbol list) 'null)
NIL
NIL
```
If these are bugs, they are probably forgivable: ABCL admits it doesn't know if its answer is correct, which I believe to be correct behavior according to the spec.
There seems to be a bug in the way Alexandria combines two `subtypep` checks into a `test=` check, because we see this:
```
CL-USER(13): (subtypep 'list '(or null cons))
NIL
NIL
CL-USER(17): (alexandria:type= 'list '(or null cons))
NIL
T
CL-USER(18): (subtypep '(or null cons) 'list)
T
T
```
Alexandria has made certainty out of uncertainty. See #35https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/33TYPE=.3 fails on Allegro2023-04-30T22:27:07ZRobert GoldmanTYPE=.3 fails on AllegroThis failure is expected -- there's a bug in Allegro's `subtypep` here, AFAICT, which I have reported to Franz.
I don't know if it's possible to mark this as a test that's expected to fail, or if we should simply add a `#-allegro` for t...This failure is expected -- there's a bug in Allegro's `subtypep` here, AFAICT, which I have reported to Franz.
I don't know if it's possible to mark this as a test that's expected to fail, or if we should simply add a `#-allegro` for this test until Franz issues a fix.
I can do a MR if someone can tell me what's is the Right Thing.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/32TYPE=.4 test fails on Allegro Beta 11: Allegro result seems consistent with spec2023-05-03T14:31:05ZRobert GoldmanTYPE=.4 test fails on Allegro Beta 11: Allegro result seems consistent with specThis test expects a return of `(nil nil)`, but on Allegro returns `(nil t)`. This is because on Allegro:
```
(subtypep 'string '(satisfies emptyp))
NIL
T
```
I don't think that it's wrong to return `(nil t)` from this `type=`, is it?...This test expects a return of `(nil nil)`, but on Allegro returns `(nil t)`. This is because on Allegro:
```
(subtypep 'string '(satisfies emptyp))
NIL
T
```
I don't think that it's wrong to return `(nil t)` from this `type=`, is it? I propose to modify the test to ignore the second value if you agree. This is in my fix MR !27
By the way, `type=.3` *also* fails on Allegro, but this one is a bug in Allegro, which I have reported to Franz.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/31read-stream-content-into-byte-vector.2 fails on Allegro Beta 11: Unsure if Al...2023-05-03T14:33:30ZRobert Goldmanread-stream-content-into-byte-vector.2 fails on Allegro Beta 11: Unsure if Allegro result is acceptableThis test fails because the test expects a `type-error`, but Allegro raises a `:program-error`.
I'd appreciate it if someone could let me know if this is something that can be fixed in the test, or if it is a bug in the Allegro implemen...This test fails because the test expects a `type-error`, but Allegro raises a `:program-error`.
I'd appreciate it if someone could let me know if this is something that can be fixed in the test, or if it is a bug in the Allegro implementation. It seems like it *should* be a `type-error`, but does the spec *dictate* that it's a `type-error`? If so, I can report it to Franz; if not, I will move to checking for a `program-error` on Allegro (in my MR for #29, to come).https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/30COPY-HASH-TABLE EQ test fails on Allegro CL v 11 beta: Allegro result seems a...2023-05-03T14:51:29ZRobert GoldmanCOPY-HASH-TABLE EQ test fails on Allegro CL v 11 beta: Allegro result seems acceptable by specInvestigating in the REPL I see this:
```
ALEXANDRIA/TESTS> (multiple-value-setq (orig eq-copy)
(let ((orig (make-hash-table :test 'eq :size 123))
(foo "foo"))
(setf (g...Investigating in the REPL I see this:
```
ALEXANDRIA/TESTS> (multiple-value-setq (orig eq-copy)
(let ((orig (make-hash-table :test 'eq :size 123))
(foo "foo"))
(setf (gethash orig orig) t
(gethash foo orig) t)
(let ((eq-copy (copy-hash-table orig)))
(values orig eq-copy))))
#<EQ hash-table with 2 entries @ #x3078a3982>
ALEXANDRIA/TESTS> orig
#<EQ hash-table with 2 entries @ #x307a26422>
ALEXANDRIA/TESTS> eq-copy
#<EQ hash-table with 2 entries @ #x307816892>
ALEXANDRIA/TESTS> (hash-table-size orig)
191 (8 bits, #xbf, #o277, #b10111111)
ALEXANDRIA/TESTS> (hash-table-size eq-copy)
307 (9 bits, #x133)
```
Looking at the Spec, it doesn't seem like we are entitled to assume that a copy will have the same size -- the size is not the number of entries, and it seems to be under the implementation's control. At least that's how I read the following:
> Returns the current size of hash-table, which is suitable for use in a call to make-hash-table in order to produce a hash table with state corresponding to the current state of the hash-table.
I will submit a patch, together with my patch for #29 that disables this test on Allegro.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/29Add setf method for alexandria:ensure-gethash2023-05-02T19:17:46ZRobert GoldmanAdd setf method for alexandria:ensure-gethashI often want to do things like have hash tables that are list-valued (i.e., default to `nil`) and that can be set with `push` without having to worry about whether they have already been set (as an aside, Python's `defaultdict` provides ...I often want to do things like have hash tables that are list-valued (i.e., default to `nil`) and that can be set with `push` without having to worry about whether they have already been set (as an aside, Python's `defaultdict` provides this same facility in a different way).
So I added the following `setf` method for `ensure-gethash`:
``` lisp
(#+sbcl sb-ext:without-package-locks
#-sbcl progn
(defsetf alexandria:ensure-gethash (key table &optional default) (value)
(let ((tempvar (gensym "TMP")))
`(let ((,tempvar (alexandria:ensure-gethash ,key ,table ,default)))
(declare (ignorable ,tempvar))
(setf (gethash ,key ,table) ,value)))))
```https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/28READ-STREAM-CONTENT-INTO-STRING no longer works with bivalent streams2022-08-22T13:27:42ZMichał Herdaphoe@disroot.orgREAD-STREAM-CONTENT-INTO-STRING no longer works with bivalent streamsLet me repost a conversation from `alexandria-devel` - the first email/diff outlines the problem, the rest is the follow-up discussion.
Madhu <enometh@meer.net>:
```diff
* alexandria-1/io.lisp: (read-stream-content-into-string): fix re...Let me repost a conversation from `alexandria-devel` - the first email/diff outlines the problem, the rest is the follow-up discussion.
Madhu <enometh@meer.net>:
```diff
* alexandria-1/io.lisp: (read-stream-content-into-string): fix recent
lossage: This addresses problems in commits (13b1575, 6ff6820,
9c97e6f, on 2021-10-24), which changed the element-type of the array
used by READ-SEQUENCE to read from the stream from CHARACTER to the
STREAM-ELEMENT-TYPE of the stream.
On CCL, ECL etc. this breaks nyxt's source/start.lisp:(listen-socket)
which basically does
(iolib:with-open-socket (s :address-family :local :connect :passive :local-filename "/tmp/foo")
(alexandria:read-stream-content-into-string (iolib:accept-connection s)))
Iolib returns an octet stream for which the STREAM-ELEMENT-TYPE is not
CHARACTER. READ-STREAM-CONTENT-INTO-STRING uses WITH-OUTPUT-TO-STRING
and that calls MAKE-STRING-OUTPUT-STREAM, the argument
:ELEMENT-TYPE ((UNSIGNED-BYTE 8)) which fails because it must be a
subtype of character
The present fix is to check if it is not a character stream and force
set the element-type to 'character if it is not.
---
alexandria-1/io.lisp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/alexandria-1/io.lisp b/alexandria-1/io.lisp
index d3be536..8c93dd6 100644
--- a/alexandria-1/io.lisp
+++ b/alexandria-1/io.lisp
@@ -65,6 +65,8 @@ (defun read-stream-content-into-string (stream &key (buffer-size 4096))
(check-type buffer-size positive-integer)
(let ((*print-pretty* nil)
(element-type (stream-element-type stream)))
+ (unless (subtypep element-type 'character)
+ (setq element-type 'character))
(with-output-to-string (datum nil :element-type element-type)
(let ((buffer (make-array buffer-size :element-type element-type)))
(loop
```
Attila:
> just a quick note: SUBTYPEP calls can be *very* costly.
Me:
> This doesn't look like a problem on the Alexandria side. Stuffing ub8 values into any place that requires characters *always* requires additional information about character encoding (is it latin1? latin2? windows-1250?) and dealing with character encodings is out of scope of Alexandria. I think that Flexi Streams/Babel should be explicitly used in this context.
Madhu:
> 1\. The function contract requires it to return a string which is of type character. 2. Arranging to call WITH-OUTPUT-TO-STRING with an octet backing it is buffer is a bug. 3. Lisps implementation support bivalent streams and alendria (correctly) deferred to the implementations behaviour, and this has been changed.
>
> If we accept your position, READ-STREAM-CONTENT-INTO-STRING function would have to be removed from alexandia, since it cannot support it.
Me:
>> 1\. The function contract requires it to return a string which is of type character.
>
>The function contract doesn't say anything about accepting a stream whose element type is not a character.
>
>> 3\. Lisps implementation support bivalent streams and alendria (correctly) deferred to the implementations behaviour, and this has been changed.
>The fact that implementations support bivalent streams as a language extension doesn't mean that trying to stuff octets into strings is portable Common Lisp. The third bullet in Alexandria's README (https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/master/README) states that Alexandria is all about portable CL.
>
> Still, after waking up, I am of two minds about this issue, since there's also the issue of programmer convenience, "don't break userspace", and "if an implementation supports an extension, Alexandria could at least try not to get in the way". Are you able to make an account at https://gitlab.common-lisp.net and post an issue to https://gitlab.common-lisp.net/alexandria/alexandria/-/issues? If not, I'll make it and try to ask for opinion there.
Madhu:
> Hello, no I do not have a c-l.net account (and I'm not sure I want to create one now because of personal issues with gitlab---I do have a github account but that may not help).
>
> My own opinion is of course that the previous behaviour should be supported either by reverting the changes or by biting the bitter pill (of some "non-portability"), I trust you will make a suitable decision. --Best Regards, Madhuhttps://gitlab.common-lisp.net/alexandria/alexandria/-/issues/27DECLARE the hash table utils INLINE2023-10-17T22:08:49ZMichał Herdaphoe@disroot.orgDECLARE the hash table utils INLINEhttps://gitlab.common-lisp.net/alexandria/alexandria/-/blob/9acc5bd5064d941bc0929d14aca82225aefb464c/alexandria-1/hash-tables.lisp#L52-101
`hash-table{keys,values}`, `{alist,plist}-hash-table` and `hash-table-{alist,plist}` can be decla...https://gitlab.common-lisp.net/alexandria/alexandria/-/blob/9acc5bd5064d941bc0929d14aca82225aefb464c/alexandria-1/hash-tables.lisp#L52-101
`hash-table{keys,values}`, `{alist,plist}-hash-table` and `hash-table-{alist,plist}` can be declared `inline`, I think - is there a reason why only `maphash-{keys,values}` are made so right now?https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/26TYPE= tests might be overzealous2024-01-25T17:40:02ZMichał Herdaphoe@disroot.orgTYPE= tests might be overzealousIt seems that it's possible for an implementation to return the following (see [this thread](https://github.com/armedbear/abcl/issues/433)):
```
CL-USER(3): (subtypep '(or null cons) 'list)
T
T
CL-USER(4): (subtypep 'list '(or null cons...It seems that it's possible for an implementation to return the following (see [this thread](https://github.com/armedbear/abcl/issues/433)):
```
CL-USER(3): (subtypep '(or null cons) 'list)
T
T
CL-USER(4): (subtypep 'list '(or null cons))
NIL
NIL
CL-USER(5): (subtypep 'null '(and symbol list))
T
T
CL-USER(6): (subtypep '(and symbol list) 'null)
NIL
NIL
```
It seems that the tests for `TYPE=` do not take this into account and therefore they fail on ABCL.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/25string element types should perhaps be smarter2022-02-25T12:20:15ZTim Bradshawstring element types should perhaps be smarter20211024
Issue text
string element types should perhaps be smarter
This is closely related to #24, but unlike that issue my suggested solution is, potentially, not completely compatible although I rather doubt anything will care.
(1....20211024
Issue text
string element types should perhaps be smarter
This is closely related to #24, but unlike that issue my suggested solution is, potentially, not completely compatible although I rather doubt anything will care.
(1.) `read-file-into-string` opens the file with an external format specified by an argument to the function, but doesn't specify the element type. That means that in conforming implementations you'll always get `character`, and on implementations like LW which have a make-thinner-strings-by-default option you may get an error if you specify an external format which will produce `character`s (this is a deficiency in LW I think although it's the documented behaviour: I've suggested that `open` could 'fatten' the stream in the case where the external format clearly implies character types larger than the default one).
I think a solution to (1) is to specify the element type as `:default` which will explicitly produce an element type big enough for the external format. this keeps LW happy but also will mean that other implementations which may be able to produce thinner strings may actually be able to do that. On the other hand the element types of those strings will now not be `character` so this is potentially a slightly incompatible change.
(2) `write-string-into-file` also does not specify the element type of the stream. This can, again, break on LW for the same reasons as (1). I think it safe to specify it as `:default` which means it will always correspond to whatever the external format implies.
I believe that (2) is a fully compatible change.