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/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/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/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/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/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/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.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/22ALEXANDRIA:SWITCH does not accept a function value2021-04-15T10:39:40ZMichał Herdaphoe@disroot.orgALEXANDRIA:SWITCH does not accept a function valueThis works:
```lisp
(defun foo (thing)
(alexandria:switch (thing :test (lambda (thing list) (member thing list :test #'equal)))
('(1 2 3) :number)
('("1" "2" "3") :string)
('(:one :two :three) :keyword)))
```
This explod...This works:
```lisp
(defun foo (thing)
(alexandria:switch (thing :test (lambda (thing list) (member thing list :test #'equal)))
('(1 2 3) :number)
('("1" "2" "3") :string)
('(:one :two :three) :keyword)))
```
This explodes:
```lisp
(defun foo (thing)
(alexandria:switch (thing :test (alexandria:rcurry #'member :test #'equal))
('(1 2 3) :number)
('("1" "2" "3") :string)
('(:one :two :three) :keyword)))
```https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/20Make (R)CURRY globally INLINE to allow expansion of compiler macros2023-10-17T12:49:56ZPhoebe GoldmanMake (R)CURRY globally INLINE to allow expansion of compiler macrosAt present, `curry` and `rcurry` have preceding `inline` declarations which allow the collection of inlining information, and they have compiler macros, but both are globally disabled. In the absence of any documentation describing why i...At present, `curry` and `rcurry` have preceding `inline` declarations which allow the collection of inlining information, and they have compiler macros, but both are globally disabled. In the absence of any documentation describing why it would be beneficial not to inline these forms or to expand these compiler macros, I assume there is no good reason. SBCL has been issuing compiler notes at me every time I invoke `curry` or `rcurry` because it must emit typechecks that the result will be a function, and I would very much prefer not to start every source file of mine with `(declaim (inline curry rcurry))`. So, unless there's a good reason not to, please remove the `notinline` declaration for `curry` and `rcurry` at line 155 of functions.lisp and let the compiler macros do their job. Thanks!https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/17Add Travis CI config2024-01-31T22:59:00ZStelian IonescuAdd Travis CI configAlexandria should have automatic testing, and Travis seems the most common solution. If gitlab.common-lisp.net can't provide that, the repository should be moved to Github.Alexandria should have automatic testing, and Travis seems the most common solution. If gitlab.common-lisp.net can't provide that, the repository should be moved to Github.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/15Modify ROTATE/SHUFFLE and add NROTATE/NSHUFFLE2020-05-04T06:40:01ZMichał Herdaphoe@disroot.orgModify ROTATE/SHUFFLE and add NROTATE/NSHUFFLE## Issue
The current manual for `rotate` states:
> Note: the original sequence may be destructively altered, and result sequence may share structure with it.
This is inconsistent with the naming scheme for destructive operations in Co...## Issue
The current manual for `rotate` states:
> Note: the original sequence may be destructively altered, and result sequence may share structure with it.
This is inconsistent with the naming scheme for destructive operations in Common Lisp, which are commonly prefixed with `n`. This also means that Alexandria does not export a non-destructive sequence-rotating operation.
## Proposal
Move the current `fdefinition` of `rotate` into `nrotate` and export that new symbol. `rotate` may then be implemented by means of calling `nrotate` over `copy-sequence` to always work on fresh data.
## Cost to users
* User code may need to be modified to avoid double copying that results in effect of this change.
* Possible, but unlikely, package conflicts if another package used next to Alexandria exports a `nrotate` symbol.
* Possible breakage of user code if `rotate` was used only for its side effects and not for its return-value.
## Benefits to users
* Better separation of mutating from non-mutating operations by using the `n` prefix for mutating operations, just like with `nconc`, `nsubseq`, etc..
* Exporting a non-destructive functionality that performs the same operation as the new `nrotate` without mutating original data.
* The change is backwards-compatible protocol-wise if the return value of `rotate` was used.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/12FORMAT-SYMBOL does not accept a FORMATTER2024-01-31T09:39:53ZMichał Herdaphoe@disroot.orgFORMAT-SYMBOL does not accept a FORMATTER```lisp
CL-USER> (alexandria:format-symbol :keyword (formatter "~A~A") "FOO" "BAR")
Error: #<FUNCTION "fmt$~A~A" {52DB3B8B}> is not a string designator.
[Condition of type SIMPLE-TYPE-ERROR]
```
I claim that a formatter should be ac...```lisp
CL-USER> (alexandria:format-symbol :keyword (formatter "~A~A") "FOO" "BAR")
Error: #<FUNCTION "fmt$~A~A" {52DB3B8B}> is not a string designator.
[Condition of type SIMPLE-TYPE-ERROR]
```
I claim that a formatter should be accepted in order to preserve the semantics of `FORMAT`.
The simple fix is to remove the `STRING` call inside the body of `FORMAT-SYMBOL`.https://gitlab.common-lisp.net/alexandria/alexandria/-/issues/10if-let* would be nice2024-01-26T17:10:59ZMatthew Kraussif-let* would be niceI could use an `if-let*` macro. Wondering why there wasn't one already, I found that somebody tried to contribute it back in 2012, there was some question as to what should be bound in the else form, and then it seemed to die (https://ww...I could use an `if-let*` macro. Wondering why there wasn't one already, I found that somebody tried to contribute it back in 2012, there was some question as to what should be bound in the else form, and then it seemed to die (https://www.mail-archive.com/alexandria-devel@common-lisp.net/msg00493.html)
I could make a pull request for this, but before I do, wanted to check if there is some reason it hasn't been done...