[LISPWORKS][Common Lisp HyperSpec (TM)] [Previous][Up][Next]


Issue STRING-OUTPUT-STREAM-BASHING Writeup

Issue:              STRING-OUTPUT-STREAM-BASHING

References: WITH-OUTPUT-TO-STRING

GET-OUTPUT-STREAM-STRING

FORMAT

Related issues: MAPPING-DESTRUCTIVE-INTERACTION

WITH-OUTPUT-TO-STRING-APPEND-STYLE

Category: CLARIFICATION

Edit history: V1, 12 Feb 1991, Sandra Loosemore

Problem description:

Is it valid to call GET-OUTPUT-STREAM-STRING on a stream bound by

WITH-OUTPUT-TO-STRING? If so, must the WITH-OUTPUT-TO-STRING still

return a string containing *all* of the collected output to the

stream? Or should only output collected since the last call to

GET-OUTPUT-STREAM-STRING be returned?

The ambiguity exists for both the case where no string argument is

provided to WITH-OUTPUT-TO-STRING (where the string is returned as its

value) and where a string with a fill pointer is provided and

destructively modified. There is also a problem with string output

streams created by calls to FORMAT when its stream argument is NIL or

a string with a fill pointer, although users have to try harder to

get their hands on the stream object in that case.

It is also not clear what the effects of destructive modifications to

a string supplied as an argument to WITH-OUTPUT-TO-STRING or FORMAT

are supposed to be.

Proposal (STRING-OUTPUT-STREAM-BASHING:UNDEFINED):

Clarify that the consequences of calling GET-OUTPUT-STREAM-STRING

on a stream created by WITH-OUTPUT-TO-STRING or FORMAT are undefined.

In the cases where a string argument with a fill pointer is supplied

as an argument to WITH-OUTPUT-TO-STRING or FORMAT, the consequences

are undefined if destructive modifications are performed directly on

the string during the dynamic extent of the call.

Examples:

#1: (with-output-to-string (s)

(prin1 'foo s) (print (get-output-stream-string s))

(prin1 'bar s) (print (get-output-stream-string s)))

=> Under proposal UNDEFINED, this program is in error.

#2: (let ((x (make-array 100 :element-type 'standard-char :fill-pointer 0)))

(with-output-to-string (s x)

(prin1 'foo s) (print (get-output-stream-string s))

(prin1 'bar s) (print (get-output-stream-string s)))

x)

=> Under proposal UNDEFINED, this program is in error.

#3: (let ((x (make-array 100 :element-type 'standard-char :fill-pointer 0)))

(with-output-to-string (s x)

(prin1 'foo s) (setf (fill-pointer x) 0)

(prin1 'bar s) (setf (fill-pointer x) 0))

x)

=> Under proposal UNDEFINED, this program is in error.

Rationale:

Calling GET-OUTPUT-STREAM-STRING is a destructive modification of

the stream being manipulated by WITH-OUTPUT-TO-STRING or FORMAT.

It would be consistent with issue MAPPING-DESTRUCTIVE-INTERACTION

to prohibit this. Likewise, some implementations become confused if

the string with fill pointer underlying a string output stream is

modified directly.

Current Practice:

Lucid, Allegro, and Symbolics Genera all print "FOO" and "BAR" and

return "" from test case 1, but vary in the behavior of the other

cases.

Cost to Implementors:

No implementation would be forced to change by this proposal.

Cost to Users:

Probably few user programs rely on any particular behavior here.

Cost of non-adoption:

Continuing vagueness in the language specification.

Performance impact:

N/A

Benefits:

The costs of non-adoption are avoided.

Esthetics:

It might be more esthetic to try to specify the behavior. In the

case of WITH-OUTPUT-TO-STRING where no string argument is provided

and FORMAT with a stream argument of NIL, the behavior could easily

be explained in terms of the obvious implementation of these constructs

using MAKE-STRING-OUTPUT-STREAM and GET-OUTPUT-STREAM-STRING. However,

there are no corresponding primitives for creating a string stream from

a string with a fill pointer.

Discussion:

-------


[Starting Points][Contents][Index][Symbols][Glossary][Issues]
Copyright 1996-2005, LispWorks Ltd. All rights reserved.