#How to filter Tuple fields based on type?

1 messages · Page 1 of 1 (latest)

polar rain
#

I have an anytype tuple and I would like to keep all fields except non-const pointers and pass that to another function.

I'm working on a solution that builds an array of types, then filters that, then creates a tuple type and then puts the values back in. Suffice to say it's a major PITA and I'd like to know, is there a simpler solution I'm missing?

fresh swan
#

You could probably do something with @typeInfo() or std.builtin.fields()

Create an array of StructFields
Index thru every field in your input tuple, only add the ones you want to the array. And then use @Type() to convert it back into a struct

#

There might be some way to append values to tuples at comptime, which may make this easier

#

I'm not sure

fresh swan
#

Actually, heres another idea

#

Then when you instantiate the new tuple, just have it use the default values

polar rain
fresh swan
#
const my_tuple = .{1, 2, 3, "a", "b", "c"};
const info = @typeInfo(@TypeOf(my_tuple)).Struct;
const len = info.fields.len;

const bad_type = u32;

var new_fields: [len]std.builtin.Type.StructField = undefined;
var num_new_fields: u32 = 0;
for(info.fields) |val| {
   if(fields.type != bad_type) {
       new_fields[num_new_fields] = val;
   }
}
#

ah

#

I don't think there is gonna be any real elegant solution to this other than what you were trying before then

polar rain
fresh swan
#

could you just do something like making every type in the original tuple optional

#

and then set the values you don't want to null

green dove
# polar rain Yeah, no, that wouldn't work

very messy but it works:

fn filter(tuple: anytype) void {
    const a_b_types = comptime blk: {
        var non_const_ptr_types: []const type = &.{};
        var other_field_types: []const type = &.{};

        for (std.meta.fields(@TypeOf(tuple))) |field| {
            if (std.meta.trait.isSingleItemPtr(field.type) and !std.meta.trait.isConstPtr(field.type)) {
                non_const_ptr_types = non_const_ptr_types ++ .{field.type};
            } else {
                other_field_types = other_field_types ++ .{field.type};
            }
        }

        break :blk .{ non_const_ptr_types, other_field_types };
    };

    var non_const_ptrs: std.meta.Tuple(a_b_types[0]) = undefined;
    comptime var non_const_ptrs_i: usize = 0;

    var other_fields: std.meta.Tuple(a_b_types[1]) = undefined;
    comptime var other_fields_i: usize = 0;

    inline for (tuple) |t| {
        const T = @TypeOf(t);

        if (comptime std.meta.trait.isSingleItemPtr(T) and !std.meta.trait.isConstPtr(T)) {
            non_const_ptrs[non_const_ptrs_i] = t;
            non_const_ptrs_i += 1;
        } else {
            other_fields[other_fields_i] = t;
            other_fields_i += 1;
        }
    }

    std.debug.print("{any}\n", .{non_const_ptrs});
    std.debug.print("{any}\n", .{other_fields});
}
#
pub fn main() !void {
    var x: i32 = 0;
    var y: f32 = 0;

    var my_tuple = .{ false, &x, true, @as(i32, 10), &y };
    filter(my_tuple);
}

output:

$ zig build run
{ i32@7a107ff908, f32@7a107ff90c }
{ false, true, 10 }
polar rain
green dove
polar rain
green dove
polar rain
polar rain
#

didnt realise you can []index a tuple

#

or I could've fucked uo the filtering function and acciddntaly used something different each time

green dove
polar rain
#

mind you it's slicing on comptime indicies