On Monday, January 6, 2025 1:15:23 PM MST Renato via Digitalmars-d-learn wrote:
> On Monday, 6 January 2025 at 19:58:12 UTC, H. S. Teoh wrote:
> > On Mon, Jan 06, 2025 at 07:30:27PM +0000, Renato via Digitalmars-d-learn wrote:
> >> Is there any Phobos function that collects "some" items of a
> >> range
> >> into an array/slice?
> >> It's kind of embarrassing that I've been trying to find this
> >> for hours
> >> now without success :(.
> > [...]
> >> My use case is to parse a file format where a line is expected to have 4 items. I am currently using `takeExactly(4)` but that doesn't let me index on it, so I can only think of doing inconvenient (and inefficient) stuff like `front, skip(1).front ...` to avoid having to write my own `toArray` :D. I couldn't even find a method to take 1 item and advance the range! Am I just looking at the entirely wrong places (std.range, std.algorithm.iteration)??
> > [...]
> >
> > What's wrong with just using std.array.array?
> >
> >
> > T
>
> So I was indeed looking at the wrong place. It's not very intuitive to me that a function that acts on ranges is not in std.range but in std.array.
>
> I guess the idea is to keep std.range pure (all functions take and return ranges, not slices/arrays/HashMaps etc.)?
std.range contains the core functions for creating and operating on ranges which arguably aren't algorithms, whereas std.algorithm has general algorithms that operate on ranges (and frequently return ranges), though the distinction is not always as clear as it should be, and there's certainly some debate as to whether individual functions are where they should be.
std.array generally has functions which operate on arrays, but it also has functions for generating arrays, and a lot of functions which were originally intended for arrays have ultimately either ended up in std.algorithm or had variants of them end up in std.algorithm as they've been more generalized. What's left in std.array though is typically eager and returns arrays rather than returning ranges (and many functions in std.algorithm return lazy ranges, though some are eager in cases where they return part of the original range rather than a wrapper range).
std.string then has functions for operating on strings, but it has some overlap with std.array, because strings are arrays, and just like some of the functions in std.array either got moved to std.algorithm when they were made more general, or we ended up with more general variants in std.algorithm, some functions in std.string were made to operate on arrays in general rather than strings specifically, and so they got moved in std.array.
All in all, while the basic distinctions are relatively clear, there's always going to be some debate about which module a particular function belongs in, and sometimes functions have been moved if it was decided that they were definitely in the wrong place. And as functions have been made more general, sometimes the place that the function arguably should be has changed, and the functions have not always been moved as they've been changed.
One example would be split. IIRC, it was in std.string originally, becaause it split on whitespace specifictally. But then it was made more general and gained an overload that let you indicate what to split on, which made it so that it was moved to std.array (and a public import was left in std.string to avoid breaking code). And later, we got splitter, which operates on ranges in general and returns a lazy range rather than returning an array like split does. And somewhere in there, we also ended up with split being expanded to work on ranges in general, but it returns an array, so it still make sense for it to be in std.array, but it's no longer just operating on arrays.
In any case, since Phobos in general uses ranges all over the place, it really doesn't make sense that std.range would have all of the range-related functions. It just has some of the core ones that are range-specific and arguably not algorithms (but again, the distinctions can be blurry at times). And regardless of how clear some of the distinctions between the modules were originally, those lines have been blurred as the functionality of some of the functions involved has expanded. So, understanding the basic distinctions between the various modules helps make it possible to find stuff more easily, but functions aren't always where you might expect them to be, depending on what your expectations are.
- Jonathan M Davis
|