Ticket #827 (closed defect: duplicate)

Opened 4 years ago

Last modified 21 months ago

2D bitmap print-non-readably behavior is misleading

Reported by: mcpublic Owned by:
Priority: normal Milestone:
Component: other Version: trunk
Keywords: reader printer Cc: fred@…

Description (last modified by gb) (diff)

Summary: 2D Bitmap arrays print non-readably, #2A(#*101010 #*010101) doesn't read as 2D array, barfs, ...AND... can't create a 2D bitmap using reader.

If you create a 2D bitmap using (make-array '(4 4) :element-type '(mod 2)) The result will print as #2A(#*0000 #*0000 #*0000 #*0000) When you read it back in, the reader barfs:

> Error: Reader error on #<CCL::RECORDING-CHARACTER-INPUT-STREAM #xC75FFE6>, near position 32:
>        Initial contents for #A is inconsistent with dimensions: #2A(#<SIMPLE-BIT-VECTOR 4> #<SIMPLE-BIT-VECTOR 4> #<SIMPLE-BIT-VECTOR 4> #<SIMPLE-BIT-VECTOR 4>)

The related bug is that #1A(#*0000 #*0000 #*0000 #*0000) works "just fine" except it creates a 1D array.

Apparently there is no way to create a 2D bitmap from the reader.

Change History

comment:1 Changed 4 years ago by gb

  • Status changed from new to closed
  • Resolution set to invalid
  • Description modified (diff)

Common Lisp in fact doesn't define reader syntax for multidimensional arrays with an element-type other than T, so it shouldn't be surprising that your attempts to do so don't work.

Since there's no way to read a constant-valued multidimensional bit array, it shouldn't be surprising that there's no way to print one in a way that can be read as an equivalent object.

When CL:*PRINT-READABLY* is true, any attempt to print a bit array which has other than one dimension will fail (signaling a CL:PRINT-NOT-READABLE error.) When CL:*PRINT-READABLY* is false and CL:*PRINT-ARRAY* is true, an implementation is allowed to print a multidimensional BIT array using syntax that's suggestive (to a human reader) of its element type; see CLHS 22.1.3.8. CCL does use this syntax; of course, it isn't a READable representation of the bit array, either.

None of this has anything to do with CCL. The behavior that you expect isn't entirely unreasonable, it just doesn't have much to do with how Common Lisp is defined to behave. Fortunately, the standard CL reader and printer can be extended, and if you're just learning CL you might find doing so to be a worthwhile exercise.

comment:2 Changed 4 years ago by mcpublic

  • Status changed from closed to reopened
  • Resolution invalid deleted
  • Component changed from ANSI CL Compliance to other
  • Summary changed from No way to create a 2D bitmap from the reader, and related bugs to 2D bitmap print-non-readably behavior is misleading

Hi Gary,

Tim McNerney? here... (sorry, I supposed I should have logged in under my old Clozure employee login name, but I figured it was no longer active.).

Yes, you are right: CL gives implementations a lot of latitude. And so CCL can be completely compliant with the CL spec and yet still have self-inconsistent behavior. So I have no problem conceding that this is not a CL-compliance issue, but I think it is still worth fixing. In the case where (*print-array* = T, and *print-readably* = NIL) I might suggest that it would be better for PRINT not to mislead users into thinking that #2A(#*... ) is acceptable to READ.

I opened this ticket because I have high standards for CCL, and IHMO this printer/reader inconsistency makes CCL less than excellent, however "correct" it might be according to the ANSI spec.

With all due respect, I am reopening this bug so it can at least get discussed internally.

comment:3 Changed 4 years ago by gb

  • Status changed from reopened to closed
  • Resolution set to invalid

When a multidimensional array is printed when *PRINT-ARRAY* is true and *PRINT-READABLY* is false, the #nA syntax is used. This is non-negotiable; this is what the spec says and what anyone who bothered to read it should expect. Output in this case is supposed to provide the human reader information about the array's rank, dimensions, and contents; #nA syntax can't provide information about the array's element-type, and that's one reason that the printed representation of a multidimensional array isn't machine-readable in general. (Of course, one should never casually try to read output that wasn't generated with *PRINT-READABLY* true, anyway.)

Assuming that an implementation provides arrays with a specialized element type of (UNSIGNED-BYTE 8) - most do, but one can't assume this - then a 2x2 array of that element type will print (with these settings) the same way as a 2x2 array of element type T whose contents are equivalent. A 2x2 array of BIT might also print identically to these other cases, but the spec explicitly allows the innermost lists in the printed representation to be replaced by bit-vectors containing the same elements (and to use strings when the element type is CHARACTER); these are the only cases and this is the only way in which the printer can provide any element-type information to the human reader.

In exchange for that, the printed representation of the bit (or character) array ceases to look like a syntactically valid use of the #A reader macro. Since it's never been correct to read output generated with *PRINT-READABLY* false (for semantic/type reasons), making it syntactically invalid would seem to only affect those who were already ... misled ... about the issues.

Whether one evaluates those tradeoffs the same way or not, I have no doubt that whoever implemented that part of the printer this way considered those issues carefully before doing so; if you assume otherwise, you are very much mistaken.

comment:4 Changed 2 years ago by pjb@…

  • Status changed from closed to reopened
  • Resolution invalid deleted

I'll re-open this case.

Granted, the array read by #2A won't be a bit array but an array of T.

Nonetheless, #2A(#*00 #*11 #*10) should read a 2D array containing the same values as #2A((0 0) (1 1) (1 0)):

"2.4.8.12 Sharpsign A" says:

#nAobject constructs an n-dimensional array, using object as the value of the :initial-contents argument to make-array. 

and ccl implements make-array correctly:

cl-user> (make-array '(3 4) :element-type 't :initial-contents '(#*0000 #*1111 #*1100))
#2A((0 0 0 0) (1 1 1 1) (1 1 0 0))

This interpretation of the standard is also accepted by the other implementations.

$ clall -r '(array-dimensions #2A(#*0000 #*1111 #*1100))'

International Allegro CL Free Express Edition --> (3 4)
Clozure Common Lisp            Reader error on #<STRING-INPUT-STREAM  :CLOSED #x3020007ECD1D>: Initial contents for #A is inconsistent with dimensions: #2A(#*0000 #*1111 #*1100)
CLISP                          --> (3 4)
CMU Common Lisp                --> (3 4)
SBCL                           --> (3 4)

comment:5 Changed 21 months ago by bayerf

  • Cc fred@… added

comment:6 Changed 21 months ago by gb

  • Status changed from reopened to closed
  • Resolution set to duplicate

Most of the argument here has centered around whether or not it's appropriate to use "" or #* syntax to print the last dimension of a multidimensional array.

I think that the real bug is that described by ticket:1061. #nAarg should expect "arg" to be a sequence of sequences, but it was expecting either a list of lists or a vector of vectors and failing on the list of (bit) vectors produced in this case.

(My first reaction was to mark ticket:1061 as a duplicate of this ticket; I think that it's more appropriate to mark this as a duplicate of ticket:1061, which does a better job of describing the actual problem.)

Note: See TracTickets for help on using tickets.