zig icon indicating copy to clipboard operation
zig copied to clipboard

Allow slicing of tuples

Open alexnask opened this issue 5 years ago • 5 comments
trafficstars

This, along with the multiplication and concatenation operators would make it much easier to write code that manipulates tuples.

alexnask avatar Mar 04 '20 10:03 alexnask

Interesting. So the start and end indexes would both have to be comptime known, and it would produce a new tuple type as a result. Sort of the "tuple version" of #863.

andrewrk avatar Mar 07 '20 17:03 andrewrk

Since tuples can contain heterogeneously typed fields, it does seem natural for slicing such a tuple to yield another tuple. This is consistent with the fact that concatenating and multiplying tuples always yields a tuple even when the fields of the tuple operands are typed homogeneously.

However, this would mean special-casing the behavior of slicing, which today always yields a value of either type *[N]T (for compile time-known indices) or []T (for run time-known indices).

Would users be astonished if tuples comprising homogeneously typed fields did not slice the same way that any other currently sliceable type slices, given that such tuples are already permitted to coerce to arrays?

Aside: Would this proposal also allow for the slicing of tuple pointers?

ok-ryoko avatar Apr 03 '24 21:04 ok-ryoko

For what it's worth, I have a use case that would benefit a lot from this.

To make it short, my project defines a computation graph at compile time - each node of the graph has a eval(Input) Output method, where Input and Output are tuples. Then I have special nodes to combine other nodes in various ways. For those, I have to mangle tuples quite extensively, in order to route the right inputs to the right node - so mostly merging and splitting.

It is doable with a few helper functions, but beeing able to use the slicing syntax on tuples would clarify the code a lot.

For reference here are my helper functions

// extracting a list of field types from a tuple. essentially the inverse of std.meta.Tuple
fn fieldTypes(T: type) [std.meta.fields(T).len]type {
    const fields = std.meta.fields(T);
    var types: [fields.len]type = undefined;
    for (fields, 0..) |*f, i| {
        types[i] = f.*.type;
    }
    return types;
}

// return type of the split function
fn Split(T: type, comptime pivot: usize) type {
    // TODO check A is tuple
    const types = fieldTypes(T);
    return struct {
        Tuple(types[0..pivot]),
        Tuple(types[pivot..]),
    };
}

// split a tuple at pivot
fn split(tuple: anytype, comptime pivot: usize) Split(@TypeOf(tuple), pivot) {
    var result: Split(@TypeOf(tuple), pivot) = undefined;
    inline for (tuple, 0..) |value, i| {
        if (i < pivot) {
            result[0][i] = value;
        } else {
            result[1][i - pivot] = value;
        }
    }
    return result;
}

tgirod avatar May 08 '24 21:05 tgirod

Also, would it make sense to do the same to manipulate tuple types?

const T = struct{ f32, bool, u8};
T[0]; // f32
T[1]; // bool
T[0..2]; // struct{f32, bool};

But maybe that would count as another proposal...

tgirod avatar May 16 '24 16:05 tgirod

Also, would it make sense to do the same to manipulate tuple types?

TFW tuple types are tuples themselves. Massive inception gigabrain moment... :laughing: Maybe this comes for free.

Inve1951 avatar May 20 '24 06:05 Inve1951

Slicing has typically meant getting a reference to the original memory of the thing being sliced. If the proposal merely wants functionality to copy portions of a tuple, then I doubt slicing would be the correct syntax or nomenclature for it. In that case, helper functions in the standard library would suffice.

theantagonist9509 avatar Jun 22 '24 04:06 theantagonist9509