Skip to content

Commit

Permalink
Merge pull request RustLangES#49 from ivanlynch/main
Browse files Browse the repository at this point in the history
fix: improve readability and translations in chapter 4
  • Loading branch information
Phosphorus-M authored Feb 12, 2024
2 parents 6faa65b + fb42ed6 commit 7fbec29
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 105 deletions.
3 changes: 3 additions & 0 deletions ci/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,8 @@ dereferencing
DerefMut
DeriveInput
Dest
inglés
ningún
destructor
destructure
destructured
Expand Down Expand Up @@ -2055,3 +2057,4 @@ xcode
xpression
yyyy
ZipImpl
LIFO
43 changes: 20 additions & 23 deletions src/ch04-01-what-is-ownership.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## ¿Qué es el Ownership?

El *ownership* es un conjunto de reglas que gobiernan cómo un programa de Rust
El *ownership* es un conjunto de reglas que definen cómo un programa de Rust
administra la memoria. Todos los programas tienen que administrar la forma en
que usan la memoria de un computador mientras se ejecutan. Algunos lenguajes
tienen recolección de basura que busca regularmente la memoria que ya no se
Expand Down Expand Up @@ -30,7 +30,7 @@ datos muy común: las cadenas de caracteres.
> La analogía es que el ownership es como la propiedad de un objeto, por ejemplo
> si tienes un libro, el libro es tuyo. Si lo prestas a alguien, el libro sigue
> siendo tuyo, pero ahora el libro esta en posesión de otra persona. Cuando
> devuelves el libro, el libro regresa a tu posesión.
> te devuelven el libro, el libro regresa a tu posesión.
> ### El Stack y el Heap
>
Expand All @@ -44,8 +44,7 @@ datos muy común: las cadenas de caracteres.
> Tanto el stack como el heap son partes de la memoria disponible para su código
> para usar en tiempo de ejecución, pero están estructurados de formas
> diferentes. El stack almacena valores en el orden en que los recibe y elimina
> los valores en el orden opuesto. Esto se conoce como *último en, primero
> fuera*. Piense en una pila de platos: cuando agrega más platos, los coloca en
> los valores en el orden opuesto. Esto se conoce como LIFO que es el acrónimo inglés de *Last In, First Out* o en español *El último en entrar, es el primero en salir*. Piense en una pila de platos: cuando agrega más platos, los coloca en
> la parte superior de la pila, y cuando necesita un plato, toma uno de la
> parte superior. Agregar o eliminar platos del medio o de la parte inferior no
> funcionaría tan bien! Agregar datos se llama *empujar en el stack*, y
Expand Down Expand Up @@ -114,10 +113,10 @@ Ahora que hemos pasado la sintaxis básica de Rust, no incluiremos todo el códi
`fn main() {` en los ejemplos, por lo que si está siguiendo, asegúrese de
colocar los siguientes ejemplos dentro de una función `main` manualmente. Como
resultado, nuestros ejemplos serán un poco más concisos, permitiéndonos
centrarnos en los detalles reales en lugar del código de la caldera.
centrarnos en los detalles reales en lugar del código repetitivo.

Como primer ejemplo de ownership, veremos el *ámbito* de algunas variables.
Un ámbito es el rango dentro de un programa para el que un elemento es válido.
Como primer ejemplo de ownership, veremos el *contexto de ejecución* de algunas variables.
Un contexto de ejecución es el rango o espacio dentro de un programa para el que un elemento es válido.
Toma la siguiente variable:

```rust
Expand All @@ -126,23 +125,22 @@ let s = "hola";

La variable `s` se refiere a un literal de cadena, donde el valor de la cadena
está codificado en el texto de nuestro programa. La variable es válida desde el
punto en que se declara hasta el final del *ámbito* actual. El listado 4-1
punto en que se declara hasta el final del *contexto de ejecución* actual. El listado 4-1
muestra un programa con comentarios que anotan dónde sería válida la variable
`s`.

```rust
{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}}
```

<span class="caption">Listado 4-1: Una variable y el ámbito en el que es
válida</span>
<span class="caption">Listado 4-1: Una variable y el contexto de ejecución en el que es válida</span>

En otras palabras, hay dos puntos importantes en el tiempo aquí:

* Cuando `s` entra en *ámbito*, es válido.
* Permanece válido hasta que sale de *ámbito*.
* Cuando `s` está el *contexto de ejecución*, es válido.
* Permanece válido hasta que sale de *contexto de ejecución*.

En este punto, la relación entre los ámbitos y cuándo las variables son válidas
En este punto, la relación entre los contextos de ejecución y cuándo las variables son válidas
es similar a la de otros lenguajes de programación. Ahora construiremos sobre
este entendimiento al introducir el tipo `String`.

Expand All @@ -151,10 +149,9 @@ este entendimiento al introducir el tipo `String`.
Para ilustrar las reglas de ownership, necesitamos un tipo de datos más complejo
que los que cubrimos en la sección [“Tipos de Datos”][data-types]<!-- ignore -->
del Capítulo 3. Los tipos cubiertos anteriormente son de un tamaño conocido,
pueden almacenarse en el stack y se pueden sacar del stack cuando su ámbito
termina, y se pueden copiar rápidamente y trivialmente para crear una nueva
pueden almacenarse en el stack y se pueden sacar del stack cuando su contexto de ejecución termina, y se pueden copiar rápidamente y trivialmente para crear una nueva
instancia independiente si otra parte del código necesita usar el mismo valor
en un ámbito diferente. Pero queremos ver los datos que se almacenan en el heap
en un contexto de ejecución diferente. Pero queremos ver los datos que se almacenan en el heap
y explorar cómo Rust sabe cuándo limpiar esos datos, y el tipo `String` es un
gran ejemplo.

Expand Down Expand Up @@ -220,7 +217,7 @@ universal en los lenguajes de programación.
Sin embargo, la segunda parte es diferente. En los lenguajes con un *recolector
de basura (Garbage Collector)*, el recolector de basura rastrea y limpia la
memoria que ya no se está usando y no necesitamos pensar en ello. En la mayoría
de los lenguajes sin un GC, es nuestra responsabilidad identificar cuándo la
de los lenguajes sin un recolector de basura, es nuestra responsabilidad identificar cuándo la
memoria ya no se está usando y llamar al código para liberarla explícitamente,
tal como lo hicimos para solicitarla. Hacer esto correctamente ha sido
históricamente un problema difícil de programación. Si lo olvidamos,
Expand All @@ -229,7 +226,7 @@ inválida. Si lo hacemos dos veces, eso también es un error. Necesitamos
emparejar exactamente una `asignación` con exactamente una `liberación`.

Rust toma un camino diferente: la memoria se devuelve automáticamente una vez
que la variable que la posee sale del alcance. Aquí hay una versión de nuestro
que la variable que la posee sale del contexto de ejecución. Aquí hay una versión de nuestro
ejemplo de alcance de la Lista 4-1 usando un `String` en lugar de un literal
de cadena:

Expand All @@ -239,7 +236,7 @@ de cadena:

Hay un punto natural en el que podemos devolver la memoria que necesita nuestro
`String` al administrador: cuando `s` sale del alcance. Cuando una variable
sale del alcance, Rust llama a una función especial para nosotros. Esta
sale del contexto de ejecución, Rust llama a una función especial para nosotros. Esta
función se llama [`drop`][drop]<!-- ignore -->, y es donde el autor de `String`
puede poner el código para devolver la memoria. Rust llama a `drop`
automáticamente en la llave de cierre.
Expand Down Expand Up @@ -329,10 +326,10 @@ de ejecución si los datos en el heap fueran grandes.
<span class="caption">Figura 4-3: Otra posibilidad de lo que `s2 = s1` podría
hacer si Rust copiara también los datos del heap</span>

Anteriormente, dijimos que cuando una variable sale de ámbito, Rust llama
Anteriormente, dijimos que cuando una variable sale de contexto de ejecución, Rust llama
automáticamente a la función `drop` y limpia la memoria del heap para esa
variable. Pero la Figura 4-2 muestra que ambos punteros de datos apuntan al
mismo lugar. Esto es un problema: cuando `s2` y `s1` salen de ámbito, ambos
mismo lugar. Esto es un problema: cuando `s2` y `s1` salen de contexto de ejecución, ambos
intentarán liberar la misma memoria. Esto se conoce como un error de *doble
liberación* y es uno de los errores de seguridad de la memoria que mencionamos
anteriormente. Liberar la memoria dos veces puede conducir a la corrupción de
Expand Down Expand Up @@ -484,9 +481,9 @@ similares a las de la Lista 4-3.
<span class="caption">Lista 4-4: Transferencia de propiedad de los valores
de retorno</span>

La propiedad (ownership) de una variable sigue el mismo patrón cada vez:
La propiedad (ownership) de una variable sigue el mismo patrón cada vez:
asignar un valor a otra variable lo mueve. Cuando una variable que incluye datos
en el heap sale del alcance, el valor se limpiará por `drop` a menos que la
en el heap sale del contexto de ejecución, el valor se limpiará por `drop` a menos que la
propiedad de los datos se haya movido a otra variable.

Aunque esto funciona, tomar la propiedad y luego devolver la propiedad con cada
Expand Down
40 changes: 19 additions & 21 deletions src/ch04-02-references-and-borrowing.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Primero, ten en cuenta que todo el código de la tupla en la declaración de la
variable y el valor de retorno de la función ha desaparecido. En segundo
lugar, observe que pasamos `&s1` a `calcular_longitud` y, en su definición,
tomamos `&String` en lugar de `String`. Este signo ampersands (&) representa
*referencia*, y te permiten referirte a algún valor sin tomar la propiedad de
_referencia_, y te permiten referirte a algún valor sin tomar la propiedad de
él. La Figura 4-5 representa este concepto.

<div class="center">
Expand All @@ -45,7 +45,7 @@ Vamos a echar un vistazo más de cerca a la llamada de función aquí:
```

