#tuple element types

1 messages · Page 1 of 1 (latest)

sleek sand
#

What's a good way to test whether an element in a tuple has the type []u8? For example:

const tuple = .{ true, 19, 3.14, 'A', "hello" };
inline for (tuple) |value| {
    // Determine if value is a string and
    // do something different for strings vs. non-strings.
}
hot bronze
#

i think std.meta.trait.isZigString(@TypeOf(value)) will work

#

but in this case, "hello" is not a []const u8, but a *const [5:0]u8 which will coerce to a []const u8

sleek sand
#

That seems like exactly what I want, but for some reason I can't print the string value when I find it. Here's what I have:

const std = @import("std");
const print = std.debug.print;
const trait = std.meta.trait;

test "tuple" {
    const tuple = .{ true, @as(u8, 19), @as(f32, 3.14), 'A', "hello" };

    inline for (tuple) |value| {
        const T = @TypeOf(value);
        if (trait.isZigString(T)) {
            print("value = {s}\n", .{value});
        } else {
            print("value = {any}\n", .{value});
        }
    }
}
#

If I comment out the print for strings, it works for all the other types using the second print.

#

With the first print uncommented, it seems to try to use that for all the values and I get error messages like "invalid format string 's' for type 'bool'". Maybe there's something weird going on because the loop is inline.

swift wind
#

try putting comptime before the trait.isZigString

sleek sand
#

That fixed it! Why do I need that? Can the trait methods only be used at compile-time?

swift wind
#

youre forcing the condition to be known at comptime, so therefore one of the branches wont get analyzed. when both branches get analyzed thats when you get the error because the types dont match up

sleek sand
#

It's not yet clear to me which parts of this code are being run at compile-time. It seems like if the value passed to isZigString must be known at compile-time then the assignment to tuple must also happen at compile-time. Is that true? I guess due to the inline, there is no loop to execute. Is all the code that is generated for the inline for also run at compile-time?

swift wind
#

the value isnt being passed to isZigString, it’s type is, which is known at compile time. all types have to be. not all the code in an inline for is run at compile time, its just copy-pasting the code for each loop to its own block, which is necessary for looping over some data types.

hot bronze
#

i agree that it can be difficult to tell what is happening at comptime vs runtime. maybe that article will help clear it up a bit.

sleek sand
#

@swift wind Would you say that the assignment to the variable tuple is performed at compile-time? It seems it would have to be in order to know the type of each element in the tuple so the unrolled loop can know those for passing to isZigString.

#

@Travis Interesting that you mentioned that article. I already had a printed copy sitting on my desk one foot away from me. 😉

swift wind
sleek sand
#

Ah, I hadn't considered that the compiler could just determine the types without necessarily performing the assignment. Thanks for explaining that!