Skip to content

Commit 7e55049

Browse files
committed
Improve the annotated join method and dispatch
With the initial implementation, join could work for AnnotatedStrings, however only when the eltype of the iterator or delim was itself a Annotated{String,Char}. This was better than nothing, but seems inconsistent in the face of mixed iterators. Furthermore, the implementation of an annotated join was far from optimised, relying on zipping and then calling annotatedstring(xs...). By contrast, the non-annotated implementation relies on printing to IO and even has manually defined alternative methods for optional arguments to minimise code generation. With the advent of AnnotatedIOBuffer and _isannotated, we can improve on both those aspects. The new AnnotatedIOBuffer type allows us to re-use the optimised join(::IO, ...) methods, and we can more reliably dispatch to them with _isannotated. Since this is a type-based decision, the Julia compiler is kind enough to work out which branch is taken at compile-time, making this zero-overhead in the unannotated case.
1 parent 6e7db14 commit 7e55049

File tree

1 file changed

+9
-18
lines changed

1 file changed

+9
-18
lines changed

base/strings/io.jl

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,28 +353,19 @@ function join(io::IO, iterator, delim="")
353353
end
354354
end
355355

356-
# TODO: If/when we have `AnnotatedIO`, we can revisit this and
357-
# implement it more nicely.
358-
function join_annotated(iterator, delim="", last=delim)
359-
xs = zip(iterator, Iterators.repeated(delim)) |> Iterators.flatten |> collect
360-
xs = xs[1:end-1]
361-
if length(xs) > 1
362-
xs[end-1] = last
363-
end
364-
annotatedstring(xs...)::AnnotatedString{String}
365-
end
366-
367-
function _join_maybe_annotated(args...)
368-
if any(_isannotated eltype, args)
369-
join_annotated(args...)
356+
function _join_preserve_annotations(iterator, args...)
357+
if _isannotated(eltype(iterator)) || any(_isannotated, args)
358+
io = AnnotatedIOBuffer()
359+
join(io, iterator, args...)
360+
read(seekstart(io), AnnotatedString{String})
370361
else
371-
sprint(join, args...)
362+
sprint(join, iterator, args...)
372363
end
373364
end
374365

375-
join(iterator) = _join_maybe_annotated(iterator)
376-
join(iterator, delim) = _join_maybe_annotated(iterator, delim)
377-
join(iterator, delim, last) = _join_maybe_annotated(iterator, delim, last)
366+
join(iterator) = _join_preserve_annotations(iterator)
367+
join(iterator, delim) = _join_preserve_annotations(iterator, delim)
368+
join(iterator, delim, last) = _join_preserve_annotations(iterator, delim, last)
378369

379370
## string escaping & unescaping ##
380371

0 commit comments

Comments
 (0)