Though the docstrings do not explicitly say that this will work even when the stream is closed, I find it surprising behavior, because the behavior stated in the docstring does not happen either. Is this intended? What’s the rationale?
I couldn’t find any mention of what happens when writing to a closed IO:
The docstring of print([io::IO], xs...) says nothing about this and links to show: “print falls back to calling the 2-argument show(io, x) for each argument x in xs”.
The docstring of show(io::IO, mime, x) doesn’t mention writing to a closed IO either and says that “the function body calls write (or similar) to write that representation of x to io”.
The docstring of write(io::IO, x) doesn’t say anything about writing to a closed ioeither and links back to print.
“No documentation found for public binding Core.IO.”
IOStream doesn’t mention closed streams.
The docstring for close(stream) doesn’t explain what it means to “Close an I/O stream” and what happens if one tries to interact with a closed stream.
the rest are details. Usually, when a docstring says “do x”, it is understood that not doing x is an exception, ie an error.
But I don’t want to language lawyer here, I am wondering if others find it surprising, and whether it should be reported in an issue. Ie I am more interested in a practical discussion than whether arguing about the docstrings.
print(io::IO, s::Union{String,SubString{String}}) simply calls write and always returns nothing.
write(io::IO, s::Union{String,SubString{String}}) calls unsafe_write, which returns an integer (the number of bytes written). So print just wastes the returned value of write.
In the case of a closed IO, write fails to write and returns zero:
julia> let
io = open("/tmp/test", "w")
close(io)
@which write(io, "test")
end
write(io::IO, s::Union{SubString{String}, String})
@ Base strings/io.jl:246
julia> let
io = open("/tmp/test", "w")
close(io)
write(io, "test")
end
0
BTW, writing zero bytes isn’t exactly an error because I guess it’s technically valid to write an empty string, thus correctly writing zero bytes.
print seems to literally be print(io::IO, s::Union{String,SubString{String}}) = (write(io, s); nothing), so it never checks what write returned.
I think write(::IO, x) should somehow indicate an error if the number of bytes written by unsafe_write does not equal the number of bytes in x.
This is a bug in write. It should error if it cannot write the full output, not just return zero. The error should then have details on why the write failed or if it was a partial write the error would contain the number of bytes written.