<p><strong>Q</strong> what are the advantages and disadvantages of slicing an array using offset+length and start/end offsets?</p>
<p><strong>My Observations</strong></p>
<ol>
<li><p>Adoption: Both are used in some languages and libraries. JavaScript had both, but the offset+len version is dis-recommended according to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr" rel="noreferrer">MDN</a>.</p>
</li>
<li><p>Merit: start-end offset can avoid some error that offset+len doesn't. For example, when an end is before a start, it is obvious some error exist; however, since len is often unsigned offset+len cannot catch some of the errors that start-end can catch.</p>
</li>
<li><p>Edge cases: some languages and/or data types treat negative values as offsets from the end. If a code blindly trust values passed from outside, this may result in instability or vulnerability.</p>
</li>
</ol>
<p><strong>So</strong>: what are the considerations of when using one or another?</p>

<arrays>
Offset+Length vs 2 Offsets
<p>For functionality, it doesn't matter. Even if you use unsigned integers, it's highly likely the programmer would use unchecked type conversions, bypassing the check. The programmer would most likely just blindly add or subtract the starting offset if the default implementation is not what they wanted. And I personally think returning an empty string for backward ranges is a better behavior than error in conversion, because it is such a small problem that nobody is going to process the error.</p>
<p>For usability, you may choose to support multiple options. But the start-end way as a base option is more compatible with other options, say counting from the end of the string. In the string-based language Tcl, you could use <code>end-n</code> to refer to a position from the end, which is more explicit and clear than languages just use negatives. We could extend this to support <code>start+n</code>. But it would be very awkward if the expected value is the length.</p>
<p>For uniformity, it's clear it couldn't be uniform and we'll need both variants somewhere. The start-end way could be used on iterators where the length isn't easily computable. as the case of C++. But counting n nodes from a point is also a frequently used operation. The former is more like a basic way referring to something, and the later is more like an actual operation. But it's unlikely you would distinguish the two this way at the language level in a newly designed language. So it doesn't really mean anything.</p>
<p>Offset+length could be clearer if the length is fixed, especially if you have a fixed length string type. But the <code>start+n</code> format is equally clear if your language supports it.</p>

CC BY-SA 4.0
2024-09-14T06:56:35.267Z
2024-09-14T06:56:35.267Z
user23013
<p>Given that <code>end = start + length</code>, it mostly doesn't matter: having 2 of the 3 means you can get the third with a simple addition or subtraction. In my answer, I'll use these notations for the two different representations: <code>[start, end)</code>; <code>&lt;start, length&gt;</code></p>
<p>Here are some considerations I could think of:</p>
<ul>
<li>Off by one: is <code>end = start + length</code> (pointing to one past the last element) or is it <code>end = start + length - 1</code> (pointing to the last element itself)? (I will be assuming the former in the rest of this answer.)</li>
<li>Are sequences with negative length valid?
<ul>
<li>If so, what does it represent? I could think of these options, there may be more potential sensible options:
<ul>
<li>A reversed slice: for example, something like <code>slice([1, 2, 3, 4, 5], &lt;2, -3&gt;)</code> would be <code>[3, 2, 1]</code></li>
<li>A &quot;normal&quot; slice, containing all the items of the reversed slice but in the original order: given <code>s1 &gt; s2</code>, <code>[s1, s2) == [s2 + 1, s1 + 1)</code>, or equivalently <code>&lt;s, len&gt; == &lt;s + len, -len&gt;</code>.</li>
<li>Like <code>String.prototype.substring</code>, <code>[s1, s2) == [s2, s1)</code>. While conceptually easy to understand, it does mean that <code>[s1, s2)</code> does now exclude index <code>s1</code> if <code>s1 &gt;= s2</code>. That may be unexpected, or you may not care, given that it is always excluded in the case that <code>s1 == s2</code>.</li>
<li>An empty slice</li>
</ul>
</li>
<li>If not, can this restriction be represented statically (if relevant)? As you mentioned <code>length</code> could be represented as an unsigned integer, but requiring that <code>end &gt;= start</code> may require special attention.
- If <code>length</code> is represented as an unsigned integer, how is integer overflow handled? <code>slice(x, &lt;0, prev_length - 1&gt;)</code> could have unexpected results if it silently wraps.
- In general, you need to decide how to handle invalid slices, even if represented as <code>[start, end)</code> with <code>end &lt; start</code>.</li>
</ul>
</li>
</ul>
<p>I don't think <code>String.prototype.substr</code> being deprecated should weigh too heavily for you. I don't see any technical reason for it, I think it was just a method being implemented by some couple of browsers and when they decided to tighten up the standard, it was just the one that happened to lose out for reasons other than its arguments.</p>

