#How to compare and get the active field of two tagged unions with the same tag

1 messages · Page 1 of 1 (latest)

stiff quiver
#
const TTag = enum {
  one,
  two,
};

const TStorage = union(TTag) {
  one: void,
  two: u8,
};

const T = union(TTag) {
  one: OneHandler,
  two: TwoHandler,
};

The code I'm using is similar to the one above. How would I go about checking whether the tags of the input param1: T, param2: TStorage are equal, and if so, get the active field (param1.one and param2.one if the tag is one, for example)? I could manually populate switches to solve this, but is there a solution to this much like inline else for a single tagged union?

last topaz
#

union types coerce to their tag value, so you can:

const tag1: TTag = TStorage{ ... };
const tag2: TTag = T{ ... };
const res = tag1 == tag2;
stiff quiver
#

Yeah the equality is the easier part, but how do I access param1.one and param2.one once I know they're equal?

west gate
#

i use std.meta.eql sometimes, but maybe ^ is better

#

probably not good in this case because i think it also compares the fields

last topaz
#

after you get the tag you can use @field(val, @tagName(tag)) to get the field

stiff quiver
#

I tried that, but the params are not comptime fields. @field() needs a comptime field name

last topaz
#

I guess you'll have to do some inline switch shenanigans to get the satellite data...

#

thing is, your question is kinda weird, since the satellite data's type might be different for each variant of the union

stiff quiver
#

The tags not being equal is illegal behavior and shouldn't happen. The data structure is like this because T is global, shared and immutable and TStorage is per entity, unique and mutable

stiff quiver
#

That's why I need the active fields exactly

last topaz
#

can you elaborate on what are the OneHandler and TwoHandler types?

#

I think I'm missing something

stiff quiver
#

Just structs with a few fields and a few functions. It would be calling something like param1.one.tick(param2.one); ideally

#

inline else would call param1.one.tick(param2.two); in an unreachable prong and throw a compile error

last topaz
#

if the structure of the execution is the same across all of the different prongs you could

switch (param1) {
    inline else => |param1_satellite| {
        param1_satellite.tick(@field(param2, @tagName(param1)));
    },
}
stiff quiver
#

No I can't, @field() only works for comptime field names like I've said above...

last topaz
#

actaully no, because param1 isn't comptime known inside of the inline else...

#

yeyeye sorry

#

my mistake

sinful horizon
#

inline else => |param1_satellite, param1_tag|

last topaz
#

ah here we go, didn't know you could do that

stiff quiver
#

Oh I didn't even know that existed. Does that guarantee equal tags?

last topaz
#

it'll fail on runtime if param2's active field isn't param1_tag

sinful horizon
#

i dont understand the question

sinful horizon
#

all what i said does is give you a comptime known tag, not related to whatever happens with it

stiff quiver
#

I misunderstood. Thought you could do an inline else over param1 and param2 at the same time, but this just seems to give you the active tag?

sinful horizon
#

yes

stiff quiver
#

I can't do anything with the tag, I can't access the field at the given tag unless it's comptime, which it isn't

sinful horizon
#

yes it is

#

thats the point

stiff quiver
#

Oh alright. I'll give it a try

last topaz
#

with an inline else the tag's value is comptime known, and the type of param1_satellite is generic - as long as the body of the inline else is type-checked correctly across all of the possible types of param1_satellite the code will compile

stiff quiver
#

Works now, thanks for the help

#

I can't seem to get the thread to close. Was it changed from ✅?

sinful horizon
#

twas not