I think it's fair to say that #<< *is* a bug. There does not seem to be any coherent description of what it means. It's overloaded to mean *either* #nextPut: *or* #nextPutAll: *or* something else, in some confusing ways. CommandLineHandler #nextPutAll: (sent somewhere else) Integer left shift (someone has been smoking too much C++) NonInteractiveTranscript #show: = locked #print: SocketStream #putOn: (which may itself act like #nextPut:, #nextPutAll:, #print, put elements sans separators, or something else) Stream #putOn: (see above) WriteStream either #nextPutAll: or #putOn: Transcript #show: = locked #print: ThreadSafeTranscript #show: = locked #print: VTermOutputDriver #putOn: VTermOutputDriver2 #asString then #nextPutAll: ZnEncodedWriteStream #nextPutAll: ZnHtmlOutputStream #asString then #nextPutAll: SequenceableCollection class #streamContents:
As was once said about PL/I, #<< fills a much-needed gap. When I see #print:, or #nextPut:, or #nextPutAll:, I know what to expect. When I see #putOn:, I have in general no idea what will happen. And when I see << it is worse. One point of << is to imitate C++'s composition of outputs. That might work, too, if only there were some agreement about what #nextPutAll: returns. There is not. It might return the receiver. It might return some other stream related to the receiver. It might even return the collection argument. So when you see a << b << c in general you not only do not have a clue what (a) is going to do with (b) but you have no idea what object the message << c will be sent to. Now let's see if we can puzzle out what Array streamContents: [ :s | s << 10 << '10' << #(10 '10') ] does. The output will be going to a WriteStream. aWriteStream << anInteger is not, but is like, aWriteStream print: anInteger. So we add $1 and $0. aWriteStream << aString reduces to aWriteStream nextPutAll: aString. So we add $1 and $0. aWriteStream on anArray << anotherArray reduces to aWriteStream nextPutAll: anotherArray. So we add 10 and '10'. Thus the result we get is #($1 $0 $1 $0 10 '10'). What result we should *expect* from this muddle I cannot say. If, on the other hand, you wrote explicitly Array streamContents: [:stream | stream print: 10; nextPutAll: '10'; nextPutAll: #(10 '10')] you would have an easy time figuring out what to expect. By the way, there is no standard definition of #show:, but in other Smalltalk systems it's usually a variant of #nextPutAll:, not a variant of #print:. There's no denying that locked output is useful to have, but #show: is not perhaps the best name for it.