diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index 0a7e618d..9735b7f3 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -239,8 +239,8 @@ ayudar a dividir líneas largas cuando llamas a un método con la sintaxis `.method_name()`. Ahora discutamos lo que hace esta línea. Como se mencionó anteriormente, `read_line` coloca lo que el usuario ingresa en -la cadena que le pasamos, pero también devuelve un valor `Result`. [`Result`][ -result] es una [*enumeración*][enums], a menudo +la cadena que le pasamos, pero también devuelve un valor `Result`. [`Result`][result] +es una [*enumeración*][enums], a menudo llamada *enum*, que es un tipo que puede estar en uno de varios estados posibles. Llamamos a cada estado posible a una *variante*. diff --git a/src/ch03-02-data-types.md b/src/ch03-02-data-types.md index 7788046b..0ea8757d 100644 --- a/src/ch03-02-data-types.md +++ b/src/ch03-02-data-types.md @@ -1,16 +1,15 @@ ## Tipos de datos Cada valor en Rust es de un cierto *tipo de dato*, que le dice a Rust qué tipo -de dato se está especificando para que sepa cómo trabajar con ese dato. Veremos -dos subconjuntos de tipos de datos: escalar y compuesto. +de dato se está especificando para que sepa cómo trabajar con ese dato. Veremos dos subconjuntos de tipos de datos: escalares y compuestos. Tenga en cuenta que Rust es un lenguaje *estáticamente tipado*, lo que significa que debe conocer los tipos de todas las variables en tiempo de compilación. El compilador generalmente puede inferir qué tipo queremos usar en función del valor y cómo lo usamos. En los casos en que muchos tipos son posibles, como -cuando convertimos un `String` en un tipo numérico usando `parse` en la -[sección “Comparando la Adivinanza con el Número Secreto”][comparing-the-guess-to-the-secret-number] - del capítulo 2, debemos agregar una anotación de tipo, como +cuando convertimos un `String` en un tipo numérico usando `parse` en la sección +[“Comparando la Adivinanza con el Número Secreto”][comparing-the-guess-to-the-secret-number] +del capítulo 2, debemos agregar una anotación de tipo, como esta: ```rust @@ -54,26 +53,26 @@ estas variantes para declarar el tipo de un valor entero. | 128-bit | `i128` | `u128` | | arch | `isize` | `usize` | -Cada variante puede ser *signed* (con signo) o *unsigned* (sin signo) y tiene +Cada variante puede ser *signed* (con signo) o *unsigned* (sin signo) y tiene un tamaño explícito. *Signed* y *unsigned* se refieren a si es posible que el -número sea negativo, es decir, si el número necesita tener un signo con él +número sea negativo, es decir, si el número necesita tener un signo con él (signed) o si solo será positivo y por lo tanto puede representarse sin signo (unsigned). Es como escribir números en papel: cuando el signo importa, un número se muestra con un signo más o un signo menos; sin embargo, cuando es -seguro suponer que el número es positivo, se muestra sin signo. +seguro suponer que el número es positivo, se muestra sin signo. Los números con signo se almacenan usando la -[representación de complemento a dos][twos-complement]. +representación de [complemento a dos][twos-complement]. -Cada variante con signo puede almacenar números de -(2n - 1) -a 2n - 1 - 1, donde *n* es el número de bits que usa la variante. -Así, un `i8` puede almacenar números de -(27) a 27 - 1, -lo que equivale a -128 a 127. Las variantes sin signo pueden almacenar números -de 0 a 2n - 1, por lo que un `u8` puede almacenar números de 0 a 28 - 1, +Cada variante con signo puede almacenar números de -(2n - 1) +a 2n - 1 - 1, donde *n* es el número de bits que usa la variante. +Así, un `i8` puede almacenar números de -(27) a 27 - 1, +lo que equivale a -128 a 127. Las variantes sin signo pueden almacenar números +de 0 a 2n - 1, por lo que un `u8` puede almacenar números de 0 a 28 - 1, lo que equivale a 0 a 255. -Además, los tipos `isize` y `usize` dependen de la arquitectura de la -computadora en la que se ejecuta su programa, que se denota en la tabla como -“arch”: 64 bits si está en una arquitectura de 64 bits y 32 bits si está en una +Además, los tipos `isize` y `usize` dependen de la arquitectura de la +computadora en la que se ejecuta su programa, que se denota en la tabla como +“arch”: 64 bits si está en una arquitectura de 64 bits y 32 bits si está en una arquitectura de 32 bits. Puede escribir literales enteros en cualquiera de las formas que se muestran en @@ -115,12 +114,12 @@ colección. > Cuando está compilando en modo de lanzamiento con la bandera `--release`, > Rust *no* incluye comprobaciones para el desbordamiento de enteros que > provocan desbordamientos. En su lugar, si ocurre un desbordamiento, Rust -> realiza *complemento de dos envolviendo*. En resumen, los valores mayores que +> realiza una *envoltura de complemento a dos*. En resumen, los valores mayores que > el valor máximo que el tipo puede contener “se envuelven” al mínimo de los > valores que el tipo puede contener. En el caso de un `u8`, el valor 256 se > convierte en 0, el valor 257 se convierte en 1, y así sucesivamente. El > programa no se desbordará, pero la variable tendrá un valor que probablemente -> no sea el que esperaba que tuviera. Depender del comportamiento de envoltura +> no sea el que esperaba que tuviera. Depender del comportamiento de la envoltura > del desbordamiento de enteros se considera un error. > > Para manejar explícitamente la posibilidad de desbordamiento, puede usar estas @@ -170,8 +169,8 @@ código muestra cómo usaría cada operación numérica en una declaración `let ``` Cada expresión en estas instrucciones usa un operador matemático y se evalúa a -un solo valor, que luego se vincula a una variable. [Apéndice -B][appendix_b] contiene una lista de todos los operadores que +un solo valor, que luego se vincula a una variable. El [Apéndice +B][appendix_b] contiene una lista de todos los operadores que Rust proporciona. #### El tipo booleano @@ -193,8 +192,7 @@ la sección [“Control de flujo”][control-flow]. #### El tipo de carácter -El tipo `char` de Rust es el tipo alfabético más primitivo del lenguaje. Aquí -hay algunos ejemplos de declarar valores `char`: +El tipo `char` de Rust es el tipo alfabético más primitivo del lenguaje. Estos son algunos ejemplos de declaración de valores `char`: Nombre de archivo: src/main.rs @@ -203,9 +201,7 @@ hay algunos ejemplos de declarar valores `char`: ``` Tenga en cuenta que especificamos literales `char` con comillas simples, en -oposición a literales de cadena, que usan comillas dobles. El tipo `char` de -Rust tiene cuatro bytes de tamaño y representa un valor escalar de Unicode, -lo que significa que puede representar mucho más que solo ASCII. Letras +oposición a literales de cadena, que usan comillas dobles. El tipo `char` de Rust tiene un tamaño de cuatro bytes y representa un valor escalar Unicode, lo que significa que puede representar mucho más que ASCII. Letras acentuadas; Caracteres chinos, japoneses y coreanos; Emojis; y espacios de ancho cero son todos valores `char` válidos en Rust. Los valores escalar de Unicode van desde `U+0000` a `U+D7FF` y `U+E000` a `U+10FFFF` inclusive. Sin embargo, @@ -221,14 +217,10 @@ tiene dos tipos compuestos primitivos: tuplas y matrices. #### El Tipo Tupla -Una *tupla* es una forma general de agrupar juntos un número de valores con -una variedad de tipos en un solo tipo compuesto. Las tuplas tienen una -longitud fija: una vez declaradas, no pueden crecer ni disminuir en tamaño. +Una *tupla* es una forma general de agrupar varios valores de distintos tipos en un tipo compuesto. Las tuplas tienen una longitud fija: una vez declaradas, su tamaño no puede aumentar ni disminuir. -Creamos una tupla escribiendo una lista separada por comas de valores dentro de -paréntesis. Cada posición en la tupla tiene un tipo, y los tipos de los -valores diferentes en la tupla no tienen que ser los mismos. Hemos agregado -anotaciones de tipo opcionales en este ejemplo: +Creamos una tupla escribiendo una lista de valores separados por comas dentro de +paréntesis. Cada posición de la tupla tiene un tipo, y los tipos de los distintos valores de la tupla no tienen por qué ser iguales. En este ejemplo hemos añadido anotaciones de tipo opcionales: Nombre de archivo: src/main.rs @@ -236,10 +228,7 @@ anotaciones de tipo opcionales en este ejemplo: {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-10-tuples/src/main.rs}} ``` -La variable `tup` se vincula a toda la tupla porque se considera que una tupla -es un único elemento compuesto. Para obtener los valores individuales de una -tupla, podemos usar el emparejamiento de patrones para descomponer un valor de -tupla, así: +La variable `tup` se vincula a toda la tupla porque una tupla se considera un único elemento compuesto. Para obtener los valores individuales de una tupla, podemos utilizar la concordancia de patrones para desestructurar un valor de tupla, así: Nombre de archivo: src/main.rs @@ -288,7 +277,7 @@ de corchetes: ``` Los arreglos son útiles cuando desea que sus datos se asignen en el stack (pila) -en lugar del heap (montículo) (hablaremos más sobre el stack y el heap en el +en lugar del heap (montículo) (hablaremos más sobre el stack y el heap en el [Capítulo 4][stack-and-heap]) o cuando desea asegurarse de que siempre tenga un número fijo de elementos. Sin embargo, un arreglo no es tan flexible como el tipo vector. Un *vector* es un tipo de colección similar @@ -331,10 +320,7 @@ de una manera más concisa. ##### Accediendo a los Elementos del Arreglo - -Un arreglo es un solo fragmento de memoria de un tamaño conocido y fijo que se -puede asignar en el stack. Puede acceder a los elementos de un arreglo usando -indexación, así: +Un arreglo es un trozo de memoria de tamaño fijo y conocido que puede asignarse a la pila. Se puede acceder a los elementos de una matriz utilizando la indexación, de la siguiente manera: Nombre de archivo: src/main.rs @@ -374,26 +360,11 @@ thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` -El programa resultó en un error de *ejecución* en el punto de uso de un valor -inválido en la operación de indexación. El programa salió con un mensaje de -error y no ejecutó la última instrucción `println!`. Cuando intenta acceder a un -elemento usando indexación, Rust verificará que el índice que ha especificado -es menor que la longitud del arreglo. Si el índice es mayor o igual que la -longitud, Rust entrará en pánico. Esta verificación debe ocurrir en tiempo de -ejecución, especialmente en este caso, porque el compilador no puede -posiblemente saber qué valor ingresará un usuario cuando ejecuten el código -después. - -Este es un ejemplo de los principios de seguridad de la memoria de Rust en -acción. En muchos lenguajes de bajo nivel, esta clase de verificación no se -realiza, y cuando proporciona un índice incorrecto, se puede acceder a la memoria -inválida. Rust lo protege contra este tipo de error al salir inmediatamente en -vez de permitir el acceso a la memoria y continuar. El Capítulo 9 discute más de -la gestión de errores de Rust y cómo puede escribir código legible y seguro que -ni se pone en pánico ni permite el acceso a la memoria inválida. - -[comparing-the-guess-to-the-secret-number]: -ch02-00-guessing-game-tutorial.html#comparando-la-adivinanza-con-el-numero-secreto +El programa dio lugar a un *error en tiempo de ejecución* al momento de utilizar un valor no válido en la operación de indexación. El programa salió con un mensaje de error y no ejecutó la sentencia final `println!`. Cuando intentas acceder a un elemento utilizando la indexación, Rust comprobará que el índice que has especificado es menor que la longitud del array. Si el índice es mayor o igual que la longitud, Rust entrará en pánico. Esta comprobación tiene que ocurrir en tiempo de ejecución, especialmente en este caso, porque el compilador no puede saber qué valor introducirá el usuario cuando ejecute el código más tarde. + +Este es un ejemplo de los principios de seguridad de memoria de Rust en acción. En muchos lenguajes de bajo nivel, este tipo de comprobación no se hace, y cuando proporcionas un índice incorrecto, se puede acceder a memoria inválida. Rust te protege contra este tipo de error saliendo inmediatamente en lugar de permitir el acceso a la memoria y continuar. El Capítulo 9 discute más sobre el manejo de errores de Rust y cómo puedes escribir código legible y seguro que no entre en pánico ni permita el acceso a memoria inválida. + +[comparing-the-guess-to-the-secret-number]: ch02-00-guessing-game-tutorial.html#comparando-la-adivinanza-con-el-numero-secreto [twos-complement]: https://es.wikipedia.org/wiki/Complemento_a_dos [control-flow]: ch03-05-control-flow.html#flujo-de-control [strings]: ch08-02-strings.html#almacenando-texto-codificado-en-utf-8-con-strings diff --git a/src/ch19-01-unsafe-rust.md b/src/ch19-01-unsafe-rust.md index aa634cd3..5300a380 100644 --- a/src/ch19-01-unsafe-rust.md +++ b/src/ch19-01-unsafe-rust.md @@ -13,7 +13,7 @@ algunos programas no válidos. Aunque el código *podría* estar bien, si el compilador de Rust no tiene suficiente información para estar seguro, rechazará el código. En estos casos, puede usar código inseguro para decirle al compilador: "Confía en mí, sé lo que estoy haciendo". Sin embargo, debes tener -cuidado, ya que el uso de Unsafe Rust conlleva riesgos: si usas código inseguro +cuidado, ya que el uso de Unsafe Rust conlleva riesgos: si usas código inseguro de manera incorrecta, pueden ocurrir problemas debido a la inseguridad de la memoria, como la desreferenciación de puntero nulo. @@ -39,7 +39,7 @@ Unsafe*. Esos superpoderes incluyen la capacidad de: * Implementar un trait inseguro * Acceder a los campos de `union`s -Es importante entender que `unsafe` no desactiva el borrow checker ni +Es importante entender que `unsafe` no desactiva el borrow checker ni deshabilita ninguna otra de las comprobaciones de seguridad de Rust: si usa una referencia en código inseguro, aún se verificará. La palabra clave `unsafe` solo le da acceso a estas cinco funciones que luego no son verificadas por el @@ -73,11 +73,11 @@ inseguro. ### Desreferenciación de un puntero crudo -En el Capítulo 4, en la sección [“Referencias y -punteros”][references-and-pointers] mencionamos que el compilador -garantiza que las referencias siempre son válidas. Unsafe Rust tiene dos nuevos -tipos llamados *punteros crudos* que son similares a las referencias. Al igual -que con las referencias, los punteros crudos pueden ser inmutables o mutables y +En el Capítulo 4, en la sección [`Referencias y punteros`][dangling-references] + mencionamos que el compilador garantiza que las referencias siempre son válidas. +Unsafe Rust tiene dos nuevos tipos llamados *punteros crudos* que son similares +a las referencias. Al igual que con las referencias, los punteros crudos pueden +ser inmutables o mutables y se escriben como `*const T` y `*mut T`, respectivamente. El asterisco no es el operador de desreferencia; es parte del nombre del tipo. En el contexto de los punteros crudos, *inmutable* significa que el puntero no se puede asignar @@ -96,14 +96,14 @@ la seguridad garantizada a cambio de un mayor rendimiento o la capacidad de interactuar con otro lenguaje o hardware donde las garantías de Rust no se aplican. -El Listing 19-1 muestra cómo crear un puntero crudo inmutable y mutable a +El Listing 19-1 muestra cómo crear un puntero crudo inmutable y mutable a partir de referencias. ```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-01/src/main.rs:here}} ``` -Listing 19-1: Creando punteros crudos a partir de +Listing 19-1: Creando punteros crudos a partir de referencias Observa que no incluimos la palabra clave `unsafe` en este código. Podemos @@ -156,9 +156,9 @@ potencialmente creando una carrera de datos. ¡Ten cuidado! Con todos estos peligros, ¿por qué usarías punteros crudos? Un caso de uso importante es cuando se interactúa con código C, como verás en la siguiente -sección, [“Llamando a una función o método -inseguro”](#calling-an-unsafe-function-or-method). Otro caso es -cuando se construyen abstracciones seguras que el borrow checker no entiende. +sección, [“Llamando a una función o método +inseguro”](#calling-an-unsafe-function-or-method). Otro caso es +cuando se construyen abstracciones seguras que el borrow checker no entiende. Presentaremos funciones inseguras y luego veremos un ejemplo de una abstracción segura que usa código inseguro. @@ -213,7 +213,7 @@ el slice en el índice dado como argumento. El Listado 19-4 muestra cómo usar {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-04/src/main.rs:here}} ``` -Listing 19-4: Usando la función segura +Listing 19-4: Usando la función segura `split_at_mut` No podemos implementar esta función utilizando solo Rust seguro. Un intento @@ -259,7 +259,7 @@ y algunas llamadas a funciones inseguras para hacer que la implementación de {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-06/src/main.rs:here}} ``` -Listing 19-6: Usando código inseguro en la implementación +Listing 19-6: Usando código inseguro en la implementación de la función `split_at_mut` Recordemos la sección [“The Slice Type”][the-slice-type] del @@ -303,7 +303,7 @@ ubicación de memoria arbitraria y crea un slice de 10,000 elementos. {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}} ``` -Listing 19-7: Creando un slice a partir de una ubicación +Listing 19-7: Creando un slice a partir de una ubicación de memory arbitraria No somos propietarios de la memoria en esta ubicación arbitraria, y no hay @@ -356,7 +356,7 @@ valor absoluto de su argumento. > programación mangla los nombres de manera ligeramente diferente, por lo que > para que una función Rust sea nombrable por otros lenguajes, debemos > deshabilitar el mangling del compilador de Rust. -> +> > En el siguiente ejemplo, hacemos que la función `call_from_c` sea accesible > desde el código C, después de que se compile a una biblioteca compartida y > se vincule desde C: @@ -367,13 +367,14 @@ valor absoluto de su argumento. > println!("Just called a Rust function from C!"); > } > ``` +> > Este uso de `extern` no requiere `unsafe`. ### Acceder o modificar una variable estática mutable En este libro, aún no hemos hablado de *variables globales*, las cuales Rust admite, pero pueden ser problemáticas con las reglas de ownership de Rust. Si -dos hilos acceden a la misma variable global mutable, puede causar una +dos hilos acceden a la misma variable global mutable, puede causar una condición de carrera. En Rust, las variables globales son llamadas variables *static*. El Listado @@ -390,12 +391,12 @@ string slice como valor. inmutable Las static variables son similares a las constantes, que discutimos en la -sección ["Diferencias entre variables y +sección ["Diferencias entre variables y constantes"][differences-between-variables-and-constants] en el Capítulo 3. Los nombres de las variables static están en `SCREAMING_SNAKE_CASE` por convención. Las variables static solo pueden almacenar referencias con el lifetime -`'static`, lo que significa que el compilador de Rust puede calcular el -lifetime y no estamos obligados a anotarlo explícitamente. Acceder a una +`'static`, lo que significa que el compilador de Rust puede calcular el +lifetime y no estamos obligados a anotarlo explícitamente. Acceder a una variable static inmutable es seguro. Una diferencia sutil entre constantes y variables static inmutables es que los @@ -440,7 +441,7 @@ como `unsafe` también, como se muestra en el Listado 19-11. {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}} ``` -Listing 19-11: Definiendo e implementando un trait +Listing 19-11: Definiendo e implementando un trait inseguro Al utilizar `unsafe impl`, estamos prometiendo que mantendremos las invariantes @@ -476,11 +477,8 @@ mantener la seguridad de la memoria. Cuando tengas una razón para usar código `unsafe`, puedes hacerlo, y tener la anotación `unsafe` explícita hace que sea más fácil rastrear la fuente de los problemas cuando ocurren. -[dangling-references]: -ch04-02-references-and-borrowing.html#dangling-references -[differences-between-variables-and-constants]: -ch03-01-variables-and-mutability.html#constants -[extensible-concurrency-with-the-sync-and-send-traits]: -ch16-04-extensible-concurrency-sync-and-send.html#extensible-concurrency-with-the-sync-and-send-traits +[dangling-references]: ch04-02-references-and-borrowing.html#dangling-references +[differences-between-variables-and-constants]: ch03-01-variables-and-mutability.html#constants +[extensible-concurrency-with-the-sync-and-send-traits]: ch16-04-extensible-concurrency-sync-and-send.html#extensible-concurrency-with-the-sync-and-send-traits [the-slice-type]: ch04-03-slices.html#the-slice-type [reference]: https://doc.rust-lang.org/reference/items/unions.html diff --git a/src/title-page.md b/src/title-page.md index 8f5fce3f..5a2797f8 100644 --- a/src/title-page.md +++ b/src/title-page.md @@ -19,7 +19,7 @@ Press][nsprust]. [install]: ch01-01-installation.html [editions]: appendix-05-editions.html [nsprust]: https://nostarch.com/rust-programming-language-2nd-edition -[translations]: appendix-06-translation.html +[traducciones]: appendix-06-translation.html > **🚨 ¿Quieres una experiencia de aprendizaje más interactiva? Prueba una > versión diferente del Libro de Rust, con: cuestionarios, resaltado,