Today's questions are mainly syntax but also semantics.
Ranges
A ranged for loop looks like this:
1 2 3 4 5 6 7 8 9 10 11 | for val in start..<end { // Half-Closed Range } // Similar to for val := start; val < end; val++ { } for val in start...end { // Open Range } // Similar to for val := start; val <= end; val++ { } |
These are very useful constructs however, I have very little need for the "open range" and the explicit c-style for loop may be clearer.
My question for this part is, should I allow both (like Swift) or just have the "half-closed range" (like Rust)?
If the only range is half-closed, maybe the operator should just be a double dot `..` (and that would also act as the "ellipsis"), or a colon `:` for ranges (like slice operations currently) (see the Cobra language).
Slicing Operations
Currently, if you want to slice something, the syntax is similar to Go, Python, Cobra, etc:
1 2 3 4 | thing[a:b] // a ..< b thing[a:] // a ..< thing.count thing[:b] // 0 ..< b thing[:] // 0 ..< thing.count |
This means that all slice operations are half-closed which is syntactically inconsistency with for ranges. If I allow both range types, the syntax may look a little weird to get the same results.
1 2 3 4 5 6 7 8 9 | thing[a..<b] // a ..< b thing[a..<] // a ..< thing.count thing[..<b] // 0 ..< b thing[..<] // 0 ..< thing.count thing[a...b] // a ... b thing[a...] // a ... thing.count-1 thing[...b] // 0 ... b thing[...] // 0 ... thing.count-1 |
Using the `..` range proposed in the previous section, would make it look a bit nicer:
1 2 3 4 | thing[a..b] // a ..< b thing[a..] // a ..< thing.count thing[..b] // 0 ..< b thing[..] // 0 ..< thing.count |
My question for this part is (dependent on the previous section), what should the slicing syntax be?
Slice Internals
The colon syntax was originally used as slices stored a capacity as well as a count (e.g. `a[low:high:max]`) which meant that slices could be used as a buffer-like type. This was removed when dynamic arrays but this may not be the designed result. I'm starting to think that allowing a slice to have a capacity would be a better ideas as it would follow a "pattern":
1 2 3 4 5 6 | Pointer - data (Fixed) Array - data + count* Slice - data + count + capacity Dynamic Array - data + count + capacity + allocator * count is implicit as it's not stored due to array counts being known at compile time. |
And finally the questions for this part: are buffer-like slices are a better construct to have? And what would the slicing syntax be to allow for an optional capacity "field"?