CC BY-SA 4.0
2024-09-14T08:18:26.317Z
2024-09-15T09:37:31.877Z
2024-09-15T09:37:31.877Z
Jasmijn
CC BY-SA 4.0
2024-09-16T16:16:25.210Z
Another option for slicing an array, with negative length or equivalente end less than start, is to wraparound. That is, more or less the complement of the reversed slice. No very useful, probably.
Pablo H
# Offset+Length vs 2 Offsets
Posted by: username_0 on 2024-09-14
**Q** what are the advantages and disadvantages of slicing an array using offset+length and start/end offsets?

**My Observations**

1. Adoption: Both are used in some languages and libraries. JavaScript had both, but the offset+len version is dis-recommended according to [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr).
2. Merit: start-end offset can avoid some error that offset+len doesn't. For example, when an end is before a start, it is obvious some error exist; however, since len is often unsigned offset+len cannot catch some of the errors that start-end can catch.
3. Edge cases: some languages and/or data types treat negative values as offsets from the end. If a code blindly trust values passed from outside, this may result in instability or vulnerability.

**So**: what are the considerations of when using one or another?
**Tags:** arrays
---
## 2 answers
### Answer by username_2 on 2024-09-14. Score: 7 | Accepted answer
Given that `end = start + length`, it mostly doesn't matter: having 2 of the 3 means you can get the third with a simple addition or subtraction. In my answer, I'll use these notations for the two different representations: `[start, end)`;

Here are some considerations I could think of:

* Off by one: is `end = start + length` (pointing to one past the last element) or is it `end = start + length - 1` (pointing to the last element itself)? (I will be assuming the former in the rest of this answer.)
* Are sequences with negative length valid?
  + If so, what does it represent? I could think of these options, there may be more potential sensible options:
    - A reversed slice: for example, something like `slice([1, 2, 3, 4, 5], <2, -3>)` would be `[3, 2, 1]`
    - A "normal" slice, containing all the items of the reversed slice but in the original order: given `s1 > s2`, `[s1, s2) == [s2 + 1, s1 + 1)`, or equivalently  `==` .
    - Like `String.prototype.substring`, `[s1, s2) == [s2, s1)`. While conceptually easy to understand, it does mean that `[s1, s2)` does now exclude index `s1` if `s1 >= s2`. That may be unexpected, or you may not care, given that it is always excluded in the case that `s1 == s2`.
    - An empty slice
  + If not, can this restriction be represented statically (if relevant)? As you mentioned `length` could be represented as an unsigned integer, but requiring that `end >= start` may require special attention.
    - If `length` is represented as an unsigned integer, how is integer overflow handled? `slice(x, <0, prev_length - 1>)` could have unexpected results if it silently wraps.
    - In general, you need to decide how to handle invalid slices, even if represented as `[start, end)` with `end < start`.

I don't think `String.prototype.substr` being deprecated should weigh too heavily for you. I don't see any technical reason for it, I think it was just a method being implemented by some couple of browsers and when they decided to tighten up the standard, it was just the one that happened to lose out for reasons other than its arguments.
> **Comments:**
> **username_3** (2024-09-16): Another option for slicing an array, with negative length or equivalente end less than start, is to wraparound. That is, more or less the complement of the reversed slice. No very useful, probably.  
---
### Answer by username_1 on 2024-09-14. Score: 2
For functionality, it doesn't matter. Even if you use unsigned integers, it's highly likely the programmer would use unchecked type conversions, bypassing the check. The programmer would most likely just blindly add or subtract the starting offset if the default implementation is not what they wanted. And I personally think returning an empty string for backward ranges is a better behavior than error in conversion, because it is such a small problem that nobody is going to process the error.

For usability, you may choose to support multiple options. But the start-end way as a base option is more compatible with other options, say counting from the end of the string. In the string-based language Tcl, you could use `end-n` to refer to a position from the end, which is more explicit and clear than languages just use negatives. We could extend this to support `start+n`. But it would be very awkward if the expected value is the length.

For uniformity, it's clear it couldn't be uniform and we'll need both variants somewhere. The start-end way could be used on iterators where the length isn't easily computable. as the case of C++. But counting n nodes from a point is also a frequently used operation. The former is more like a basic way referring to something, and the later is more like an actual operation. But it's unlikely you would distinguish the two this way at the language level in a newly designed language. So it doesn't really mean anything.

Offset+length could be clearer if the length is fixed, especially if you have a fixed length string type. But the `start+n` format is equally clear if your language supports it.
---
