This language is starting to take shape very fast and the "base language" looks like it will be done sooner than later.
Today's questions are mainly syntax but also semantics.
Ranges
A ranged for loop looks like this:
| 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:
| 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.
| 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:
| 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":
| 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"?