La sintaxis `&s1` nos permite crear una referencia que *se refiere* al valor de
`s1` pero no la posee. Porque no la posee, el valor al que apunta no se
`s1` pero sin ser el propietario. Por este motivo, el valor al que apunta no se
descartará cuando la referencia deje de usarse.

Del mismo modo, la firma de la función usa `&` para indicar que el tipo del
Expand All @@ -55,15 +55,15 @@ parámetro `s` es una referencia. Vamos a agregar algunas anotaciones
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs:here}}
```

El ámbito en el que la variable `s` es válida es el mismo que el ámbito de
El contexto de ejecución en el que la variable `s` es válida es el mismo que el contexto de ejecución de
cualquier parámetro de función, pero el valor al que apunta la referencia no se
descarta cuando `s` deja de usarse, porque `s` no tiene la propiedad. Cuando
las funciones tienen referencias como parámetros en lugar de los valores
reales, no necesitaremos devolver los valores para devolver la propiedad,
porque nunca tuvimos la propiedad.

Llamamos a la acción de crear una referencia *prestar* (borrowing en ingles).
Como en la vida real, si una persona posee algo, puedes pedir prestado.
Como en la vida real, si una persona posee algo, puedes pedir prestado.
Cuando termines, tienes que devolverlo. No lo posees.

Entonces, ¿qué pasa si intentamos modificar algo que estamos prestando? Prueba
Expand All @@ -90,7 +90,7 @@ referencias. No se nos permite modificar algo al que tenemos una referencia.

Podemos arreglar el código del Listado 4-6 para permitirnos modificar un valor
prestado con solo unos pequeños cambios que usen, en su lugar, una
*referencia mutable*:
_referencia mutable_:

<span class="filename">Nombre de archivo: src/main.rs</span>

Expand Down Expand Up @@ -120,7 +120,7 @@ Aquí está el error:
```

Este error dice que este código es inválido porque no podemos prestar `s` como
mutable más de una vez a la vez. El primer préstamo mutable está en `r1` y debe
mutable más de una vez. El primer préstamo mutable está en `r1` y debe
durar hasta que se use en el `println!`, pero entre la creación de esa
referencia mutable y su uso, intentamos crear otra referencia mutable en `r2`
que presta los mismos datos que `r1`.
Expand All @@ -130,7 +130,7 @@ mismo tiempo permite la mutación pero de una manera muy controlada. Es algo
con lo que los nuevos Rustaceans luchan porque la mayoría de los lenguajes te
permiten mutar cuando quieras. El beneficio de tener esta restricción es que
Rust puede prevenir las carreras de datos en tiempo de compilación. Una
*carrera de datos* es similar a una condición de carrera y ocurre cuando
_carrera de datos_ es similar a una condición de carrera y ocurre cuando
ocurren estos tres comportamientos:

