Lanzamiento de Rust 1.35.0: implementaciones de rasgos funcionales y otras innovaciones

Les presento una traducción de la publicación sobre la nueva versión del lenguaje de programación favorito de todos, Rust .


Introduccion


El equipo del lenguaje de programación Rust se complace en anunciar una nueva versión, 1.35.0. Rust es un lenguaje de programación que permite a todos desarrollar software confiable y rápido.


Si instaló la versión anterior de Rust usando rustup , obtener la versión actual no será difícil:


 $ rustup update stable 

Si aún no tiene rustup , puede obtenerlo en la página correspondiente de nuestro sitio web. Una revisión detallada de esta versión está disponible en GitHub.


¿Qué se incluye en la versión estable?


Las principales innovaciones de esta versión incluyen la implementación de los rasgos FnOnce, FnMut y Fn en las Box<dyn FnOnce> , Box<dyn FnMut> y Box<dyn Fn> , respectivamente.


Además, las funciones en línea (cierres) se pueden convertir en punteros de función inseguros. Macro dbg! introducido en Rust 1.32.0 ahora se puede invocar sin especificar argumentos.


Además, esta versión introdujo muchas estabilizaciones de la biblioteca estándar. A continuación se presentan los más significativos, pero hay disponible un análisis detallado de algunos de ellos.


Rasgos Fn* implementados en el Box<dyn Fn*>


En Rust 1.35.0, los FnOnce , FnMut y Fn FnMut implementan en Box<dyn FnOnce> , Box<dyn FnMut> y Box<dyn Fn> respectivamente.


En el pasado, si deseaba llamar a una función encapsulada en Box<T> , tenía que usar FnBox , porque los objetos Box<dyn FnOnce> y similares no implementaban los rasgos Fn* correspondientes. También interfirió con la transferencia de funciones encapsuladas en el Box<T> al código que estaba esperando al implementador del rasgo Fn (se propuso crear funciones incorporadas temporales).


Esto fue causado por la incapacidad del compilador para detectar tales implementaciones. Este defecto se ha solucionado con la introducción de unsized_locals .


Sin embargo, ahora puede usar las funciones encapsuladas en Box<T> incluso en lugares que esperan que se implemente un rasgo funcional. Por ejemplo, el siguiente código se compila sin errores:


 fn foo(x: Box<dyn Fn(u8) -> u8>) -> Vec<u8> { vec![1, 2, 3, 4].into_iter().map(x).collect() } 

Box<dyn FnOnce> se pueden llamar sin Box<dyn FnOnce> alboroto:


 fn foo(x: Box<dyn FnOnce()>) { x() } 

Convertir a punteros inseguros


Desde los tiempos de Rust 1.19.0, ha sido posible convertir funciones integradas que no capturan el entorno en punteros de función. Por ejemplo, podrías escribir:


 fn twice(x: u8, f: fn(u8) -> u8) -> u8 { f(f(x)) } fn main() { assert_eq!(42, twice(0, |x| x + 21)); } 

Pero desafortunadamente, esta característica no se ha expandido a punteros de función inseguros. Esta versión introdujo los cambios descritos anteriormente:


 ///  ,   `unsafe fn`. unsafe fn call_unsafe_fn_ptr(f: unsafe fn()) { f() } fn main() { // :     //       //  unsafe { call_unsafe_fn_ptr(|| { dbg!(); }); } } 

Llame a dbg!() Sin argumentos


Debido a la abundancia de llamadas println! como depuradores de granjas colectivas, la macro dbg! se introdujo en Rust 1.32.0 dbg! . Recuerde que esta macro le permite capturar rápidamente el resultado de una determinada expresión con contexto:


 fn main() { let mut x = 0; if dbg!(x == 1) { x += 1; } dbg!(x); } 

Las líneas de código anteriores imprimirán en el terminal el resultado de la expresión x == 1 x respectivamente:


 [src/main.rs:4] x == 1 = false [src/main.rs:8] x = 0 

Como se mencionó en la sección anterior, donde se puede llamar a una función de orden superior call_unsafe_fn_ptr se debe llamar a dbg!() Sin especificar argumentos. Esto puede ser extremadamente útil para descubrir ramas de programas seleccionados:


 fn main() { let condition = true; if condition { dbg!(); // [src/main.rs:5] } } 

Estabilización de la biblioteca estándar.


En Rust 1.35.0, muchos componentes de la biblioteca estándar se han estabilizado. Además de esto, se han introducido algunas implementaciones, que puede leer aquí .


Copie el signo de un número de coma flotante a otro número


Con esta versión, copysign han agregado nuevos métodos de copysign a las primitivas de coma flotante (más específicamente, f32 y f32 ):



Como sugiere el nombre de los métodos, puede usarlos para copiar el signo de un número a otro:


 fn main() { assert_eq!(3.5_f32.copysign(-0.42), -3.5); } 

Comprobando si Range contiene un valor específico


Rust 1.35.0 adquirió un par de métodos nuevos en estructuras Range* :



Con estos métodos, puede verificar fácilmente si un cierto valor está en un rango. Por ejemplo, puedes escribir:


 fn main() { if (0..=10).contains(&5) { println!("5    [0; 10]."); } } 

Traducir (mapa) y dividir RefCell prestado


Con el advenimiento de Rust 1.35.0, puede traducir y dividir el valor de RefCell prestado en un conjunto de valores prestados en diferentes componentes de los datos prestados:



RefCell valor de RefCell través de la función en línea


Esta versión presenta el conveniente método replace_with declarado en la estructura RefCell :



Hash un puntero o enlace a


Esta versión presenta la función ptr::hash , que toma un puntero sin procesar para el hash. El uso de ptr::hash puede evitar el hash de un valor especificado o referenciado en lugar de la dirección en sí.


Option<&T> contenido de copia Option<&T>


Con el comienzo de Rust 1.0.0, los métodos Option::cloned en Option<&T> y Option<&mut T> permitieron clonar el contenido si estaba presente ( Some(_) ). Sin embargo, la clonación a veces puede ser una operación costosa, y los métodos opt.cloned() no describieron ninguna pista.


Este lanzamiento contribuyó:



La funcionalidad de opt.copied() es la misma que opt.cloned() . Sin embargo, el método descrito anteriormente solicita las condiciones T: Copy , cuyo fallo causará un error de compilación.


Cambios Clippy


Clippy, una herramienta que drop_bounds imperfecciones comunes para mejorar la calidad del código, ha adquirido drop_bounds . Funciona cuando la función generalizada solicita el cumplimiento de la condición T: Drop :


 fn foo<T: Drop>(x: T) {} 

Esto es a menudo un error ya que las primitivas no implementan Drop . Además, T: Drop no cubre tipos como String , que no tienen un comportamiento destructivo, sino el resultado de tipos en línea (como Vec<u8> ).


Además de drop_bounds , esta versión divide redundant_closure en redundant_closure y redundant_closure_for_method_calls .


Lea la versión detallada de Clippy aquí .


Cambios en carga


Una descripción detallada de los cambios de carga está disponible aquí .


Miembros 1.35.0


Mucha gente se unió para crear Rust 1.35.0. No podríamos haber hecho esto sin todos ustedes, ¡ gracias !


Del traductor


Con cualquier pregunta sobre el idioma Rust, podrán ayudarlo en el chat de Telegram en ruso o en un chat similar para los recién llegados .

Source: https://habr.com/ru/post/453338/


All Articles