# List slicing inconsistency

**URL:** <https://forum.modular.com/t/list-slicing-inconsistency/2737>\
**Category:** Standard Library\
**Created:** [February 16, 2026, 3:38pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737 "2026-02-16T15:38:13Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 16, 2026, 3:38pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/1 "2026-02-16T15:38:13Z")

</div>

At the moment it‘s quite surprising for users that `lst[0:4]` returns a `Span` (without copying values) and `lst[0:4:2]` returns a new `List` (with copied values) which leads to different semantics.

How about adding a `NonContiguousSpan` to the stdlib? It would store the step size and a contiguous memory pointer into the original list. Its getter would then use the stored `step` size to access the non copied values in a non contiguous manner. This would greatly improve performance of non contiguous list slicing and align its semantics with contiguous list slicing.  
Or is this considered a corner case that isn’t worth implementing?

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [February 16, 2026, 5:01pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/2 "2026-02-16T17:01:34Z")

</div>

One thought I have about this, can we decouple `Layout` from `LayoutTensor` and use it more generally? I think that using `LayoutTrait` as a more general abstraction for an indexing scheme would help solve this issue, and could still enable better solutions to this issue. However, there would need to be some work to expose scatter/gather through a “LayoutSpan” and the ability to do some specialization for 1d indexing would help a lot.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 16, 2026, 7:18pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/3 "2026-02-16T19:18:45Z")

</div>

I like the idea of generalizing over indexing schemes. But isn‘t slicing a 1D list a much simpler thing than having a generalized `LayoutTrait` that has to be tweaked for this use case?

Or, to put it in other words: How about starting with a concrete `LayoutSpan` for list slicing and generalize afterwards?

This way the current inconsistency can be fixed in the short term and used as a starting point for further generalization.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 17, 2026, 9:42am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/4 "2026-02-17T09:42:53Z")

</div>

So, it’s “start:end:1” versus “start:end.”

The former has value semantics, while the latter has reference semantics.

You define these different semantics as an inconsistency.

There are multiple solutions to unify the semantics, such as changing stepped slicing to a lazy, iterator-like abstraction, or changing non-stepped slicing to have value semantics via either the always-copy or copy-on-write approaches.

However, it should be noted that the always-copy approach was abandoned for performance reasons because a systems programming language would find it too tempting to simply increment a pointer and decrement a length.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 17, 2026, 10:10am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/5 "2026-02-17T10:10:06Z")

</div>

I wonder if it’s truly worthwhile to dedicate resources to addressing this specific use case when the language has so many more compelling problems to tackle.

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [February 17, 2026, 4:04pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/6 "2026-02-17T16:04:41Z")

</div>

Indexing a 1d list is simpler than indexing an N-D thing, but since we can be generic over rank we should. Perhaps some conditional conformance to make things a bit nicer for 1d is in order, but I think a unified abstraction is valuable here. We would need some kind of `LayoutSpan`/`View` type to hold this.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 18, 2026, 6:25am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/7 "2026-02-18T06:25:33Z")

</div>

Shall I try implementing a PoC for this?

@owenhilyard : Do you have input on how to start such a PoC?

The Idea would be to start with a struct that is generalizable but can be used in the concrete case of List slicing. One could start based on the current `Span` implementation or start from scratch with a `LayoutView`. The easiest way I think this could be implemented is having a pointer to the original list and using the slice info (start, end, step) for getter/setter logic.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 18, 2026, 6:44am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/8 "2026-02-18T06:44:41Z")

</div>

> [@leb-kuchen](#):
>
> However, it should be noted that the always-copy approach was abandoned for performance reasons because a systems programming language would find it too tempting to simply increment a pointer and decrement a length.

The idea would be to always have reference logic for performance reasons. So slicing `lst[:4:2]` would have the same reference semantic and performance characteristics as `lst[:4]`.

BTW: @Serotonin pointed out on [Discord](https://discord.com/channels/1087530497313357884/1151418092052815884/1473001637214945281) that numpy `np.array` has reference semantic for both, contiguous and non-contiguous slicing.

---

<div class="post-metadata">

**Author:** ![leb-kuchen](https://avatars.discourse-cdn.com/v4/letter/l/a183cd/32.png) [@leb-kuchen](https://forum.modular.com/u/leb-kuchen)\
**Post date:** [February 18, 2026, 8:59am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/9 "2026-02-18T08:59:09Z")

</div>

> [@christoph\_schlumpf](#):
>
> The Idea would be to start with a struct that is generalizable but can be used in the concrete case of List slicing.

You essentially propose this(in simplied mojo sudo code):

```mojo
struct NonContiguousSpan[T]:
    var span: Span[T]
    var step: Int
    fn __getitem__ (self, idx: Int) -> T:
        return self.span[self.step * idx]
    fn __iter__ (self) yields T:
        for i in range(0, len(span), self.step):
            yield self.span[i]

```

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 18, 2026, 3:16pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/10 "2026-02-18T15:16:50Z")

</div>

Yes, exactly, something in this direction was my first thought, but I think @owenhilyard has something more generic in mind.

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [February 18, 2026, 7:14pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/11 "2026-02-18T19:14:11Z")

</div>

Step 1 would be to make span that uses `LayoutTrait`. Once you have that, then most things should sort-of just work.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 21, 2026, 8:50am UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/12 "2026-02-21T08:50:15Z")

</div>

What is the stance of the Modular/Stdlib team on this?

- it’s no inconsistency but intentional
- not worth fixing this inconsistency before Mojo 1.0
- Fix it with a concrete non-contiguous `Span`
- Fix it by implementing `LayoutTrait`
- …

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [February 21, 2026, 4:10pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/13 "2026-02-21T16:10:44Z")

</div>

See [Can we sort elements in descending order in mojo?](https://forum.modular.com/t/can-we-sort-elements-in-descending-order-in-mojo/2757) for an example using slicing with negative step size where the expectation might have been that the slicing was non copying.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [March 3, 2026, 8:02pm UTC](https://forum.modular.com/t/list-slicing-inconsistency/2737/14 "2026-03-03T20:02:29Z")

</div>

`LayoutTrait` has been removed from Mojo.

> <https://github.com/modular/modular/commit/bee88c2eabca2de95d9b3e0763268fa6c3dab2d0>
>
> Remove \`LayoutTrait\` which was only used by three types in the layout
> module (\`L…ayout\`, \`Swizzle\`, \`ComposedLayout\`) and provided no real
> polymorphic value. \`ComposedLayout\` was the only consumer of the generic
> constraint, but was only ever instantiated with concrete type
> combinations \`\[Layout, Layout\]\` and \`\[Layout, Swizzle\]\`.
> 
> \- Delete \`LayoutTrait\` from \`layout.mojo\`
> \- Remove \`LayoutTrait\` conformance from \`Layout\` and \`Swizzle\`
> \- De-genericize \`ComposedLayout\` to use concrete \`Layout\` + \`Swizzle\`
> types, which is all it was ever instantiated with
> \- Update test to use \`composition()\` for the \`Layout\`-\`Layout\` case
> 
> MODULAR\_ORIG\_COMMIT\_REV\_ID: 10daf6aa7e251045f06622cdd314cb1380104a09

Now we have one less option.

What is the stance of the Modular/Stdlib team on this?

- it’s no inconsistency but intentional
- not worth fixing this inconsistency before Mojo 1.0
- Fix it with a non-contiguous `Span`
- …
