#Compare slices of tagged unions

1 messages · Page 1 of 1 (latest)

viscid stratus
#

Is there a easy way to compare slices of tagged unions?

const diff = std.mem.indexOfDiff(Token, tokens, &com_tokens);

gives me back

C:\Users\PC\scoop\persist\zvm\data\master\lib\std\mem.zig:715:58: error: operator != not allowed for type 'root.Token'
    while (index < shortest) : (index += 1) if (a[index] != b[index]) return index;
                                                ~~~~~~~~~^~~~~~~~~~~

Where Token is a tagged union

quartz widget
#

do you want to search by token tag?

#

if so maybe something like this

std.mem.indexOfDiff(@typeInfo(Token).Union.tag_type.?, ...);
viscid stratus
#

I need to compare the tag and the value for each item in the tagged union slices to find where they first differ

quartz widget
#

ok then i think you would need to write your own helper for that.

viscid stratus
#

What I'm trying to do is use a switch to compare the values of a slice, and since it's not telling me they are equal, I was trying to figure out why, even though the values of the switch and the slice certainly are the same

const com_tokens = [_]Token{
        Token{ .addition = 5 },
        Token{ .l_array = 6 },
        Token{ .addition = -1 },
        Token{ .shifting = 4 },
        Token{ .addition = 1 },
        Token{ .shifting = -4 },
        Token{ .r_array = 1 },
    };
    const compare: *const []Token = @ptrCast(&com_tokens);
switch (&tokens) {
        compare => { // compare and tokens have the same value
            try std.testing.expect(true);
        },
        else => {
            // But this is what gets hit
            try std.testing.expect(false);
        },
    }
quartz widget
#

i don't think that switch is doing what you expect. switch on a pointer value compares the value of the pointers, not the values pointed to.

viscid stratus
#

Yes, I came to that same conclusion. I guess I just can't do that
I wanted to do the same like Rust

match instructions.as_slice() {
    // ...
    &[.., JumpRight(_), Add(255), Move(x), Add(1), Move(y)]
        if x == -y =>
    {
        let len = instructions.len();
        instructions.drain(len - 5..);
        Instruction::AddTo(x)
    }
    _ => Instruction::JumpLeft(pair_address),
}
quartz widget
#

you might write that search like this:

    const index: ?usize = for(tokens, com_tokens, 0..) |t, ct, i| {
        if(!t.eql(ct)) break i;
    } else null;
#

one way you could achieve something similar would be to encode the tag and value as an integer. that would allow you to compare them w/ std.mem.eql() atleast.

#

this is what i mean by encoding a Token as an integer:

const Token = union(enum) {
    fn toInt(t: Token) usize {
        return @as(usize, @intFromEnum(@as(std.meta.Tag(Token), t)) << 32) |
            switch (t) {
            .jump_right => 0,
            .add => |x| x,
            // ...
        };
    }
};
#

and with that you should be able to use mem.startsWith() to achive something similar:

    if (std.mem.startsWith(usize, token_ints, &.{
        (Token{ .jump_right = {} }).toInt(),
        (Token{ .add = 255 }).toInt(),
        // ...
    })) {
        // ...
    }
#

and for that you'd need to encode tokens into a token_ints slice. so maybe this isn't a great approach. i think my first ideas was better. 🙃

viscid stratus
#

Dw, I did it in the C way, ty