Articulo de referencia

Sintaxis de Rust

Un fragmento de código Rust La sintaxis de Rust es el conjunto de reglas que definen cómo se escribe y compila un programa en Rust . La sintaxis de Rust es similar a la de C y C...

Un fragmento de código Rust

La sintaxis de Rust es el conjunto de reglas que definen cómo se escribe y compila un programa en Rust .

La sintaxis de Rust es similar a la de C y C++ , [ 1 ] [ 2 ] aunque muchas de sus características fueron influenciadas por lenguajes de programación funcional como OCaml . [ 3 ]

Lo esencial

Aunque la sintaxis de Rust está muy influenciada por las sintaxis de C y C++, la sintaxis de Rust es mucho más distinta de la sintaxis de C++ que la de Java o C# , ya que esos lenguajes tienen más declaraciones, nombres de tipos primitivos y palabras clave al estilo de C.

A continuación se muestra un programa "¡Hola, mundo!" en Rust. La fnpalabra clave denota una función , y la println!macro (ver §  Macros ) imprime el mensaje en la salida estándar . [ 4 ] Las instrucciones en Rust se separan con punto y coma .

fn main () { println! ( "Hola, mundo!" ); }

Palabras reservadas

Palabras clave

Las siguientes 42 palabras están reservadas y no pueden utilizarse como identificadores.

  • as
  • async
  • await
  • break
  • const
  • continue
  • crate
  • dyn
  • else
  • enum
  • extern
  • false
  • fn
  • for
  • if
  • impl
  • in
  • let
  • loop
  • match
  • mod
  • move
  • mut
  • pub
  • ref
  • return
  • Self
  • self
  • static
  • struct
  • super
  • trait
  • true
  • type
  • union
  • unsafe
  • use
  • where
  • while

Palabras no utilizadas

Las siguientes palabras están reservadas como palabras clave, pero actualmente no tienen ningún uso ni propósito. Hay 14 palabras sin usar.

  • abstract
  • become
  • box
  • do
  • final
  • gen
  • macro
  • override
  • priv
  • try
  • typeof
  • unsized
  • virtual
  • yield

Variables

Las variables en Rust se definen mediante la letpalabra clave. [ 5 ] El siguiente ejemplo asigna un valor a la variable con nombre fooy muestra su valor.

fn main () { let foo : i32 = 10 ; println! ( "El valor de foo es {foo}" ); }

Las variables son inmutables por defecto, pero al añadir la mutpalabra clave se permite que la variable sea mutada. [ 6 ] El siguiente ejemplo utiliza //, que denota el inicio de un comentario . [ 7 ]

