Marco Leise:
return s.chunks(2).map!( c => [cast(char)c.dropOne.front, cast(char)c.front] ).join;So I would use the second version offered by bearophile: auto result = new char[s.length]; foreach (immutable i, ref c; result) c = s[i + (i & 1 ? -1 : 1)]; return result; I can easily reason about it from looking at it. It makes one allocation "new char[s.length]" and does no UTF-8 decoding.
But the first version with dropOne and two fronts is for me simper to see as correct, while in the second code I need a bit of thinking to prove there are no out of bounds accesses.
Perhaps for/foreach are becoming a code smell, they are becoming an optimization over the more common and safer functional code (or an alternative solution where the functional code is a problem).
To avoid the conditional (I have not benchmarked them): c = s[i + (2 * !(i & 1) - 1)]; Bye, bearophile
