On 1/19/23 10:11 PM, Ruby The Roobster wrote:
> Take this example:
import std;
void main()
{
auto c = "a|b|c|d|e".splitter('|');
c.writeln;
string[] e = ["a", "b", "c", "d", "e"];
assert(c.equal(e));
typeof(c).stringof.writeln;
}
The program prints:
["a", "b", "c", "d", "e"]
Result
What is the purpose of this 'Result' type? To serve as a generic range? Because, it seems to only cause problems. For example, you cannot assign or cast the result type into a range, even when the type has the same inherent function:
string[] c = "a|b|c|d|e".splitter('|'); // fails
string[] d = cast(string[])"a|b|c|d|e".splitter('|'); // also fails
The Result
type is an internal type that provides a lazily-evaluated range of the original string. That is, no array is allocated, and the actual searching of the |
character isn't done until you start fetching each element.
It returns windows into the original string, and builds each window one element at a time (via slicing).
So when you say "cast to a range", you are incorrectly stating the type string[]
as a "range", when you are trying to cast to an array of strings. The Result
type is a range, it's a range of strings. But it is not an array. If you want an array, you can use the split
function, which allocates an array to hold all the slices.
> And if you need to perform a set operation?
c[] ~= "lolno"; // fails, as [] isn't defined for Result.
Right, because a Result
is not an array. Appending is an array operation, not a range operation.
> Then what is the point of this type, if not to just make things difficult? It cannot be casted, and vector operations cannot be performed, and it seems to just serve as an unnecessary generalization.
The point is to be a range over the original input, evaluated lazily. Using this building block, you can create an array, or use some other algorithm, or whatever you want. All without allocating more space to hold an array.
-Steve