Payload Captures

Las capturas de carga utilizan la sintaxis |valor| y aparecen en muchos lugares, algunos de los cuales ya hemos visto. Dondequiera que aparezcan, se utilizan para “capturar” el valor de algo.

Con las declaraciones if y los optionals.

test "optional-if" {
    const maybe_num: ?usize = 10;
    if (maybe_num) |n| {
        try expect(@TypeOf(n) == usize);
        try expect(n == 10);
    } else {
        unreachable;
    }
}

Con las declaraciones if y las uniones de errores. El else con la captura de error es requerido aquí.

test "error union if" {
    const ent_num: error{UnknownEntity}!u32 = 5;
    if (ent_num) |entity| {
        try expect(@TypeOf(entity) == u32);
        try expect(entity == 5);
    } else |err| {
        _ = err catch {};
        unreachable;
    }
}

Con los bucles while y los optionals. Esto puede tener un bloque else.

test "while optional" {
    var i: ?u32 = 10;
    while (i) |num| : (i.? -= 1) {
        try expect(@TypeOf(num) == u32);
        if (num == 1) {
            i = null;
            break;
        }
    }
    try expect(i == null);
}

Con los bucles while y las uniones de errores. El else con la captura de error es requerido aquí.

const expect = @import("std").testing.expect;

var numbers_left2: u32 = undefined;

fn eventuallyErrorSequence() !u32 {
    return if (numbers_left2 == 0) error.ReachedZero else blk: {
        numbers_left2 -= 1;
        break :blk numbers_left2;
    };
}

test "while error union capture" {
    var sum: u32 = 0;
    numbers_left2 = 3;
    while (eventuallyErrorSequence()) |value| {
        sum += value;
    } else |err| {
        try expect(err == error.ReachedZero);
    }
}

Para loops.

test "for capture" {
    const x = [_]i8{ 1, 5, 120, -5 };
    for (x) |v| try expect(@TypeOf(v) == i8);
}

Casos de switch en uniones etiquetadas.

const expect = @import("std").testing.expect;

const Info = union(enum) {
    a: u32,
    b: []const u8,
    c,
    d: u32,
};

test "switch capture" {
    const b = Info{ .a = 10 };
    const x = switch (b) {
        .b => |str| blk: {
            try expect(@TypeOf(str) == []const u8);
            break :blk 1;
        },
        .c => 2,
        // Si estos son del mismo tipo, 
        //pueden estar dentro del mismo grupo de captura.
        .a, .d => |num| blk: {
            try expect(@TypeOf(num) == u32);
            break :blk num * 2;
        },
    };
    try expect(x == 20);
}

Como vimos en las secciones de Union y Optional anteriormente, los valores capturados con la sintaxis |val| son inmutables (similar a los argumentos de función), pero podemos usar la captura de puntero para modificar los valores originales. Esto captura los valores como punteros que aún son inmutables, pero debido a que el valor es ahora un puntero, podemos modificar el valor original desreferenciándolo:

Edita esta pagina Última actualización: 5/15/2024 por Vital