1

I am working with Allegro CL 11.0 Express Edition on Linux (Ubuntu 16.04). I am seeing behavior from READ-SEQUENCE which is surprising to me. Is the following conforming to the CLHS? EDIT: Franz, Inc. confirms that this is a bug. See the PS for more info.

In this example, twobytes.txt is a file which contains a followed by a newline.

$ /usr/local/acl11.0express.64/alisp
International Allegro CL Free Express Edition
11.0 [64-bit Linux (x86-64)]
Copyright (C) 1985-2023, Franz Inc., Lafayette, CA, USA.  All Rights Reserved.

This development copy of Allegro CL is licensed to:
   Allegro CL 11.0 Express user

;; Optimization settings: safety 1, space 1, speed 1, debug 2,
;; compilation-speed 1.
;; For a complete description of all compiler switches given the
;; current optimization settings evaluate (EXPLAIN-COMPILER-SETTINGS).
CL-USER(1): (defvar f (open "twobytes.txt" :element-type '(unsigned-byte 8)))
; Autoloading for EXCL::GRAY-OPEN:
; Fast loading from bundle code/streamc.fasl.
;   Fast loading from bundle code/efft-utf-8s-base.fasl.
;   Fast loading from bundle code/efft-utf8-base.fasl.
;   Fast loading from bundle code/efft-void.fasl.
;   Fast loading from bundle code/efft-latin1-base.fasl.
F
CL-USER(2): (defvar l (list 1 1 1 1 1 1))
L
CL-USER(3): (read-sequence l f)
6
CL-USER(4): l
(97 10 :EOF :EOF :EOF :EOF)

Is this a bug? I expected the return value of READ-SEQUENCE to be 2 instead of 6, and I expected L to be (97 10 1 1 1 1) afterwards.

When I try the same code with SBCL or Clozure CL, I get the expected results.

For the record, CLHS says

If the end of file for stream is reached before copying all elements of the subsequence, then the extra elements near the end of sequence are not updated.

I looked for a list of known bugs for Allegro CL, but I was unable to find any such list.

PS. I submitted a bug report to Franz, Inc. and a representative confirms that it's a bug in the implementation of Gray streams. The workaround that was suggested is to omit :element-type, then OPEN will return a FILE-SIMPLE-STREAM, which, fortuitously, has :element-type equal to (unsigned-byte 8), and the READ-SEQUENCE bug is not present. Here is the same example as before, this time with expected behavior.

CL-USER(1): (defvar f (open "twobytes.txt"))
F
CL-USER(2): f
#<FILE-SIMPLE-STREAM #P"twobytes.txt" for input pos 0 @ #x100079bfd22>
CL-USER(3): (defvar l (list 1 1 1 1 1 1))
L
CL-USER(4): (read-sequence l f)
2
CL-USER(5): l
(97 10 1 1 1 1)
5
  • Looks like a bug to me. The documentation is very clear that your expected results are correct. Commented Feb 27 at 18:09
  • Apparently Allegro CL doesn't have a public bug list. Send email to [email protected]. Commented Feb 27 at 18:19
  • what happens if you open the file as a text stream? Commented Feb 27 at 22:49
  • Interesting, it may seem to open the stream as a Gray stream, when such an element type is given. Commented Feb 27 at 23:06
  • stream-read-byte is documented to return :eof when the stream is at end of file. Commented Feb 27 at 23:13

1 Answer 1

4

You are calling open with an element type, which isn't a character, but an unsigned byte.

This causes in Allegro CL the autoloading of some Gray Streams functionality (see your output). Gray Streams are an old specification for CLOS based stream implementation. Then the Common Lisp system will use CLOS based stream functions like stream-read-sequence and stream-read-byte to read from streams. These functions have different (simplified) argument and return values, compared to the standard functions read-sequence and read-byte.

So, for Allegro CL:

  • OPEN on a file with unsigned byte creates a Gray Stream object.

  • READ-SEQUENCE then calls EXCL:STREAM-READ-SEQUENCE, which creates this observed result

CLOS Streams

In LispWorks 8 I can use the CLOS generic function STREAM:STREAM-READ-SEQUENCE for a file /tmp/a.txt with two characters:

CL-USER 29 > (let ((seq (list 1 1 1 1 1 1 1 1)))
               (with-open-file (s "/tmp/a.txt"
                                :element-type '(unsigned-byte 8))
                 (values (stream:stream-read-sequence
                            s seq 0 (length seq))
                         seq)))
2
(97 10 1 1 1 1 1 1)

Now, what would happen if one uses EXCL:STREAM-READ-SEQUENCE in Allegro CL?

It puts :eof into the list, so I suspect that its implementation fails to detect the possible :eof value of excl:stream-read-byte.

Allegro CL:

CG-USER(7): (let ((seq (list 1 1 1 1 1 1 1 1)))
               (with-open-file (s "/tmp/a.txt"
                                :element-type '(unsigned-byte 8))
                 (values (excl:stream-read-sequence s seq 0 (length seq))
                         seq)))
8
(97 10 :EOF :EOF :EOF :EOF :EOF :EOF)

and if we don't specify the element type, we get this result:

CG-USER(9): (let ((seq (list 1 1 1 1 1 1 1 1)))
               (with-open-file (s "/tmp/a.txt")
                 (values (read-sequence seq s)
                         seq)))
2
(97 10 1 1 1 1 1 1)

Interestingly enough, this opens the stream as with element type unsigned-byte 8.

Sign up to request clarification or add additional context in comments.

9 Comments

Why does a character stream return character codes instead of characters?
@barmar: good question. First I thought I copied a wrong/edited example. But no. That's the result. Allegro CL (macOS, Apple Silicon) opens the stream with element type unsigned-byte 8, when the element type is not given. If I open the stream with element type character, explicitly, then I get characters.
@barmar: the Allegro CL doc says: "The Allegro CL streams model uses simple-streams, which formally have no element-type but act in general as if they have element type (unsigned-byte 8)."
Strange. The spec says that the default element type should be character.
@RainerJoswig Thanks, I got a confirmation from Franz, Inc. that it's a bug; I've edited the problem statement to say more about that.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.