Conversation
|
Thanks to @andyferris for the idea. |
Formatting.md
Outdated
|
|
||
| where `stringformat` is the appropriately defined function returning a formatted string. | ||
|
|
||
| However this may result in large numbers of intermediate allocations of small strings. Ideally we would want this to lower to something like |
There was a problem hiding this comment.
Interpolation could instead call something like stringformat(io, pi, fracdigits=4) on the io::IOBuffer that is used for string construction by string.
Maybe "π is approximately $(pi, fracdigits=4)." could instead lower string("π is approximately ", StringFormat(pi, fracdigits=4), "."), where a f::StringFormat{T,KW} object caches both the object pi::T and a namedtuple (fracdigits=4,)::KW, and has a print(io, f) method (used by both string and print).
There was a problem hiding this comment.
i.e.
immutable StringFormat{T,KW}
x::T # the value to be printed
kws::KW # NamedTuple of keyword arguments
end
write(io::IO, f::StringFormat) = write(io, f.x) # fallback methodThere was a problem hiding this comment.
this wouldn't immediately help with the print(io, "π is approximately $(pi, fracdigits=4).") case though.
There was a problem hiding this comment.
You would pass StringFormat(...) in that case.
I don’t think we’d want $ there
There was a problem hiding this comment.
Wait, I misread it. Yes, you’d write twice there. Not sure it’s a big deal.
There was a problem hiding this comment.
One option would be to lower to LazyString(...) instead of string(...)
|
I was wondering - do we need a new |
|
We could for keyword arguments, but not for positional (since |
|
Just to pull together my (now hidden) suggestions from above, what if we made LazyString(("π is approximately ", StringFormat(pi, fracdigits=4), "."))with the definitions: # String-like object formed by lazily concatenating printed args
struct LazyString{T<:Tuple} <: AbstractString
args::T
end
function write(io::IO, ls::LazyString)
# write this loop more cleverly to unroll at compile-time
for arg in ls.args; print(buf, arg); end
end
String(ls::LazyString) = let buf=IOBuffer(); write(buf, ls); String(take!(buf)); end
# ... other string methods...
struct StringFormat{T,KW}
x::T # the value to be printed
kws::KW # NamedTuple of keyword arguments
end
write(io::IO, f::StringFormat) = print(io, f.x) # fallback methodThen you could write specialized Using a (This would be a breaking change since |
|
I can see why we'd want |
|
I agree that from a usability perspective, strings should be the default result. Another option would be to make the lazy version available via a string macro? |
|
A negative thing about having the formatting inline is that it makes it harder to read the string: vs Separating content and formatting is usually also a good idea. |
|
@KristofferC I haven't seen any other language do that sort of thing, but we could do that via |
|
Note that all of this could potentially be implemented in a package if you are willing to use a string macro, e.g. |
|
You could just do |
|
@MikeInnes, the problem with that is that it forces the construction of a temporary string, which slows down I/O. |
No description provided.