#array to array of optional

1 messages · Page 1 of 1 (latest)

vague zephyr
#

If I have an array of things, what is the idiomatic/easiest way to turn it into an array of optionals?

const std = @import("std");

test "optional_arrays" {
    const arr = [_]i8{ 0, 3, 4};
    var arr_maybies:[3]?i8 = .{ null, null, null };
    // ? this doesn't work
    std.mem.copyForwards(?i8, &arr_maybies, &arr);
     
    try std.testing.expectEqual(arr_maybies[1].?, arr[1]);
}
fading granite
#

the copy function doesn't work because the optional integer has a different memory layout than the non-optional one

#

i'd use a loop over both arrays, like

for (&arr_maybes, arr) |*dst, src| {
    dst.* = src;
}
short rapids
#

if you need to use this often, create a helper function:

fn toOptional(arr: anytype) ToOptional(@TypeOf(arr)) {
    var res: ToOptional(@TypeOf(arr)) = undefined;
    for (arr, &res) |a, *r| {
        r.* = a;
    }
    return res;
}

fn ToOptional(comptime T: type) type {
    const info = @typeInfo(T);
    const i = switch (info) {
        .Array => |i| i,
        else => @compileError("Expected Array type, found: " ++ @typeName(T)),
    };

    return @Type(std.builtin.Type{
        .Array = .{
            .len = i.len,
            .child = ?i.child,
            .sentinel = null, // can't bother :P
        },
    });
}
#

there is a proposal to allow coercion of child types within ?T and E!T - which I think should be expanded to arrays, too

if the proposal is accepted, with the addition, type coercion would make simple assignment work

fading granite
#

that already happens with vectors and it can lead to pretty funny codegen