Proposed Changes to the Range API for Phobos v3
Steven Schveighoffer
schveiguy at gmail.com
Sat May 18 20:21:01 UTC 2024
On Saturday, 18 May 2024 at 14:26:18 UTC, H. S. Teoh wrote:
> On Thu, May 16, 2024 at 08:56:55AM -0600, Jonathan M Davis via
> Digitalmars-d wrote: [...]
>> 1. The easy one is that the range API functions for dynamic
>> arrays will not treat arrays of characters as special. A
>> dynamic array of char will be a range of char, and a dynamic
>> array of wchar will be a range of wchar.
>>
>> Any code that needs to decode will need to use the phobos v3
>> replacement for std.utf's decode or decodeFront - or use
>> foreach - to decode the code units to code points (and if it
>> needs to switch encodings, then there will be whatever
>> versions of byUTF, byChar, etc. that the replacement for
>> std.utf will have).
>
> I thought we already have this? std.string.byRepresentation,
> std.uni.byCodePoint, std.uni.byGrapheme already fill this need.
Yes, all those would be present, except possibly
`byRepresentation`.
I think the message is that `somestr.front` will not decode, you
need to use `decodeFront` or whatnot.
>
>
> [...]
>> However, with infinite ranges, there is no such solution. If
>> they cannot be default-initialized, then they either can't be
>> ranges, or they would have to be finite ranges which would
>> just never be empty if they're constructed at runtime (while
>> doing something like the flag trick to make their init value
>> empty). And it's certainly true that the range API doesn't
>> (and can't) guarantee that finite ranges are truly finite, but
>> it's still better if we can define infinite ranges that need
>> to be constructed at runtime as infinite ranges, since then we
>> can get the normal benefits that come from statically knowing
>> that a range is infinite.
>
> Infinite ranges also have the peculiarity that slicing may
> create a finite range, i.e., the underlying type changes.
> That's another wrinkle to deal with.
The `hasSlicing` test is very hard to understand. But it looks
like it either it's infinite, or the slice must be the same type
as the range itself.
So I think we already are dealing with this, and I wouldn't
expect it to change.
Clearly, `.init` is going to be the same type, and we can exploit
that for emptying a range.
I wouldn't expect the rules for hasSlicing to change.
>
>
> [...]
>> 4. All ranges must be either dynamic arrays or structs (and not
>> pointers to structs either).
>
> Although, come to think of it, we could have a .byRef range
> wrapper that encapsulates a pointer to the range so that
> changes to iteration state would be preserved. But then it
> begs the question, why not just allow pointers in the first
> place? Why require jumping through extra hoops?
It is impossible to hook the copying of pointers. And in this
case, in order to prevent undue aliasing, we *must prohibit*
copying of input ranges (which pointers to ranges are, even if
the range itself is a forward range).
The answer, as you said, is to make a generic `byRef` range
wrapper which is non-copyable (and hence, a proper input range).
The point is to remove the requirement for `save` and use the
copyability to determine if a range is a forward range. This
makes sense, since most people forget to call `save` anyway, and
just count on copying being the same thing. We should just hook
the thing that people use.
>> 11. Finite random-access ranges are required to implement
>> opDollar, and their opIndex must work with $. Similarly, any
>> ranges which implement slicing must implement opDollar, and
>> slicing must work with $.
>>
>> In most cases, this will just be an alias to length, but
>> barring a language change that automatically treats length as
>> opDollar (which has been discussed before but has never
>> materialized and is somewhat controversial given types where
>> it wouldn't make sense to treat length as opDollar), we have
>> to require that opDollar be defined, or generic code won't be
>> able to use $ with indexing or slicing. We probably would have
>> required it years ago except that it would have broken code to
>> add the requirement.
> [...]
>
> Will this also require implementing arithmetic operators on the
> return
> type of opDollar? Otherwise things like r[0 .. $-1] still
> wouldn't
> work correctly. Or r[0 .. complicatedMathFunc(($-1)/2)].
It appears that the intention in current range code (in
`hasSlicing` at least) is that `$` must be `size_t`. But I'm not
sure.
But if that is the intention, obviously size_t has well-defined
behavior.
-Steve
More information about the Digitalmars-d
mailing list