* Dos o más punteros acceden a los mismos datos al mismo tiempo.
Expand All @@ -143,7 +143,7 @@ difíciles de diagnosticar y corregir cuando intentas rastrearlas en tiempo de
ejecución; ¡Rust evita este problema al negarse a compilar código con carreras
de datos!

Como siempre, podemos usar llaves para crear un nuevo ámbito, permitiendo
Como siempre, podemos usar llaves para crear un nuevo contexto de ejecución, permitiendo
múltiples referencias mutables, solo no *simultáneas*:

```rust
Expand Down Expand Up @@ -171,7 +171,7 @@ repentinamente debajo de ellos! Sin embargo, se permiten múltiples referencias
inmutables porque nadie que solo está leyendo los datos tiene la capacidad de
afectar la lectura de los datos de nadie más.

Tenga en cuenta que el ámbito de una referencia comienza desde donde se
Tenga en cuenta que el contexto de ejecución de una referencia comienza desde donde se
introduce y continúa hasta la última vez que se usa la referencia. Por
ejemplo, este código se compilará porque el último uso de las referencias
inmutables, el `println!`, ocurre antes de que se introduzca la referencia
Expand All @@ -181,9 +181,9 @@ mutable:
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs:here}}
```

Los ámbitos de las referencias inmutables `r1` y `r2` terminan después del
Los contextos de ejecución de las referencias inmutables `r1` y `r2` terminan después del
`println!` donde se usan por última vez, que es antes de que se cree la
referencia mutable `r3`. Estos ámbitos no se superponen, por lo que este código
referencia mutable `r3`. Estos contextos de ejecución no se superponen, por lo que este código
está permitido: ¡el compilador puede decir que la referencia ya no se está
utilizando en un punto antes del final del ámbito!

Expand All @@ -200,7 +200,7 @@ un puntero que hace referencia a una ubicación en la memoria que puede haber
sido otorgada a otra persona, al liberar algo de memoria mientras se preserva
un puntero a esa memoria. En Rust, por el contrario, el compilador garantiza
que las referencias nunca serán referencias colgantes: si tiene una referencia
a algún dato, el compilador asegurará que los datos no salgan de ámbito antes
a algún dato, el compilador asegurará que los datos no salgan de contexto de ejecución antes
de que la referencia a los datos lo haga.

Intentemos crear una referencia colgante para ver cómo Rust los previene con un
Expand All @@ -221,8 +221,7 @@ Aquí está el error:
```

Este mensaje de error se refiere a una característica que aún no hemos cubierto:
los tiempos de vida. Discutiremos los tiempos de vida en detalle en el Capítulo
10. Pero, si ignora las partes sobre los tiempos de vida, el mensaje contiene la
los tiempos de vida. Discutiremos los tiempos de vida en detalle en el Capítulo 10. Pero, si ignora las partes sobre los tiempos de vida, el mensaje contiene la
clave para saber por qué este código es un problema:

```text
Expand All @@ -232,16 +231,15 @@ for it to be borrowed from

Se traduciría algo así como:

```text
el tipo de retorno de la función contiene un valor prestado, pero no hay valor
para que se preste
```
````text
el tipo de retorno de la función contiene un valor prestado, pero no hay ningún valor
que pueda ser prestado```
<span class="filename">Nombre de archivo: src/main.rs</span>
```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}}
```
````

Porque `s` se crea dentro de `colgar`, cuando el código de `colgar` finaliza,
`s` se desalocará. Pero intentamos devolver una referencia a él. Eso significa
Expand All @@ -260,8 +258,8 @@ Esto funciona sin problemas. La propiedad se mueve fuera y nada se desaloca.

Repasemos lo que hemos discutido sobre las referencias:

* En cualquier momento dado, puedes tener *o bien* una referencia mutable *o*
- En cualquier momento dado, puedes tener *o bien* una referencia mutable *o*
cualquier número de referencias inmutables.
* Las referencias deben ser siempre válidas.
- Las referencias deben ser siempre válidas.

A continuación, veremos un tipo diferente de referencia: los slices.
Loading

0 comments on commit 7fbec29

Please sign in to comment.