Rust Closures con Restricciones Genéricas

RustRustBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, se explica que las closures en Rust utilizan la anonimidad de tipos, lo que requiere el uso de genéricos cuando se usan closures como parámetros de función.

Nota: Si el laboratorio no especifica un nombre de archivo, puede usar cualquier nombre de archivo que desee. Por ejemplo, puede usar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99325{{"Rust Closures con Restricciones Genéricas"}} rust/function_syntax -.-> lab-99325{{"Rust Closures con Restricciones Genéricas"}} rust/expressions_statements -.-> lab-99325{{"Rust Closures con Restricciones Genéricas"}} rust/operator_overloading -.-> lab-99325{{"Rust Closures con Restricciones Genéricas"}} end

Anonimidad de tipos

Las closures capturan de manera concisa variables de los ámbitos envolventes. ¿Esto tiene alguna consecuencia? Seguro que sí. Observe cómo el uso de una closure como parámetro de función requiere [genéricos], lo cual es necesario debido a cómo se definen:

// `F` debe ser genérico.
fn apply<F>(f: F) where
    F: FnOnce() {
    f();
}

Cuando se define una closure, el compilador crea implícitamente una nueva estructura anónima para almacenar las variables capturadas dentro, mientras implementa la funcionalidad a través de uno de los traits: Fn, FnMut o FnOnce para este tipo desconocido. Este tipo se asigna a la variable que se almacena hasta la llamada.

Dado que este nuevo tipo es de tipo desconocido, cualquier uso en una función requerirá genéricos. Sin embargo, un parámetro de tipo sin límite <T> todavía sería ambiguo y no se permitiría. Por lo tanto, limitar por uno de los traits: Fn, FnMut o FnOnce (que implementa) es suficiente para especificar su tipo.

// `F` debe implementar `Fn` para una closure que no
// toma entradas y no devuelve nada - exactamente lo que se
// requiere para `print`.
fn apply<F>(f: F) where
    F: Fn() {
    f();
}

fn main() {
    let x = 7;

    // Captura `x` en un tipo anónimo e implementa
    // `Fn` para él. Guárdalo en `print`.
    let print = || println!("{}", x);

    apply(print);
}

Resumen

¡Felicitaciones! Has completado el laboratorio de Anonimidad de Tipos. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.