fnmain(){// This code would not compile without adding "mut".letmutfoo:i32=10;println!("The value of foo is {foo}");foo=20;println!("The value of foo is {foo}");}

Multiple let expressions can define multiple variables with the same name, known as variable shadowing. Variable shadowing allows transforming variables without having to name the variables differently.[8] The example below declares a new variable with the same name that is double the original value:

fnmain(){letfoo:i32=10;// This will output "The value of foo is 10"println!("The value of foo is {foo}");letfoo:i32=foo*2;// This will output "The value of foo is 20"println!("The value of foo is {foo}");}

Variable shadowing is also possible for values of different types. For example, going from a string to its length in bytes:

fnmain(){letletters:str="abc";letletters:usize=letters.len();}

Block expressions and control flow

A block expression is delimited by curly brackets. When the last expression inside a block does not end with a semicolon, the block evaluates to the value of that trailing expression:[9]

fnmain(){letx:i32={println!("this is inside the block");1+2};println!("1 + 2 = {x}");}

Trailing expressions of function bodies are used as the return value:[10]

fnadd_two(x:i32)->i32{x+2}

if expressions

Una ifexpresión condicional ejecuta código en función de si el valor dado es verdadero o falso true. elseSe puede usar para cuando el valor se evalúa como verdadero false, y else ifse puede usar para combinar múltiples expresiones. [ 11 ]

fn main () { let x : i32 = 10 ; if x > 5 { println! ( "el valor es mayor que cinco" ); }if x % 7 == 0 { println! ( "El valor es divisible por 7" ); } else if x % 5 == 0 { println! ( "El valor es divisible por 5" ); } else { println! ( "El valor no es divisible por 7 ni por 5" ); } }

ify elselos bloques pueden evaluarse a un valor, que luego puede asignarse a una variable: [ 11 ]

fn main () { let x : i32 = 10 ; let new_x : i32 = if x % 2 == 0 { x / 2 } else { 3 * x + 1 }; println! ( "{new_x}" ); }

whilebucles

whilepuede utilizarse para repetir un bloque de código mientras se cumple una condición. [ 12 ]

fn main () { // Iterar sobre todos los enteros del 4 al 10 let mut value : i32 = 4 ; while value <= 10 { println! ( "value = {value}" ); value += 1 ; } }

forbucles e iteradores

Los bucles for en Rust recorren los elementos de una colección. [ 13 ]for Las expresiones funcionan sobre cualquier tipo de iterador .

fn main () { // Usando `for` con sintaxis de rango para la misma funcionalidad que arriba // La sintaxis 4..=10 significa el rango de 4 a 10, hasta 10 inclusive. for value in 4 ..= 10 { println! ( "value = {value}" ); } }

En el código anterior, 4..=10es un valor de tipo Rangeque implementa el Iteratorrasgo. El código dentro de las llaves se aplica a cada elemento devuelto por el iterador.

Los iteradores se pueden combinar con funciones sobre iteradores como map, filter, y sum. Por ejemplo, la siguiente suma todos los números entre 1 y 100 que son múltiplos de 3:

( 1 ..= 100 ). filtro ( |& x : i8 | -> bool x % 3 == 0 ). suma ()

loopy breakdeclaraciones

En términos más generales, la looppalabra clave permite repetir una porción de código hasta que breakocurra un evento. breakOpcionalmente, puede salir del bucle con un valor. En el caso de bucles anidados, las etiquetas denotadas por 'label_namepueden usarse para romper un bucle externo en lugar del bucle más interno. [ 14 ]

fn main () { let value : i32 = 456 ; let mut x : i32 = 1 ; let y = loop { x *= 10 ; if x > value { break x / 10 ; } }; println! ( "Mayor potencia de diez que es menor o igual que value: {y}" );let mut up : i32 = 1 ; ' outer : loop { let mut down : i32 = 120 ; loop { if up > 100 { break 'outer ; }Si down < 4 { break ; }abajo /= 2 ; arriba += 1 ; println! ( "arriba: {arriba}, abajo: {abajo}" ); } arriba *= 2 ; } }

Coincidencia de patrones

Las expresiones matchy if letse pueden usar para la coincidencia de patrones . Por ejemplo, matchse puede usar para duplicar un valor entero opcional si está presente, y devolver cero en caso contrario: [ 15 ]

fn double ( x : Option < u64 > ) -> u64 { match x { Some ( y ) => y * 2 , None => 0 , } }

De forma equivalente, esto se puede escribir con if lety else:

fn double ( x : Option < u64 > ) -> u64 { if let Some ( y ) = x { y * 2 } else { 0 } }

Tipos

Rust es fuertemente tipado y estático , lo que significa que los tipos de todas las variables deben conocerse en tiempo de compilación. Asignar un valor de un tipo particular a una variable de tipo diferente provoca un error de compilación . Se utiliza la inferencia de tipos para determinar el tipo de las variables si no se especifica. [ 16 ]

El tipo (), llamado "tipo de unidad" en Rust, es un tipo concreto que tiene exactamente un valor (él mismo). No ocupa memoria (ya que representa la ausencia de valor). Todas las funciones que no tienen un tipo de retorno indicado devuelven implícitamente (). Es similar a voiden otros lenguajes de estilo C, sin embargo voiddenota la ausencia de un tipo y no puede tener ningún valor.

El tipo de entero predeterminado es i32, y el tipo de punto flotante predeterminado es f64. Si el tipo de un número literal no se proporciona explícitamente, se infiere del contexto o se utiliza el tipo predeterminado. [ 17 ]

Tipos primitivos

En Rust, los tipos enteros se nombran según su signo y la cantidad de bits que ocupan. Por ejemplo, i32es un entero con signo que ocupa 32 bits de almacenamiento, mientras que u8es sin signo y solo ocupa 8 bits. isizey usizeocupan almacenamiento dependiendo de la arquitectura del ordenador que ejecuta el código; por ejemplo, en ordenadores con arquitecturas de 32 bits , ambos tipos ocuparán 32 bits de espacio.

Por defecto, los literales enteros están en base 10, pero se admiten diferentes bases0b11 con prefijos, por ejemplo, para números binarios , 0o567para octales y 0xDBpara hexadecimales . Por defecto, los literales enteros tienen como tipo predeterminado. Se pueden usar i32sufijos como para establecer explícitamente el tipo de un literal. [ 18 ] Los literales de byte como están disponibles para representar el valor ASCII (como un ) de un carácter específico. [ 19 ]4u32b'X'u8

El tipo booleano se denomina boolque puede tomar un valor de trueo false. Un charocupa 32 bits de espacio y representa un valor escalar Unicode: [ 20 ] un punto de código Unicode que no es un sustituto . [ 21 ] Los números de punto flotante IEEE 754 son compatibles con f32para flotantes de precisión simple y f64para flotantes de doble precisión . [ 22 ]

Tipos compuestos

Los tipos compuestos pueden contener múltiples valores. Las tuplas son listas de tamaño fijo que pueden contener valores cuyos tipos pueden ser diferentes. Los arrays son listas de tamaño fijo cuyos valores son del mismo tipo. Las expresiones de los tipos tupla y array se pueden escribir enumerando los valores y se puede acceder a ellos con .indexo [index]: [ 23 ]

let tuple : ( u32 , i64 ) = ( 3 , - 3 ); let array : [ i8 ; 5 ] = [ 1 , 2 , 3 , 4 , 5 ]; let value : i64 = tuple . 1 ; // -3 let value : i8 = array [ 2 ]; // 3

Los arreglos también se pueden construir copiando un solo valor varias veces: [ 24 ]

let array2 : [ char ; 10 ] = [ ' ' ; 10 ];

Propiedad y referencias

El sistema de propiedad de Rust consiste en reglas que garantizan la seguridad de la memoria sin utilizar un recolector de basura. En tiempo de compilación, cada valor debe adjuntarse a una variable llamada propietario de ese valor, y cada valor debe tener exactamente un propietario. [ 25 ] Los valores se mueven entre diferentes propietarios mediante asignación o pasando un valor como parámetro de función. Los valores también pueden tomarse prestados, lo que significa que se pasan temporalmente a una función diferente antes de ser devueltos al propietario. [ 26 ] Con estas reglas, Rust puede prevenir la creación y el uso de punteros colgantes : [ 26 ] [ 27 ]

fn print_string ( s : String ) { println! ( "{}" , s ); }fn main () { let s : String = String :: from ( "Hello, World" ); print_string ( s ); // s consumido por print_string // s se ha movido, por lo que ya no se puede usar // otro print_string(s); resultaría en un error de compilación }

La función print_stringtoma posesión del Stringvalor pasado como argumento; alternativamente, &se puede usar para indicar un tipo de referencia (en &String) y para crear una referencia (en &s): [ 28 ]

fn print_string ( s : & String ) { println! ( "{}" , s ); }fn main () { let s : String = String :: from ( "Hello, World" ); print_string ( & s ); // s es prestada por print_string print_string ( & s ); // s no ha sido consumida; podemos llamar a la función muchas veces }

Debido a estas reglas de propiedad, los tipos de Rust se conocen como tipos lineales o afines , lo que significa que cada valor se puede usar exactamente una vez. Esto impone una forma de aislamiento de fallos de software , ya que el propietario de un valor es el único responsable de su corrección y liberación. [ 29 ]

Cuando un valor sale del ámbito, se elimina ejecutando su destructor . El destructor puede definirse programáticamente mediante la implementación del Droprasgo . Esto ayuda a gestionar recursos como identificadores de archivos, sockets de red y bloqueos , ya que cuando se eliminan objetos, los recursos asociados a ellos se cierran o liberan automáticamente. [ 30 ]

vidas

La vida útil de un objeto se refiere al período de tiempo durante el cual una referencia es válida; es decir, el tiempo entre la creación y la destrucción del objeto. [ 31 ] Estas vidas útiles están implícitamente asociadas con todos los tipos de referencia de Rust. Si bien a menudo se infieren, también pueden indicarse explícitamente con parámetros de vida útil con nombre (a menudo denotados como 'a, 'b, etc.). [ 32 ]

En Rust, la duración de los objetos puede considerarse con alcance léxico , lo que significa que la duración de la vida útil de un objeto se infiere del conjunto de ubicaciones en el código fuente (es decir, números de función, línea y columna) para las que una variable es válida. [ 33 ] Por ejemplo, una referencia a una variable local tiene una duración que corresponde al bloque en el que se define: [ 33 ]

fn main () { let x : i32 = 5 ; // ------------------+- Tiempo de vida 'a // | let r : & i32 = & x ; // -+-- Tiempo de vida 'b | // | | println! ( "r: {}" , r ); // | | // | | // -+ | } // ------------------+

El verificador de préstamos del compilador de Rust se asegura de que las referencias solo se utilicen en las ubicaciones del código fuente donde la vida útil asociada sea válida. [ 34 ] [ 35 ] En el ejemplo anterior, almacenar una referencia a la variable xen res válido, ya que la variable xtiene una vida útil más larga ( 'a) que la variable r( 'b). Sin embargo, cuando xtiene una vida útil más corta, el verificador de préstamos rechazaría el programa:

fn main () { let r : & i32 ; // ------------------+- Tiempo de vida 'a // | { // | let x : i32 = 5 ; // -+-- Tiempo de vida 'b | r = & x ; // ERROR: x no | | } // vive mucho -| | // suficiente | println! ( "r: {}" , r ); // | } // ------------------+

Dado que la vida útil de la variable referenciada ( 'b) es más corta que la vida útil de la variable que contiene la referencia ( 'a), el verificador de préstamos falla, impidiendo xque se utilice fuera de su ámbito. [ 36 ]

Los tiempos de vida se pueden indicar utilizando parámetros de tiempo de vida explícitos en los argumentos de la función. Por ejemplo, el siguiente código especifica que la referencia devuelta por la función tiene el mismo tiempo de vida que original(y no necesariamente el mismo tiempo de vida que prefix): [ 37 ]

fn remove_prefix <' a > ( mut original : & ' a str , prefix : & str ) -> & ' a str { if original . starts_with ( prefix ) { original = original [ prefix . len () .. ]; } original }

En el compilador, la propiedad y los tiempos de vida trabajan juntos para prevenir problemas de seguridad de memoria como punteros colgantes. [ 38 ] [ 39 ]

Tipos definidos por el usuario

Los tipos definidos por el usuario se crean con las palabras clave structo enum. La structpalabra clave se utiliza para denotar un tipo de registro que agrupa múltiples valores relacionados. [ 40 ]enum Los pueden adoptar diferentes variantes en tiempo de ejecución, con capacidades similares a los tipos de datos algebraicos que se encuentran en los lenguajes de programación funcional. [ 41 ] Tanto los registros como las variantes de enumeración pueden contener campos con diferentes tipos. [ 42 ] Se pueden definir nombres alternativos, o alias, para el mismo tipo con la typepalabra clave . [ 43 ]

La implpalabra clave puede definir métodos para un tipo definido por el usuario. Los datos y las funciones se definen por separado. Las implementaciones cumplen una función similar a la de las clases en otros lenguajes. [ 44 ]

Biblioteca estándar

OptionLos valores se manejan utilizando azúcar sintáctico , como la if letconstrucción, para acceder al valor interno (en este caso, una cadena): [ 59 ]

fn main () { let name1 : Option <& str > = None ; // En este caso, no se imprimirá nada if let Some ( name ) = name1 { println! ( "{name}" ); }let name2 : Option <& str > = Some ( "Matthew" ); // En este caso, se imprimirá la palabra "Matthew" if let Some ( name ) = name2 { println! ( "{name}" ); } }

Consejos

Para evitar el uso de punteros nulos y su desreferenciación , se garantiza que las referencias básicas &no sean nulas. Rust utiliza en su lugar para este propósito: indica que hay un valor presente y es análogo al puntero nulo. [ 60 ] implementa una "optimización de puntero nulo", evitando cualquier sobrecarga espacial para tipos que no pueden tener un valor nulo (referencias o los tipos, por ejemplo). [ 61 ] Aunque los punteros nulos se evitan idiomáticamente, la constante de puntero nulo en Rust se representa mediante .&mutOptionSome(T)NoneOptionNonZerostd::ptr::null()

Rust también admite punteros sin formato *consty *mut, que pueden ser nulos; sin embargo, es imposible desreferenciarlos a menos que el código se declare explícitamente como inseguro mediante el uso de un unsafebloque. A diferencia de la desreferenciación, la creación de punteros sin formato está permitida dentro de código Rust seguro. [ 62 ]

Conversión de tipo

Rust no proporciona conversión de tipos implícita (coerción) entre la mayoría de los tipos primitivos. Sin embargo, la conversión de tipos explícita (casting) se puede realizar utilizando la aspalabra clave. [ 63 ]

let x : i32 = 1000 ; println! ( "1000 como u16 es: {}" , x as u16 );
Presentación sobre Rust a cargo de Emily Dunham, del equipo de Rust de Mozilla (conferencia linux.conf.au , Hobart, 2017).

Polimorfismo

Medicamentos genéricos

Entre las características más avanzadas de Rust se incluye el uso de funciones genéricas . A una función genérica se le asignan parámetros genéricos , lo que permite aplicar la misma función a diferentes tipos de variables. Esta capacidad reduce el código duplicado [ 64 ] y se conoce como polimorfismo paramétrico .

El siguiente programa calcula la suma de dos elementos, para lo cual la suma se implementa utilizando una función genérica:

usar std :: ops :: Add ;// sum es una función genérica con un parámetro de tipo, T fn sum < T > ( num1 : T , num2 : T ) -> T donde T : Add < Output = T > , // T debe implementar el rasgo Add donde la suma devuelve otro T { num1 + num2 // num1 + num2 es azúcar sintáctico para num1.add(num2) proporcionado por el rasgo Add }fn main () { let result1 : i32 = sum ( 10 , 20 ); println! ( "La suma es: {}" , result1 ); // La suma es: 30let result2 : f32 = sum ( 10.23 , 20.45 ); println! ( "La suma es: {}" , result2 ); // La suma es: 30.68 }

En tiempo de compilación, las funciones polimórficas como esta sumse instancian con los tipos específicos que requiere el código; en este caso, suma de enteros y suma de números de coma flotante.

Los genéricos se pueden usar en funciones para permitir implementar un comportamiento para diferentes tipos sin repetir el mismo código. Las funciones genéricas se pueden escribir en relación con otros genéricos, sin conocer el tipo real. [ 65 ]

Rasgos

Fragmento de std::io

El sistema de tipos de Rust admite un mecanismo llamado traits, inspirado en las clases de tipos del lenguaje Haskell , [ 66 ] para definir un comportamiento compartido entre diferentes tipos. Por ejemplo, el Addtrait se puede implementar para floats y enteros, que se pueden sumar; y los traits Displayor Debugse pueden implementar para cualquier tipo que se pueda convertir a una cadena. Los traits se pueden usar para proporcionar un conjunto de comportamiento común para diferentes tipos sin conocer el tipo real. Esta funcionalidad se conoce como polimorfismo ad hoc .

Las funciones genéricas pueden restringir el tipo genérico para que implemente una o varias características particulares; por ejemplo, una add_onefunción podría requerir que el tipo implemente Add. Esto significa que una función genérica puede ser verificada en cuanto se define. La implementación de genéricos es similar a la implementación típica de plantillas de C++: se genera una copia separada del código para cada instanciación. Esto se denomina monomorfismo y contrasta con el esquema de borrado de tipos que se suele utilizar en Java y Haskell. El borrado de tipos también está disponible mediante la palabra clave dyn(abreviatura de dynamic). [ 67 ] Debido a que el monomorfismo duplica el código para cada tipo utilizado, puede dar como resultado un código más optimizado para casos de uso específicos, pero también aumenta el tiempo de compilación y el tamaño del binario de salida. [ 68 ]

Además de definir métodos para un tipo definido por el usuario, la implpalabra clave se puede usar para implementar un rasgo para un tipo. [ 44 ] Los rasgos pueden proporcionar métodos derivados adicionales cuando se implementan. [ 69 ] Por ejemplo, el rasgo Iteratorrequiere que el nextmétodo esté definido para el tipo. Una vez que el nextmétodo está definido, el rasgo puede proporcionar métodos auxiliares funcionales comunes sobre el iterador, como mapo filter. [ 70 ]

objetos de rasgos

Los rasgos de Rust se implementan mediante despacho estático , lo que significa que el tipo de todos los valores se conoce en tiempo de compilación; sin embargo, Rust también utiliza una característica conocida como objetos de rasgo para lograr el despacho dinámico , un tipo de polimorfismo donde la implementación de una operación polimórfica se elige en tiempo de ejecución . Esto permite un comportamiento similar al tipado dinámico , donde todos los tipos de datos que implementan un rasgo dado pueden tratarse como funcionalmente equivalentes. [ 71 ] Los objetos de rasgo se declaran utilizando la sintaxis dyn Trdonde Tres un rasgo. Los objetos de rasgo tienen un tamaño dinámico, por lo tanto deben colocarse detrás de un puntero, como Box. [ 72 ] El siguiente ejemplo crea una lista de objetos donde cada objeto puede imprimirse utilizando el Displayrasgo:

usar std :: fmt :: Display ;let v : Vec < Box < dyn Display >> = vec! [ Box :: new ( 3 ), Box :: new ( 5.0 ), Box :: new ( "hi" ), ];para x en v { println! ( "{x}" ); }

Si un elemento de la lista no implementa el Displayrasgo, provocará un error de compilación. [ 73 ]

Seguridad de la memoria

Rust está diseñado para ser seguro en cuanto a la memoria . No permite punteros nulos, punteros colgantes ni condiciones de carrera . [ 74 ] [ 75 ] [ 76 ] [ 77 ] Los valores de datos solo pueden inicializarse mediante un conjunto fijo de formas, todas las cuales requieren que sus entradas ya estén inicializadas. [ 78 ]

El código inseguro puede subvertir algunas de estas restricciones, utilizando la unsafepalabra clave. [ 62 ] El código inseguro también puede utilizarse para funcionalidades de bajo nivel, como el acceso a memoria volátil , intrínsecos específicos de la arquitectura, el juego de tipos y el ensamblaje en línea. [ 79 ]

Gestión de la memoria

Rust no utiliza recolección de basura . La memoria y otros recursos se gestionan mediante la convención de "la adquisición de recursos es la inicialización" [ 80 ] , con conteo de referencias opcional. Rust proporciona una gestión determinista de los recursos, con una sobrecarga muy baja [ 81 ] . Los valores se asignan en la pila por defecto, y todas las asignaciones dinámicas deben ser explícitas [ 82 ] .

Los tipos de referencia integrados que utilizan el &símbolo no implican conteo de referencias en tiempo de ejecución. La seguridad y validez de los punteros subyacentes se verifica en tiempo de compilación, evitando punteros colgantes y otras formas de comportamiento indefinido . [ 83 ] El sistema de tipos de Rust separa las referencias compartidas e inmutables de la forma &Tde las referencias únicas y mutables de la forma &mut T. Una referencia mutable puede ser convertida a una referencia inmutable, pero no al revés. [ 84 ]

Macros

Las macros permiten la generación y transformación de código Rust para reducir la repetición. Existen dos tipos de macros: macros declarativas definidas mediante macro_rules!, y macros procedimentales , que se definen en crates separados. [ 85 ] [ 86 ]

Debido a que Rust carece de funciones variádicas o plantillas variádicas , las funciones variádicas se implementan utilizando macros variádicas , como println!y vec!. [ 87 ]

macros declarativas

Una macro declarativa (también llamada "macro por ejemplo") es una macro, definida mediante la macro_rules!palabra clave, que utiliza la coincidencia de patrones para determinar su expansión. [ 88 ] [ 89 ] A continuación se muestra un ejemplo que suma todos sus argumentos:

macro_rules! suma { ( $initial : expr $(, $expr : expr ) * $(, ) ? ) => { $initial $( + $expr ) * } }fn main () { let x : i32 = sum ! ( 1 , 2 , 3 ); println! ( "{x}" ); // imprime 6 }

Macros procedimentales

Las macros procedimentales son funciones de Rust que se ejecutan y modifican el flujo de tokens de entrada del compilador , antes de que se compile cualquier otro componente. Generalmente son más flexibles que las macros declarativas, pero son más difíciles de mantener debido a su complejidad. [ 90 ] [ 91 ]

Las macros procedimentales se presentan en tres variantes:

  • Macros con funcionescustom!(...)
  • Derivar macros#[derive(CustomDerive)]
  • macros de atributos#[custom_attribute]

Interfaz con C y C++

Rust tiene una interfaz de funciones externas (FFI) que se puede usar tanto para llamar código escrito en lenguajes como C desde Rust como para llamar código Rust desde esos lenguajes. A partir de 2024Existe una biblioteca externa llamada CXX para llamar a o desde C++. [ 92 ] Rust y C difieren en cómo organizan las estructuras en memoria, por lo que a las estructuras de Rust se les puede dar un #[repr(C)]atributo, forzando la misma disposición que la estructura equivalente de C. [ 93 ]

Véase también

Notas

  1. En sistemas Unix, esto suele ser cadenas UTF-8 sin un byte interno cero. En Windows, se trata de cadenas UTF-16 sin un byte interno cero. A diferencia de estas,stryStringsiempre son UTF-8 válidas y pueden contener ceros internos.

Referencias

  1. Proven, Liam (27/11/2019). "Rebecca Rumbul nombrada nueva directora ejecutiva de The Rust Foundation" . The Register . Archivado del original el 14/07/2022 . Consultado el 14/07/2022 . Ambos son lenguajes de llaves, con una sintaxis similar a la de C que los hace accesibles para los programadores de C.
  2. Vigliarolo, Brandon (10 de febrero de 2021). "El lenguaje de programación Rust ahora tiene su propia fundación independiente" . TechRepublic . Archivado del original el 20 de marzo de 2023. Consultado el 14 de julio de 2022 .
  3. Klabnik y Nichols 2019 , pág. 263.
  4. Klabnik y Nichols 2019 , págs. 5–6.
  5. Klabnik y Nichols 2023 , pág. 32.
  6. Klabnik y Nichols 2023 , págs. 32–33.
  7. Klabnik y Nichols 2023 , págs. 49–50.
  8. Klabnik y Nichols 2023 , págs. 34–36.
  9. Klabnik y Nichols 2023 , págs. 6, 47, 53.
  10. Klabnik y Nichols 2023 , págs. 47–48.
  11. 1 2 Klabnik y Nichols 2023 , págs. 50–53.
  12. Klabnik y Nichols 2023 , pág. 56.
  13. Klabnik y Nichols 2023 , págs. 57–58.
  14. Klabnik y Nichols 2023 , págs. 54–56.
  15. Klabnik y Nichols 2019 , págs. 104–109.
  16. Klabnik y Nichols 2019 , pág. 24.
  17. Klabnik y Nichols 2019 , págs. 36–38.
  18. Klabnik y Nichols 2023 , págs. 36–38.
  19. Klabnik y Nichols 2023 , pág. 502.
  20. "Tipo primitivo char" . doc.rust-lang.org . Consultado el 7 de septiembre de 2025 .
  21. "Glosario de términos Unicode" . Consorcio Unicode . Archivado del original el 24 de septiembre de 2018. Consultado el 30 de julio de 2024 .
  22. Klabnik y Nichols 2019 , págs. 38–40.
  23. Klabnik y Nichols 2023 , págs. 40–42.
  24. Klabnik y Nichols 2023 , pág. 42.
  25. Klabnik y Nichols 2019 , págs. 59–61.
  26. 1 2 Klabnik y Nichols 2019 , págs. 63–68.
  27. Klabnik y Nichols 2019 , págs. 74–75.
  28. Klabnik y Nichols 2023 , págs. 71–72.
  29. Balasubramanian, Abhiram; Baranowski, Marek S.; Burtsev, Anton; Panda, Aurojit; Rakamarić, Zvonimir; Ryzhyk, Leonid (2017-05-07). "Programación de sistemas en Rust" . Actas del 16.º Taller sobre Temas Candentes en Sistemas Operativos . HotOS '17. Nueva York, NY, EE. UU.: Association for Computing Machinery. págs. 156–161 . doi : 10.1145/3102980.3103006 . ISBN  978-1-4503-5068-6. S2CID 24100599 . Archivado del original el 11 de junio de 2022 . Recuperado el 1 de junio de 2022 . 
  30. Klabnik y Nichols 2023 , págs. 327–30.
  31. "Lifetimes" . Rust by Example . Archivado del original el 16/11/2024 . Consultado el 29/10/2024 .
  32. "Anotación explícita" . Rust by Example . Consultado el 29/10/2024 .
  33. 1 2 Klabnik y Nichols 2019 , pág. 194.
  34. Klabnik y Nichols 2019 , págs. 75, 134.
  35. Shamrell-Harrington, Nell (15 de abril de 2022). "El comprobador de préstamos de Rust: un análisis profundo" . InfoQ . Archivado del original el 25 de junio de 2022. Recuperado el 25 de junio de 2022 .
  36. Klabnik y Nichols 2019 , págs. 194–195.
  37. Klabnik y Nichols 2023 , págs. 208–12.
  38. Klabnik & Nichols 2023 , 4.2. Referencias y préstamos .
  39. Pearce, David (17 de abril de 2021). "Un formalismo ligero para tiempos de vida de referencia y préstamos en Rust" . ACM Transactions on Programming Languages ​​and Systems . 43 : 1–73 . doi : 10.1145/3443420 . Archivado del original el 15 de abril de 2024. Recuperado el 11 de diciembre de 2024 .
  40. Klabnik y Nichols 2019 , pág. 83.
  41. Klabnik y Nichols 2019 , pág. 97.
  42. Klabnik y Nichols 2019 , págs. 98–101.
  43. Klabnik y Nichols 2019 , págs. 438–440.
  44. 1 2 Klabnik y Nichols 2019 , págs. 93.
  45. "OsStr en std::ffi" . Documentación de la biblioteca estándar de Rust . Archivado del original el 23 de junio de 2023. Consultado el 2 de octubre de 2023 .
  46. "OsString en std::ffi" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 02/10/2023 .
  47. "Ruta en std::path" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 02/10/2023 .
  48. "PathBuf en std::path" . Documentación de la biblioteca estándar de Rust . Archivado del original el 27 de junio de 2023. Consultado el 2 de octubre de 2023 .
  49. 1 2 3 4 "std::boxed" . La documentación de la biblioteca estándar de Rust . Archivado del original el 23 de junio de 2023. Recuperado el 23 de junio de 2023 .
  50. "Rc en std::rc" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  51. "Arc en std::sync" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  52. "Celda en std::cell" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  53. "Mutex en std::sync" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  54. "RwLock en std::sync" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  55. "Condvar en std::sync" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  56. "Duración en std::time" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  57. "HashMap en std::collections" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  58. "BTreeMap en std::collections" . Documentación de la biblioteca estándar de Rust . Archivado del original el 24/06/2023 . Consultado el 24/06/2023 .
  59. McNamara 2021 .
  60. Klabnik y Nichols 2019 , págs. 101–104.
  61. "std::option" . Documentación de la biblioteca estándar de Rust . Consultado el 12 de noviembre de 2023 .
  62. 1 2 Klabnik y Nichols 2019 , págs. 418–427.
  63. "Casting" . Rust by Example . Consultado el 1 de abril de 2025 .
  64. Klabnik y Nichols 2019 , págs. 171–172.
  65. Klabnik y Nichols 2019 , págs. 171–172, 205.
  66. "Influencias" . The Rust Reference . Archivado del original el 26 de noviembre de 2023. Consultado el 31 de diciembre de 2023 .
  67. Klabnik y Nichols 2019 , págs. 181, 182.
  68. Gjengset 2021 , pág. 25.
  69. Klabnik y Nichols 2019 , págs. 182–184.
  70. Klabnik y Nichols 2019 , págs. 281–283.
  71. Klabnik y Nichols 2023 , 18.2. Uso de objetos de rasgos que permiten valores de diferentes tipos .
  72. Klabnik y Nichols 2019 , págs. 441–442.
  73. Klabnik y Nichols 2019 , págs. 379–380.
  74. Rosenblatt, Seth (3 de abril de 2013). "Samsung se une a la búsqueda de Rust por parte de Mozilla" . CNET . Archivado del original el 4 de abril de 2013. Consultado el 5 de abril de 2013 .
  75. Brown, Neil (17 de abril de 2013). "Un sabor a óxido" . LWN.net . Archivado del original el 26 de abril de 2013. Recuperado el 25 de abril de 2013 .
  76. "Razas" . El Rustonomicon . Archivado del original el 10 de julio de 2017. Consultado el 3 de julio de 2017 .
  77. Vandervelden, Thibaut; De Smet, Ruben; Deac, Diana; Steenhaut, Kris; Braeken, An (7 de septiembre de 2024). "Descripción general de los sistemas operativos y marcos de trabajo Rust integrados" . Sensors . 24 (17): 5818. Bibcode : 2024Senso..24.5818V . doi : 10.3390/ s24175818 . PMC 11398098. PMID 39275729 .  
  78. "Preguntas frecuentes sobre el lenguaje Rust" . El lenguaje de programación Rust. 2015. Archivado del original el 20 de abril de 2015. Consultado el 24 de abril de 2017 .
  79. McNamara 2021 , pág. 139, 376–379, 395.
  80. "RAII" . Rust by Example . Archivado del original el 21/04/2019 . Consultado el 22/11/2020 .
  81. "Abstracción sin sobrecarga: rasgos en Rust" . Blog de Rust . Archivado del original el 23 de septiembre de 2021. Consultado el 19 de octubre de 2021 .
  82. "Box, stack and heap" . Rust by Example . Archivado del original el 31/05/2022 . Consultado el 13/06/2022 .
  83. Klabnik y Nichols 2019 , págs. 70–75.
  84. Klabnik y Nichols 2019 , pág. 323.
  85. Klabnik y Nichols 2023 , págs. 449–455.
  86. Gjengset 2021 , págs .
  87. El equipo de Rust (1 de abril de 2026). "Interfaces variádicas" . rust-lang.org . Rust por ejemplo.
  88. "Macros por ejemplo" . The Rust Reference . Archivado del original el 21 de abril de 2023. Consultado el 21 de abril de 2023 .
  89. Klabnik y Nichols 2019 , págs. 446–448.
  90. "Macros procedimentales" . Referencia del lenguaje de programación Rust . Archivado del original el 7 de noviembre de 2020. Consultado el 23 de marzo de 2021 .
  91. Klabnik y Nichols 2019 , págs. 449–455.
  92. "Interoperabilidad segura entre Rust y C++ con CXX" . InfoQ . 6 de diciembre de 2020. Archivado del original el 22 de enero de 2021. Consultado el 3 de enero de 2021 .
  93. "Diseño de tipo" . The Rust Reference . Archivado del original el 16 de julio de 2022. Consultado el 15 de julio de 2022 .

Fuentes

  • Gjengset, Jon (2021). Óxido para los Rustáceos (1ª  ed.). Sin prensa de almidón. ISBN 9781718501850OCLC 1277511986 .​ 
  • Klabnik, Steve; Nichols, Carol (12 de agosto de 2019). El lenguaje de programación Rust (cubre Rust 2018) . No Starch Press. ISBN 978-1-7185-0044-0.
  • Klabnik, Steve; Nichols, Carol (2023). El lenguaje de programación Rust (2.ª  ed.). No Starch Press. ISBN 978-1-7185-0310-6OCLC 1363816350 .​ 
  • McNamara, Tim (2021). Rust in Action . Manning Publications. ISBN 978-1-6172-9455-6OCLC 1153044639