Tuplas y unidad

Move no es totalmente compatible con tuplas, como cabría esperar si provienen de otro idioma y las tienen como valor de primera clase . Sin embargo, para admitir múltiples valores de retorno, Move tiene expresiones tipo tupla. Estas expresiones no dan como resultado un valor concreto en tiempo de ejecución (no hay tuplas en el código de bytes) y, como resultado, son muy limitadas: sólo pueden aparecer en expresiones (normalmente en la posición de retorno de una función); no pueden vincularse a variables locales; no se pueden almacenar en estructuras; y los tipos de tupla no se pueden utilizar para crear instancias de genéricos.

De manera similar, la unidad() es un tipo creado por el lenguaje fuente de Move para estar basado en expresiones. El valor unitario ()no da como resultado ningún valor de tiempo de ejecución. Podemos considerar que la unidad ()es una tupla vacía y cualquier restricción que se aplique a las tuplas también se aplica a la unidad.

Puede parecer extraño tener tuplas en el idioma dadas estas restricciones. Pero uno de los casos de uso más comunes de tuplas en otros lenguajes es que las funciones permitan que las funciones devuelvan múltiples valores. Algunos lenguajes solucionan esto obligando a los usuarios a escribir estructuras que contengan múltiples valores de retorno. Sin embargo, en Move, no puedes poner referencias dentro de estructuras. Esto requería que Move admitiera múltiples valores de retorno. Todos estos múltiples valores de retorno se insertan en la pila en el nivel de código de bytes. En el nivel de origen, estos múltiples valores de retorno se representan mediante tuplas.

Literales

Las tuplas se crean mediante una lista de expresiones separadas por comas dentro de paréntesis.

Sintaxis

Tipo

Descripción

()

(): ()

Unidad, la tupla vacía o la tupla de aridad 0

(e1, ..., en)

(e1, ..., en): (T1, ..., Tn)donde e_i: Tist 0 < i <= nyn > 0

Una ntupla, una tupla de arity n, una tupla con nelementos

Tenga en cuenta que (e)no tiene tipo (e): (t), es decir, no hay una tupla con un elemento. Si solo hay un elemento dentro del paréntesis, los paréntesis solo se usan para desambiguación y no tienen ningún otro significado especial.

A veces, las tuplas con dos elementos se denominan "pares" y las tuplas con tres elementos se denominan "triples".

Ejemplos

Copiar

address 0x42 {
module example {
    // all 3 of these functions are equivalent

    // when no return type is provided, it is assumed to be `()`
    fun returns_unit_1() { }

    // there is an implicit () value in empty expression blocks
    fun returns_unit_2(): () { }

    // explicit version of `returns_unit_1` and `returns_unit_2`
    fun returns_unit_3(): () { () }


    fun returns_3_values(): (u64, bool, address) {
        (0, false, @0x42)
    }
    fun returns_4_values(x: &u64): (&u64, u8, u128, vector<u8>) {
        (x, 0, 1, b"foobar")
    }
}
}

Operaciones

La única operación que se puede realizar actualmente con tuplas es la desestructuración.

Desestructurando

Para tuplas de cualquier tamaño, se pueden desestructurar en un letenlace o en una asignación.

Por ejemplo:

Copiar

address 0x42 {
module example {
    // all 3 of these functions are equivalent
    fun returns_unit() {}
    fun returns_2_values(): (bool, bool) { (true, false) }
    fun returns_4_values(x: &u64): (&u64, u8, u128, vector<u8>) { (x, 0, 1, b"foobar") }

    fun examples(cond: bool) {
        let () = ();
        let (x, y): (u8, u64) = (0, 1);
        let (a, b, c, d) = (@0x0, 0, false, b"");

        () = ();
        (x, y) = if (cond) (1, 2) else (3, 4);
        (a, b, c, d) = (@0x1, 1, true, b"1");
    }

    fun examples_with_function_calls() {
        let () = returns_unit();
        let (x, y): (bool, bool) = returns_2_values();
        let (a, b, c, d) = returns_4_values(&0);

        () = returns_unit();
        (x, y) = returns_2_values();
        (a, b, c, d) = returns_4_values(&1);
    }
}
}

Para obtener más detalles, consulte Mover variables.

Subtipificación

Junto con las referencias, las tuplas son los únicos tipos que tienen subtipos en Move. Las tuplas tienen subtipos sólo en el sentido de que subtipos con referencias (de forma covariante).

Por ejemplo:

Copiar

let x: &u64 = &0;
let y: &mut u64 = &mut 1;

// (&u64, &mut u64) is a subtype of (&u64, &u64)
// since &mut u64 is a subtype of &u64
let (a, b): (&u64, &u64) = (x, y);

// (&mut u64, &mut u64) is a subtype of (&u64, &u64)
// since &mut u64 is a subtype of &u64
let (c, d): (&u64, &u64) = (y, y);

// error! (&u64, &mut u64) is NOT a subtype of (&mut u64, &mut u64)
// since &u64 is NOT a subtype of &mut u64
let (e, f): (&mut u64, &mut u64) = (x, y);

Propiedad

Como se mencionó anteriormente, los valores de tupla realmente no existen en tiempo de ejecución. Y actualmente no se pueden almacenar en variables locales debido a esto (pero es probable que esta característica esté disponible pronto). Como tal, las tuplas sólo se pueden mover actualmente, ya que copiarlas requeriría colocarlas primero en una variable local.

Last updated