4 |
5 | # Ruta de Aprendizaje de Rust en Español
6 | Esta es la ruta de Aprendizaje de Rust hecho por la comunidad de [RustLangES](https://rustlang-es.org)
7 |
8 | ## Setup
9 |
10 | ```bash
11 | # bun
12 | bun install
13 | ```
14 |
15 | ## Development Server
16 |
17 | ```bash
18 | # bun
19 | bun run dev
20 | ```
21 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
29 |
53 |
54 |
79 |
--------------------------------------------------------------------------------
/content/1.introduction/0.index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Introducción a Rust'
3 | description: 'Introducción a Rust: El Lenguaje del Futuro en Programación de Sistemas'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 320
10 | y: 100
11 | sourcePosition:
12 | rust: 'top'
13 | targetPosition:
14 | basic: 'bottom'
15 | why-rust: 'right'
16 | rust-channels: 'right'
17 | environment: 'right'
18 | externalLinks:
19 | - name: 'Web Oficial'
20 | english: true
21 | link: 'https://rust-lang.org'
22 | - name: 'Hicimos el sitio web de nuestra boda en Angular y Rust'
23 | english: false
24 | link: 'https://blog.rustlang-es.org/articles/hicimos-el-sitio-web-de-nuestra-boda-en-angular-y-rust-pk8'
25 | ---
26 | ## Introducción a Rust: El Lenguaje del Futuro en Programación de Sistemas
27 |
28 | En el vasto universo de los lenguajes de programación, Rust ha emergido como una estrella en ascenso, atrayendo la atención de desarrolladores de todo el mundo por su enfoque único en la seguridad y el rendimiento. Rust no solo promete, sino que cumple con la difícil tarea de ofrecer un control de bajo nivel sin sacrificar la seguridad y la facilidad de uso. En este post, exploraremos qué hace que Rust sea tan especial y por qué deberías considerarlo para tus próximos proyectos.
29 |
30 | ### ¿Qué es Rust?
31 |
32 | Rust es un lenguaje de programación de sistemas que fue desarrollado por Mozilla Research, con su primera versión estable lanzada en 2015. A diferencia de muchos lenguajes modernos que priorizan la productividad y la simplicidad en detrimento de la eficiencia y el control, Rust busca ofrecer lo mejor de ambos mundos. Está diseñado para ser seguro, concurrente y práctico, permitiendo a los desarrolladores escribir código de bajo nivel sin temor a errores comunes como los desbordamientos de búfer y las condiciones de carrera.
33 |
34 | ### Características Clave de Rust
35 |
36 | 1. **Seguridad de Memoria sin Recolección de Basura:**
37 | Una de las características más distintivas de Rust es su enfoque en la seguridad de la memoria. A diferencia de otros lenguajes que utilizan un recolector de basura para gestionar la memoria, Rust emplea un sistema de propiedad y préstamo. Este sistema permite que el compilador gestione la memoria de manera segura y eficiente, previniendo errores comunes como los punteros colgantes y las fugas de memoria.
38 |
39 | 2. **Control y Rendimiento:**
40 | Rust proporciona un control de bajo nivel similar al de C y C++, permitiendo a los desarrolladores optimizar su código para un rendimiento máximo. Esto lo hace ideal para aplicaciones donde el rendimiento es crítico, como los motores de juegos, los sistemas embebidos y las aplicaciones de tiempo real.
41 |
42 | 3. **Concurrencia sin Miedo:**
43 | La concurrencia es uno de los aspectos más complejos y propensos a errores en la programación. Rust aborda este problema con su sistema de tipos y el análisis estático en tiempo de compilación, lo que ayuda a evitar las condiciones de carrera y otros errores de concurrencia. Su modelo de propiedad garantiza que dos hilos no puedan acceder al mismo recurso mutable simultáneamente, asegurando así una concurrencia segura.
44 |
45 | 4. **Ecosistema y Herramientas:**
46 | Rust cuenta con un ecosistema robusto y en constante crecimiento. Herramientas como Cargo, el gestor de paquetes y compilador de Rust, facilitan la gestión de dependencias y la compilación del código. Además, la comunidad de Rust es conocida por ser extremadamente acogedora y activa, lo que hace que aprender y resolver problemas sea más accesible.
47 |
48 | ### ¿Por Qué Elegir Rust?
49 |
50 | 1. **Proyectos Críticos de Alto Rendimiento:**
51 | Si estás trabajando en proyectos donde el rendimiento y la eficiencia son cruciales, como sistemas operativos, navegadores web o motores de juegos, Rust es una excelente opción. Su capacidad para ofrecer un control de bajo nivel sin sacrificar la seguridad lo hace ideal para estos entornos exigentes.
52 |
53 | 2. **Seguridad en Aplicaciones:**
54 | Para aplicaciones donde la seguridad es una prioridad, Rust proporciona una base sólida para prevenir vulnerabilidades comunes. Su sistema de tipos riguroso y su énfasis en la seguridad de la memoria ayudan a evitar errores que pueden ser explotados en ataques de seguridad.
55 |
56 | 3. **Desarrollo Moderno:**
57 | Rust no solo se trata de rendimiento y seguridad; también está diseñado para ser agradable de usar. Su sintaxis moderna y expresiva, junto con herramientas avanzadas, hacen que el desarrollo sea más eficiente y menos propenso a errores.
58 |
59 | ### Conclusión
60 |
61 | Rust está cambiando la forma en que pensamos sobre la programación de sistemas. Su capacidad para ofrecer seguridad y rendimiento sin compromisos lo convierte en una herramienta poderosa para los desarrolladores modernos. Si aún no has explorado Rust, ahora es el momento de sumergirte y descubrir cómo puede transformar tus proyectos. Con una comunidad en crecimiento y un ecosistema robusto, Rust está preparado para ser un pilar en el desarrollo de software del futuro.
62 |
--------------------------------------------------------------------------------
/content/1.introduction/2.rust-channels.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Stable, Beta, Nightly. ¿Que es esto?'
3 | description: 'Stable, Beta, Nightly. Los canales de distribucion y versiones de Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 620
10 | y: 140
11 | sourcePosition:
12 | introduction: 'left'
13 | externalLinks:
14 | - name: 'Web Oficial'
15 | english: true
16 | link: 'https://rust-lang.org'
17 | - name: 'Enlace de Referencia'
18 | english: true
19 | link: 'https://rust-lang.github.io/rustup/concepts/channels.html'
20 | ---
21 | ## Stable, Beta, Nightly. ¿Que es esto?
22 |
23 | Rust es conocido por su enfoque en la seguridad, el rendimiento y la confiabilidad, y parte de lo que hace a Rust tan robusto es su cuidadoso ciclo de lanzamiento. Para mantener el equilibrio entre la estabilidad y la innovación, Rust se distribuye a través de tres canales diferentes: Stable, Beta y Nightly. En este post, exploraremos qué significa cada uno de estos canales y cuándo deberías usarlos.
24 |
25 | ### Canal Stable: Seguridad y Confiabilidad
26 |
27 | El canal Stable es la versión más importante de Rust para la mayoría de los desarrolladores. Como su nombre indica, las versiones en este canal son las más estables y han pasado por un riguroso proceso de prueba. Aquí están las características clave del canal Stable:
28 |
29 | - **Lanzamientos Regulares:** Las versiones estables de Rust se lanzan cada seis semanas, lo que proporciona un flujo constante de mejoras y correcciones de errores.
30 | - **Compatibilidad Garantizada:** El canal Stable garantiza la compatibilidad hacia atrás, lo que significa que el código que compila en una versión estable continuará compilando en versiones futuras.
31 | - **Seguridad y Confiabilidad:** Dado que estas versiones han sido exhaustivamente probadas, son ideales para proyectos de producción donde la estabilidad es crucial.
32 |
33 | **Cuándo usar Stable:** Siempre que estés trabajando en un proyecto de producción o necesites asegurarte de que tu código funcione de manera confiable y segura, debes usar el canal Stable.
34 |
35 | ### Canal Beta: Probando lo Nuevo
36 |
37 | El canal Beta de Rust es una vista previa de lo que vendrá en la próxima versión estable. Esta versión se congela dos semanas antes del lanzamiento estable, y se centra en la corrección de errores y la estabilización de nuevas características.
38 |
39 | - **Vista Previa de Nuevas Características:** El canal Beta te permite probar las nuevas características que se incluirán en la próxima versión estable.
40 | - **Corrección de Errores:** Aunque es menos estable que el canal Stable, el canal Beta todavía es bastante fiable y se utiliza para encontrar y corregir errores antes del lanzamiento oficial.
41 |
42 | **Cuándo usar Beta:** Si quieres estar al tanto de las próximas características y contribuir a la detección de errores, usar el canal Beta es una excelente opción. Es ideal para pruebas y para preparar tu código para futuros lanzamientos estables.
43 |
44 | ### Canal Nightly: Innovación y Experimentación
45 |
46 | El canal Nightly es la vanguardia del desarrollo de Rust. Las versiones Nightly se generan cada noche con las últimas características y correcciones de errores que aún no están listas para el canal Beta.
47 |
48 | - **Acceso a Características Experimentales:** El canal Nightly te da acceso a las características más nuevas y experimentales, incluyendo aquellas que aún están en fase de pruebas.
49 | - **Sin Garantías de Estabilidad:** Dado que estas versiones son las menos probadas, pueden contener errores y no se garantiza que sean estables.
50 |
51 | **Cuándo usar Nightly:** Si eres un desarrollador que quiere experimentar con las últimas innovaciones y no te importa lidiar con posibles inestabilidades, el canal Nightly es para ti. Es especialmente útil para contribuyentes de Rust y aquellos que necesitan características específicas que aún no están disponibles en los canales Beta o Stable.
52 |
53 | ### Conclusión
54 |
55 | El sistema de canales de Rust permite a los desarrolladores elegir el equilibrio adecuado entre estabilidad e innovación para sus necesidades específicas. El canal Stable ofrece seguridad y confiabilidad para proyectos de producción, el canal Beta proporciona una vista previa de las próximas características, y el canal Nightly permite a los desarrolladores experimentar con las últimas novedades del lenguaje.
56 |
57 | Al comprender y utilizar estos canales de manera efectiva, puedes maximizar tu productividad y mantener tu códigobase actualizada y segura. ¡Elige el canal que mejor se adapte a tus necesidades y empieza a explorar todo lo que Rust tiene para ofrecer!
58 |
--------------------------------------------------------------------------------
/content/1.introduction/3.environment.yml:
--------------------------------------------------------------------------------
1 | title: 'Configura tu Entorno'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: 620
8 | y: 200
9 | width: 320
10 | sourcePosition:
11 | introduction: 'left'
12 |
--------------------------------------------------------------------------------
/content/1.introduction/4.install-rust.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Instala Rust'
3 | description: 'Instalación de Rust con Rustup: Una Guía Rápida en pocos minutos'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 620
10 | y: 240
11 | width: 320
12 | externalLinks:
13 | - name: 'Web Oficial de Rustup'
14 | english: true
15 | link: 'https://rustup.rs'
16 | ---
17 | ## Instalación de Rust con Rustup: Una Guía Rápida
18 |
19 | Rust es un lenguaje de programación que ha ganado popularidad rápidamente debido a su enfoque en la seguridad, el rendimiento y la facilidad de uso. Si estás interesado en comenzar a desarrollar con Rust, el primer paso es instalarlo en tu sistema. La forma más recomendada y sencilla de instalar Rust es usando Rustup, una herramienta de línea de comandos para gestionar tus instalaciones de Rust. En este post, te guiaremos a través del proceso de instalación de Rust utilizando Rustup.
20 |
21 | ### ¿Qué es Rustup?
22 |
23 | Rustup es una herramienta de instalación y gestión de Rust que facilita la configuración de múltiples versiones de Rust y la administración de diferentes toolchains (conjuntos de herramientas) en tu sistema. Con Rustup, puedes acceder fácilmente a los canales Stable, Beta y Nightly de Rust y cambiar entre ellos según sea necesario.
24 |
25 | ### Pasos para Instalar Rust con Rustup
26 |
27 | ### Instalación en Windows
28 |
29 | #### 1. Descargar e Instalar Rustup
30 |
31 | 1. Visita [rustup.rs](https://rustup.rs/) en tu navegador.
32 | 2. Haz clic en el enlace de instalación para Windows. Esto descargará un archivo ejecutable `rustup-init.exe`.
33 | 3. Ejecuta el archivo descargado. Aparecerá una ventana de terminal.
34 |
35 | #### 2. Ejecutar el Instalador
36 |
37 | 1. En la ventana de terminal, se te pedirá que confirmes la instalación. Pulsa `1` y luego `Enter` para proceder con la instalación predeterminada.
38 | 2. El instalador configurará Rust y Rustup en tu sistema.
39 |
40 | #### 3. Configurar el Entorno
41 |
42 | El instalador generalmente configura el entorno de manera automática. Para verificar, abre una nueva ventana de terminal (PowerShell o cmd) y ejecuta:
43 |
44 | ```sh
45 | rustc --version
46 | ```
47 |
48 | Si ves la versión de Rust, la instalación se ha realizado correctamente.
49 |
50 | ### Instalación en Linux
51 |
52 | #### 1. Descargar e Instalar Rustup
53 |
54 | Abre una terminal y ejecuta el siguiente comando:
55 |
56 | ```sh
57 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
58 | ```
59 |
60 | #### 2. Ejecutar el Instalador
61 |
62 | Sigue las instrucciones en la terminal. Acepta las opciones predeterminadas presionando `Enter`.
63 |
64 | #### 3. Configurar el Entorno
65 |
66 | Añade Rust a tu PATH ejecutando:
67 |
68 | ```sh
69 | source $HOME/.cargo/env
70 | ```
71 |
72 | También puedes añadir esta línea al final de tu archivo de configuración de shell (`.bashrc`, `.zshrc`, etc.) para que se ejecute automáticamente al abrir una nueva terminal.
73 |
74 | Para verificar la instalación, ejecuta:
75 |
76 | ```sh
77 | rustc --version
78 | ```
79 |
80 | Si ves la versión de Rust, la instalación ha sido exitosa.
81 |
82 | ### Instalación en macOS
83 |
84 | #### 1. Descargar e Instalar Rustup
85 |
86 | Abre una terminal y ejecuta el siguiente comando:
87 |
88 | ```sh
89 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
90 | ```
91 |
92 | #### 2. Ejecutar el Instalador
93 |
94 | Sigue las instrucciones en la terminal. Acepta las opciones predeterminadas presionando `Enter`.
95 |
96 | #### 3. Configurar el Entorno
97 |
98 | Añade Rust a tu PATH ejecutando:
99 |
100 | ```sh
101 | source $HOME/.cargo/env
102 | ```
103 |
104 | Para asegurarte de que este paso se realice automáticamente al abrir una nueva terminal, añade esta línea al final de tu archivo de configuración de shell (`.bash_profile`, `.zshrc`, etc.).
105 |
106 | Para verificar la instalación, ejecuta:
107 |
108 | ```sh
109 | rustc --version
110 | ```
111 |
112 | Si ves la versión de Rust, la instalación ha sido exitosa.
113 |
114 |
115 | #### 2. Configurar tu Entorno
116 |
117 | Una vez que Rustup haya terminado de instalarse, necesitas asegurarte de que tu entorno de línea de comandos esté configurado para usar Rust. Rustup te indicará agregar la ruta de Rust a tu archivo de configuración de shell (`.bashrc`, `.zshrc`, etc.). Puedes hacerlo manualmente o dejar que Rustup lo haga automáticamente.
118 |
119 | Si decides hacerlo manualmente, añade la siguiente línea al final de tu archivo de configuración de shell:
120 |
121 | ```sh
122 | source $HOME/.cargo/env
123 | ```
124 |
125 | Después de hacer esto, asegúrate de recargar tu archivo de configuración ejecutando `source ~/.bashrc` o `source ~/.zshrc`, dependiendo de tu shell.
126 |
127 | #### 3. Verificar la Instalación
128 |
129 | Para verificar que Rust se ha instalado correctamente, puedes ejecutar:
130 |
131 | ```sh
132 | rustc --version
133 | ```
134 |
135 | Este comando debería mostrar la versión de Rust que tienes instalada. Si ves algo similar a `rustc 1.XX.X (XXXXX YYYY-MM-DD)`, ¡felicidades, ya tienes Rust instalado en tu sistema!
136 |
137 | #### 4. Usar los Canales de Rust
138 |
139 | Una de las ventajas de usar Rustup es la facilidad con la que puedes cambiar entre diferentes versiones de Rust. Por defecto, Rustup instala la versión Stable. Sin embargo, puedes instalar y usar las versiones Beta y Nightly fácilmente.
140 |
141 | Para instalar y usar el canal Beta:
142 |
143 | ```sh
144 | rustup install beta
145 | rustup default beta
146 | ```
147 |
148 | Para instalar y usar el canal Nightly:
149 |
150 | ```sh
151 | rustup install nightly
152 | rustup default nightly
153 | ```
154 |
155 | Si en algún momento deseas volver al canal Stable, puedes hacerlo con:
156 |
157 | ```sh
158 | rustup default stable
159 | ```
160 |
161 | #### 5. Actualizar Rust
162 |
163 | Mantener tu instalación de Rust actualizada es fácil con Rustup. Simplemente ejecuta:
164 |
165 | ```sh
166 | rustup update
167 | ```
168 |
169 | Este comando actualizará Rustup y todos los toolchains instalados a sus versiones más recientes.
170 |
171 | ### Conclusión
172 |
173 | Instalar Rust usando Rustup es un proceso sencillo que te permitirá empezar a desarrollar en Rust rápidamente. Con Rustup, puedes gestionar fácilmente las versiones de Rust y asegurarte de que siempre tienes acceso a las últimas características y mejoras. Ahora que tienes Rust instalado, estás listo para explorar todo lo que este poderoso lenguaje tiene para ofrecer. ¡Feliz codificación!
174 |
--------------------------------------------------------------------------------
/content/1.introduction/6.first-program.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Tu Primer Programa'
3 | description: 'Escribiendo Tu Primer Programa en Rust: Una Guía Paso a Paso'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 620
10 | y: 320
11 | width: 320
12 | externalLinks:
13 | - name: '¡Hola, mundo!'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch01-02-hello-world'
16 | - name: '¡Hola, Cargo!'
17 | english: false
18 | link: 'https://book.rustlang-es.org/ch01-03-hello-cargo'
19 | ---
20 | ## Escribiendo Tu Primer Programa en Rust: Una Guía Paso a Paso
21 |
22 | Rust es un lenguaje de programación moderno que se destaca por su seguridad y rendimiento. Si estás listo para dar tus primeros pasos en Rust, esta guía te ayudará a configurar tu entorno y a escribir tu primer programa sencillo. Vamos a crear un proyecto llamado "hola_mundo" utilizando Cargo, la herramienta de gestión de proyectos de Rust.
23 |
24 | ### ¿Qué es Cargo?
25 |
26 | Cargo es la navaja suiza de Rust. Permite gestionar proyectos, probar código, manejar dependencias, y mucho más. Es una herramienta esencial para cualquier desarrollador de Rust.
27 |
28 | ### Paso 1: Crear un Proyecto con Cargo
29 |
30 | Para crear tu primer proyecto con Cargo, abre una terminal y ejecuta el siguiente comando:
31 |
32 | ```sh
33 | cargo new hola_mundo
34 | ```
35 |
36 | Este comando creará un nuevo directorio y un proyecto llamado "hola_mundo". Cargo generará los archivos necesarios y un directorio para ti. Vamos a explorar lo que ha creado.
37 |
38 | ### Paso 2: Explorar la Estructura del Proyecto
39 |
40 | Navega al directorio del proyecto y lista los archivos:
41 |
42 | ```sh
43 | cd hola_mundo
44 | ls
45 | ```
46 |
47 | Deberías ver los siguientes elementos:
48 |
49 | - `Cargo.toml`: Archivo de configuración de Cargo.
50 | - `src`: Directorio de código fuente.
51 | - `main.rs`: Archivo principal de Rust que contiene el punto de entrada del programa.
52 |
53 | Cargo también inicializa un nuevo repositorio Git junto con un archivo `.gitignore`.
54 |
55 | ### Paso 3: Entender el Código Generado
56 |
57 | Abre el archivo `src/main.rs` en tu editor de texto favorito. Verás el siguiente código:
58 |
59 | ```rs
60 | fn main() {
61 | println!("Hello, world!");
62 | }
63 | ```
64 |
65 | Vamos a desglosar este código línea por línea.
66 |
67 | #### La Función `main`
68 |
69 | ```rs
70 | fn main() {
71 |
72 | }
73 | ```
74 |
75 | Estas líneas definen una función llamada `main`. La función `main` es especial: siempre es el primer código que se ejecuta en cada programa ejecutable de Rust. Aquí, la primera línea declara una función llamada `main` que no tiene parámetros y no devuelve nada. Si hubiera parámetros, irían dentro de los paréntesis `()`.
76 |
77 | El cuerpo de la función está envuelto en `{}`. Rust requiere llaves alrededor de todos los cuerpos de función. Es buena costumbre colocar la llave de apertura en la misma línea que la declaración de la función, agregando un espacio entre ambos.
78 |
79 | #### El Cuerpo de la Función `main`
80 |
81 | ```rs
82 | println!("Hello, world!");
83 | ```
84 |
85 | Esta línea hace todo el trabajo en este pequeño programa: imprime texto en la pantalla.
86 |
87 | `println!` llama a una macro de Rust. Si hubiéramos llamado a una función en su lugar, habríamos ingresado `println` (sin el `!`). Hablaremos de macros en Rust más adelante. Por ahora, solo necesitas saber que usar un `!` significa que estamos llamando a una macro en lugar de una función normal y que las macros no siempre siguen las mismas reglas que las funciones.
88 |
89 | Terminamos la línea con un punto y coma (`;`), lo que indica que esta expresión ha terminado y la siguiente está lista para comenzar. La mayoría de las líneas de código de Rust terminan con un punto y coma.
90 |
91 | ### Paso 4: Ejecutar el Programa
92 |
93 | Ahora que entendemos el código, es hora de ejecutarlo. En la terminal, ejecuta:
94 |
95 | ```sh
96 | cargo run
97 | ```
98 |
99 | Deberías ver una salida similar a esta:
100 |
101 | ```sh
102 | $ cargo run
103 | Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
104 | Running `target/debug/hola_mundo`
105 | Hello, world!
106 | ```
107 |
108 | Si todo funciona correctamente, ¡felicitaciones! Has escrito y ejecutado tu primer programa en Rust.
109 |
--------------------------------------------------------------------------------
/content/2.basic/0.index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Aprende lo Básico'
3 | description: ''
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -300
10 | y: 300
11 | sourcePosition:
12 | introduction: 'top'
13 | targetPosition:
14 | error-handling: 'bottom'
15 | ---
16 | # Titulo
17 |
--------------------------------------------------------------------------------
/content/2.basic/1.syntax.yml:
--------------------------------------------------------------------------------
1 | title: 'Sintaxis Básica'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: -700
8 | y: 200
9 | width: 320
10 | align: 'center'
11 | sourcePosition:
12 | none: 'top'
13 | targetPosition:
14 | basic: 'right'
15 |
--------------------------------------------------------------------------------
/content/2.basic/10.transfer-ownership.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Transferencia de Ownership'
3 | description: 'Transferencias de Ownership en Rust: Un Cambio Fundamental en la Gestión de Recursos'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 600
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch04-01-what-is-ownership?highlight=transferencia#valores-de-retorno-y-alcance'
16 | ---
17 | ## Transferencias de Ownership en Rust: Un Cambio Fundamental en la Gestión de Recursos
18 |
19 | ### Introducción
20 |
21 | Rust es un lenguaje de programación que ha capturado la atención de desarrolladores por su enfoque único en la seguridad y el rendimiento. Un aspecto crucial que diferencia a Rust de otros lenguajes es su sistema de **ownership (propiedad)**. La **transferencia de ownership** es una característica clave de este sistema, que permite manejar la memoria de manera segura y eficiente. En este post, exploraremos en detalle cómo funcionan las transferencias de ownership en Rust y por qué son fundamentales para el paradigma de gestión de recursos del lenguaje.
22 |
23 | ### Concepto de Ownership en Rust
24 |
25 | En Rust, cada valor en el programa tiene un único propietario. Esta variable propietaria es responsable de liberar los recursos asociados cuando sale del alcance (scope). Este enfoque asegura que no haya duplicaciones de liberación de memoria ni fugas de memoria, proporcionando una seguridad robusta en tiempo de compilación.
26 |
27 | ### ¿Qué es la Transferencia de Ownership?
28 |
29 | La transferencia de ownership ocurre cuando un valor se mueve de una variable a otra, transfiriendo con ello la responsabilidad de gestionar ese valor. En Rust, esto se conoce como "mover" (move). Una vez que un valor ha sido movido, la variable original ya no puede usarse para acceder al valor, evitando así accesos inválidos a memoria.
30 |
31 | ### Ejemplo de Transferencia de Ownership
32 |
33 | Consideremos el siguiente ejemplo para ilustrar cómo funciona la transferencia de ownership:
34 |
35 | ```rust
36 | fn main() {
37 | let s1 = String::from("Hello");
38 | let s2 = s1; // s1 se mueve a s2
39 | println!("{}", s2); // Esto funciona
40 | // println!("{}", s1); // Esto causaría un error de compilación
41 | }
42 | ```
43 |
44 | En este código, la cadena `"Hello"` se asigna a `s1`. Luego, `s1` se mueve a `s2`, transfiriendo la propiedad. Intentar usar `s1` después de la transferencia causará un error de compilación porque `s1` ya no es válido.
45 |
46 | ### Transferencias de Ownership en Funciones
47 |
48 | Las transferencias de ownership también ocurren cuando se pasan parámetros a funciones y cuando se retornan valores desde funciones. Veamos un ejemplo:
49 |
50 | ```rust
51 | fn main() {
52 | let s1 = String::from("Hello");
53 | takes_ownership(s1); // s1 se mueve a la función
54 | // println!("{}", s1); // Esto causaría un error de compilación
55 | }
56 |
57 | fn takes_ownership(some_string: String) {
58 | println!("{}", some_string);
59 | }
60 | ```
61 |
62 | En este caso, `s1` se mueve a la función `takes_ownership`, transfiriendo la propiedad. Una vez que `s1` ha sido movido, ya no puede usarse en `main`.
63 |
64 | ### Retorno de Valores y Ownership
65 |
66 | Rust también permite transferir ownership cuando se retorna un valor desde una función:
67 |
68 | ```rust
69 | fn main() {
70 | let s1 = gives_ownership();
71 | println!("{}", s1);
72 | }
73 |
74 | fn gives_ownership() -> String {
75 | let some_string = String::from("Hello");
76 | some_string // se mueve al llamador
77 | }
78 | ```
79 |
80 | Aquí, la función `gives_ownership` crea una cadena y luego la retorna, transfiriendo la propiedad al llamador.
81 |
82 | ### Clonación: Copias en Lugar de Movimientos
83 |
84 | En algunos casos, es posible que desees hacer una copia en lugar de mover un valor. Rust permite esto mediante el método `clone`, que crea una copia profunda del valor:
85 |
86 | ```rust
87 | fn main() {
88 | let s1 = String::from("Hello");
89 | let s2 = s1.clone(); // Se clona s1
90 | println!("{}", s1); // Esto funciona
91 | println!("{}", s2); // Esto también funciona
92 | }
93 | ```
94 |
95 | ### Beneficios de la Transferencia de Ownership
96 |
97 | 1. **Seguridad en Tiempo de Compilación:** Al transferir ownership de manera explícita, Rust asegura que no haya accesos inválidos a memoria ni liberaciones duplicadas.
98 |
99 | 2. **Control de Recursos:** La transferencia de ownership proporciona un control preciso sobre la vida útil de los recursos, lo que es crucial para el rendimiento y la eficiencia.
100 |
101 | 3. **Prevención de Errores Comunes:** Errores como las fugas de memoria y las condiciones de carrera se evitan gracias a las reglas de ownership y borrowing.
102 |
103 | ### Conclusión
104 |
105 | La transferencia de ownership es un concepto central en Rust que redefine cómo gestionamos la memoria y los recursos. Al asegurar que cada valor tenga un único propietario y al validar las transferencias de ownership en tiempo de compilación, Rust proporciona un nivel de seguridad y eficiencia que es difícil de alcanzar en otros lenguajes. Aunque puede requerir un cambio de mentalidad para los desarrolladores acostumbrados a otros paradigmas, los beneficios que ofrece en términos de seguridad y control hacen que valga la pena adoptar este enfoque.
106 |
--------------------------------------------------------------------------------
/content/2.basic/14.primitive-types.yml:
--------------------------------------------------------------------------------
1 | title: 'Tipos de Datos Primitivos'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: -50
8 | y: 240
9 | width: 320
10 | align: 'left'
11 | sourcePosition:
12 | none: 'top'
13 | targetPosition:
14 | basic: 'left'
15 |
--------------------------------------------------------------------------------
/content/2.basic/15.boolean.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'bool'
3 | description: 'El Tipo Booleano en Rust: Características, Operaciones y Usos Prácticos'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -50
10 | y: 280
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types#el-tipo-booleano'
16 | - name: 'Libro de Referencia Rust'
17 | english: true
18 | link: 'https://doc.rust-lang.org/reference/types/boolean.html'
19 | ---
20 | ## El Tipo Booleano en Rust: Características, Operaciones y Usos Prácticos
21 |
22 | El tipo `bool` en Rust representa un valor booleano, que puede ser verdadero (`true`) o falso (`false`). Es uno de los tipos más fundamentales en cualquier lenguaje de programación y se utiliza ampliamente en Rust para controlar el flujo de ejecución y tomar decisiones basadas en condiciones. En este post, exploraremos las características principales del tipo `bool`, su funcionamiento en memoria, y algunos usos prácticos, incluyendo operaciones lógicas y comparaciones.
23 |
24 | ### Características Principales del Tipo `bool`
25 |
26 | 1. **Valores:** El tipo `bool` puede tener solo dos valores: `true` o `false`.
27 |
28 | 2. **Tamaño en Memoria:** En Rust, un valor `bool` ocupa un solo byte en la memoria. Aunque solo necesita un bit para almacenar `true` o `false`, utilizar un byte completo simplifica la alineación en memoria y la manipulación de datos a nivel de hardware.
29 |
30 | 3. **Operaciones Lógicas:** Los valores `bool` se pueden combinar mediante operaciones lógicas como AND (`&&`), OR (`||`), y NOT (`!`). Estas operaciones son fundamentales para la evaluación de expresiones booleanas.
31 |
32 | 4. **Comparaciones:** Los valores `bool` se pueden comparar utilizando los operadores de comparación (`==`, `!=`, `<`, `>`, `<=`, `>=`). Estas comparaciones ayudan a evaluar la igualdad o el orden relativo de los valores booleanos.
33 |
34 | 5. **Uso en Expresiones Condicionales:** Los valores `bool` se utilizan comúnmente en expresiones condicionales como las declaraciones `if`, `while`, y `for` para controlar el flujo de ejecución del programa.
35 |
36 | ### Ejemplos de Uso del Tipo `bool` en Rust
37 |
38 | #### 1. Declaraciones Condicionales
39 |
40 | ```rust
41 | let es_mayor_de_edad = true;
42 |
43 | if es_mayor_de_edad {
44 | println!("Puede comprar alcohol");
45 | } else {
46 | println!("No puede comprar alcohol");
47 | }
48 | ```
49 |
50 | **Gráfico 1: Uso de `bool` en Declaraciones Condicionales**
51 |
52 | ```plaintext
53 | let es_mayor_de_edad = true;
54 | |
55 | v
56 | +------------+
57 | | true |
58 | +------------+
59 | |
60 | v
61 | if es_mayor_de_edad {
62 | println!("Puede comprar alcohol");
63 | } else {
64 | println!("No puede comprar alcohol");
65 | }
66 | ```
67 |
68 | #### 2. Operaciones Lógicas
69 |
70 | ```rust
71 | let tiene_licencia = true;
72 | let tiene_coche = false;
73 |
74 | if tiene_licencia && tiene_coche {
75 | println!("Puede conducir");
76 | } else {
77 | println!("No puede conducir");
78 | }
79 | ```
80 |
81 | **Gráfico 2: Operaciones Lógicas con `bool`**
82 |
83 | ```plaintext
84 | let tiene_licencia = true;
85 | let tiene_coche = false;
86 | | |
87 | v v
88 | +------------+ +------------+
89 | | true | | false |
90 | +------------+ +------------+
91 | | |
92 | +------AND-------+
93 | |
94 | v
95 | if tiene_licencia && tiene_coche {
96 | println!("Puede conducir");
97 | } else {
98 | println!("No puede conducir");
99 | }
100 | ```
101 |
102 | #### 3. Comparaciones
103 |
104 | ```rust
105 | let a = true;
106 | let b = false;
107 |
108 | if a != b {
109 | println!("Los valores son diferentes");
110 | } else {
111 | println!("Los valores son iguales");
112 | }
113 | ```
114 |
115 | **Gráfico 3: Comparaciones con `bool`**
116 |
117 | ```plaintext
118 | let a = true;
119 | let b = false;
120 | | |
121 | v v
122 | +------------+ +------------+
123 | | true | | false |
124 | +------------+ +------------+
125 | | |
126 | +----!=--+
127 | |
128 | v
129 | if a != b {
130 | println!("Los valores son diferentes");
131 | } else {
132 | println!("Los valores son iguales");
133 | }
134 | ```
135 |
136 | ### Métodos Más Utilizados
137 |
138 | En Rust, el tipo `bool` es primitivo y no tiene métodos específicos asociados. Sin embargo, se pueden utilizar funciones y métodos proporcionados por Rust para trabajar con valores booleanos. Algunas de las funciones y métodos más comunes son:
139 |
140 | - **true y false:** Valores de tipo `bool`.
141 |
142 | - **not():** Método utilizado para negar un valor booleano.
143 |
144 | - **and():** Método utilizado para realizar una operación lógica AND entre dos valores booleanos.
145 |
146 | - **or():** Método utilizado para realizar una operación lógica OR entre dos valores booleanos.
147 |
148 | #### Ejemplo de Métodos Booleanos
149 |
150 | ```rust
151 | fn main() {
152 | if false.and(true).or(false) {
153 | println!("La expresión es verdadera");
154 | } else {
155 | println!("La expresión es falsa");
156 | }
157 | }
158 | ```
159 |
160 | **Gráfico 4: Métodos Booleanos**
161 |
162 | ```plaintext
163 | false.and(true) --> false
164 | false.or(false) --> false
165 |
166 | if false.and(true).or(false) {
167 | println!("La expresión es verdadera");
168 | } else {
169 | println!("La expresión es falsa");
170 | }
171 | ```
172 |
173 | ### Conclusión
174 |
175 | El tipo `bool` en Rust, aunque simple, es esencial para el control del flujo de ejecución y la toma de decisiones en los programas. Su implementación del trait `Copy` permite copiar valores booleanos de manera eficiente, y su representación en memoria es directa y eficaz. Además, su uso en operaciones lógicas y comparaciones es fundamental para evaluar y combinar condiciones. Comprender y utilizar correctamente el tipo `bool` nos ayuda a escribir código Rust más seguro y eficiente.
176 |
--------------------------------------------------------------------------------
/content/2.basic/16.float.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'f32, f64'
3 | description: 'Los Tipos de Punto Flotante `f32` y `f64` en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 24
10 | y: 280
11 | width: 130
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types#tipos-de-punto-flotante'
16 | ---
17 | ## Los Tipos de Punto Flotante `f32` y `f64` en Rust
18 |
19 | En Rust, los tipos `f32` y `f64` son tipos de datos de punto flotante que representan números de coma flotante de precisión simple y doble, respectivamente. Estos tipos son esenciales para realizar cálculos numéricos que requieren decimales, y cada uno tiene sus propias características y usos. En este post, exploraremos las diferencias entre `f32` y `f64`, sus aplicaciones típicas y algunos ejemplos de uso en Rust.
20 |
21 | ### Diferencias entre `f32` y `f64`
22 |
23 | #### 1. Precisión
24 |
25 | La principal diferencia entre `f32` y `f64` es la precisión:
26 | - `f32` utiliza 32 bits para representar un número de coma flotante.
27 | - `f64` utiliza 64 bits para representar un número de coma flotante.
28 |
29 | Debido a esto, `f64` proporciona una mayor precisión y un rango más amplio de valores que `f32`.
30 |
31 | #### 2. Rango de Valores
32 |
33 | - **`f32`:** Tiene un rango de valores aproximado de ±3.40282347e+38 y una precisión de aproximadamente 7 dígitos decimales.
34 | - **`f64`:** Tiene un rango de valores aproximado de ±1.7976931348623157e+308 y una precisión de aproximadamente 15 dígitos decimales.
35 |
36 | #### 3. Rendimiento
37 |
38 | En términos de rendimiento, no existe una diferencia significativa entre `f32` y `f64` en la mayoría de los procesadores modernos, ya que ambos utilizan los mismos algoritmos y métodos de procesamiento. Sin embargo, `f32` puede ser preferible en aplicaciones donde el uso de memoria es una preocupación importante.
39 |
40 | ### Usos de `f32` y `f64`
41 |
42 | - **`f32`:** Se utiliza cuando se requiere una menor precisión y se desea ahorrar memoria, como en gráficos de juegos, cálculos científicos con menos precisión o aplicaciones de bajo consumo de recursos.
43 | - **`f64`:** Se utiliza cuando se requiere una mayor precisión, como en cálculos financieros, ingeniería de precisión o aplicaciones científicas donde se necesitan valores muy precisos.
44 |
45 | ### Ejemplos de Uso en Rust
46 |
47 | ```rust
48 | fn main() {
49 | let x: f32 = 3.14; // Declaración de un valor f32
50 | let y: f64 = 3.14; // Declaración de un valor f64
51 |
52 | println!("Valor de x: {}", x);
53 | println!("Valor de y: {}", y);
54 |
55 | // Operaciones aritméticas
56 | let suma = x as f64 + y;
57 | let resta = x as f64 - y;
58 | let multiplicacion = x as f64 * y;
59 | let division = x as f64 / y;
60 |
61 | println!("Suma: {}", suma);
62 | println!("Resta: {}", resta);
63 | println!("Multiplicación: {}", multiplicacion);
64 | println!("División: {}", division);
65 | }
66 | ```
67 |
68 | **Gráfico 1: Ejemplo de Operaciones con `f32` y `f64`**
69 |
70 | ```plaintext
71 | let x: f32 = 3.14; // 32-bit float
72 | let y: f64 = 3.14; // 64-bit float
73 |
74 | +-----+ +-------+
75 | | x |----->| 3.14 |
76 | +-----+ +-------+
77 | f32
78 |
79 | +-----+ +-------+
80 | | y |----->| 3.14 |
81 | +-----+ +-------+
82 | f64
83 |
84 | let suma = x as f64 + y;
85 | let resta = x as f64 - y;
86 | let multiplicacion = x as f64 * y;
87 | let division = x as f64 / y;
88 | ```
89 |
90 | ### Métodos Más Utilizados
91 |
92 | Los tipos `f32` y `f64` no tienen métodos específicos asociados ya que son tipos primitivos en Rust. Sin embargo, se pueden utilizar funciones y métodos proporcionados por Rust para trabajar con valores de punto flotante. Algunas de las funciones y métodos más comunes son:
93 |
94 | - **`abs()`:** Devuelve el valor absoluto de un número.
95 | - **`ceil()`:** Redondea hacia arriba al número entero más cercano.
96 | - **`floor()`:** Redondea hacia abajo al número entero más cercano.
97 | - **`round()`:** Redondea al número entero más cercano.
98 | - **`sqrt()`:** Calcula la raíz cuadrada del número.
99 |
100 | #### Ejemplo de Uso de Métodos de Punto Flotante
101 |
102 | ```rust
103 | fn main() {
104 | let z: f64 = -3.14;
105 |
106 | println!("Valor absoluto: {}", z.abs());
107 | println!("Redondeo hacia arriba: {}", z.ceil());
108 | println!("Redondeo hacia abajo: {}", z.floor());
109 | println!("Redondeo al entero más cercano: {}", z.round());
110 | println!("Raíz cuadrada de 9.0: {}", 9.0f64.sqrt());
111 | }
112 | ```
113 |
114 | **Gráfico 2: Métodos Comunes para `f32` y `f64`**
115 |
116 | ```plaintext
117 | let z: f64 = -3.14;
118 |
119 | +-----+ +-------+
120 | | z |----->| -3.14 |
121 | +-----+ +-------+
122 | f64
123 |
124 | z.abs() -> 3.14
125 | z.ceil() -> -3.0
126 | z.floor() -> -4.0
127 | z.round() -> -3.0
128 | 9.0.sqrt() -> 3.0
129 | ```
130 |
131 | ### Conclusión
132 |
133 | Los tipos de punto flotante `f32` y `f64` en Rust son esenciales para realizar cálculos numéricos precisos. La elección entre `f32` y `f64` depende de la precisión requerida y las restricciones de memoria de la aplicación. Con una comprensión clara de las diferencias y usos de cada uno, podemos tomar decisiones informadas al escribir código eficiente y preciso en Rust.
134 |
--------------------------------------------------------------------------------
/content/2.basic/17.char.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'char'
3 | description: 'El Tipo `char` en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 158
10 | y: 280
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types#el-tipo-de-car%C3%A1cter'
16 | - name: 'Ferrous System'
17 | english: true
18 | link: 'https://github.com/ferrous-systems/rust-training/blob/main/training-slides/src/basic-types.md#character'
19 | ---
20 | ## El Tipo `char` en Rust
21 |
22 | El tipo `char` en Rust representa un solo carácter Unicode, que puede ser un carácter alfabético, numérico, un símbolo o un carácter especial. Este tipo es fundamental para la manipulación de texto en Rust. En este post, detallaremos las características del tipo `char`, sus usos, los métodos más comunes y cómo se maneja en memoria.
23 |
24 | ### Características del Tipo `char`
25 |
26 | #### 1. Representación Unicode
27 |
28 | En Rust, los valores `char` se representan utilizando el estándar Unicode, lo que permite representar caracteres de cualquier lenguaje humano, así como una amplia variedad de símbolos y caracteres especiales.
29 |
30 | #### 2. Tamaño en Memoria
31 |
32 | Los valores `char` en Rust ocupan 4 bytes de memoria. Esto se debe a que están codificados en UTF-8, donde cada carácter Unicode se representa por hasta 4 bytes. Esta capacidad de almacenamiento permite manejar una amplia gama de caracteres Unicode.
33 |
34 | #### 3. Inmutabilidad
35 |
36 | Los valores `char` son inmutables, lo que significa que una vez que se asigna un valor a una variable `char`, este no se puede cambiar.
37 |
38 | ### Usos del Tipo `char`
39 |
40 | - **Representación de Caracteres:** Se utiliza para representar caracteres individuales en texto, como letras, números, símbolos o caracteres especiales.
41 | - **Procesamiento de Texto y Cadenas:** Es útil para manipular y procesar texto en programas, como contar caracteres, extraer subcadenas o realizar operaciones de búsqueda y reemplazo.
42 |
43 | ### Métodos Más Comunes
44 |
45 | Aunque el tipo `char` en Rust no tiene métodos específicos asociados, se pueden realizar operaciones comunes utilizando funciones proporcionadas por Rust para trabajar con caracteres. Algunas de las funciones más comunes son:
46 |
47 | - **`is_alphabetic()`:** Devuelve `true` si el carácter es una letra alfabética.
48 | - **`is_numeric()`:** Devuelve `true` si el carácter es un dígito numérico.
49 | - **`to_uppercase()`:** Convierte el carácter a mayúsculas.
50 | - **`to_lowercase()`:** Convierte el carácter a minúsculas.
51 | - **`is_whitespace()`:** Devuelve `true` si el carácter es un espacio en blanco.
52 | - **`is_ascii()`:** Devuelve `true` si el carácter es un carácter ASCII de 7 bits.
53 |
54 | ### Ejemplo de Uso en Rust
55 |
56 | ```rust
57 | fn main() {
58 | let ch: char = 'a';
59 |
60 | if ch.is_alphabetic() {
61 | println!("{} es una letra alfabética", ch);
62 | }
63 |
64 | if ch.is_numeric() {
65 | println!("{} es un dígito numérico", ch);
66 | }
67 |
68 | println!("{} en mayúsculas es {}", ch, ch.to_uppercase());
69 | println!("{} en minúsculas es {}", ch.to_lowercase().next().unwrap(), ch.to_lowercase());
70 | println!("{} es un espacio en blanco: {}", ch, ch.is_whitespace());
71 | println!("{} es un carácter ASCII: {}", ch, ch.is_ascii());
72 | }
73 | ```
74 |
75 | **Gráfico 1: Ejemplo de Uso del Tipo `char`**
76 |
77 | ```plaintext
78 | let ch: char = 'a';
79 |
80 | +-----+ +---+
81 | | ch |----->| a |
82 | +-----+ +---+
83 | char
84 |
85 | ch.is_alphabetic() -> true
86 | ch.is_numeric() -> false
87 | ch.to_uppercase() -> 'A'
88 | ch.to_lowercase() -> 'a'
89 | ch.is_whitespace() -> false
90 | ch.is_ascii() -> true
91 | ```
92 |
93 | ### Espacio en Memoria
94 |
95 | Como se mencionó anteriormente, los valores `char` en Rust ocupan 4 bytes de memoria, ya que están codificados en UTF-8. Esto permite representar una amplia gama de caracteres Unicode con un solo valor `char`. La codificación UTF-8 también garantiza una compatibilidad completa con los estándares Unicode y la capacidad de representar texto en múltiples idiomas y scripts.
96 |
97 | **Gráfico 2: Espacio en Memoria del Tipo `char`**
98 |
99 | ```plaintext
100 | +---------------------+
101 | | 'a' |
102 | | |
103 | | 4 bytes (UTF-8) |
104 | +---------------------+
105 | ```
106 |
107 | ### Conclusión
108 |
109 | El tipo `char` en Rust es una herramienta poderosa para manejar caracteres individuales y realizar operaciones de procesamiento de texto. Su representación en Unicode y su capacidad para ocupar 4 bytes de memoria le permiten manejar una amplia gama de caracteres de diferentes idiomas y scripts. Comprender cómo utilizar y manipular el tipo `char` es esencial para escribir programas eficientes y robustos en Rust.
110 |
--------------------------------------------------------------------------------
/content/2.basic/18.signed-integer.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'i8, i16, i32, i64, i128, isize'
3 | description: 'Comprendiendo los Tipos Enteros con Signo en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -50
10 | y: 320
11 | width: 280
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types.html#tipos-de-enteros'
16 | - name: 'Ferrous System'
17 | english: true
18 | link: 'https://github.com/ferrous-systems/rust-training/blob/main/training-slides/src/basic-types.md#integers'
19 | - name: 'Ferrocene Language Specification'
20 | english: true
21 | link: 'https://public-docs.ferrocene.dev/main/specification/types-and-traits.html#integer-types'
22 | ---
23 | ## Comprendiendo los Tipos Enteros con Signo en Rust
24 |
25 | En Rust, los tipos `i8`, `i16`, `i32`, `i64`, `i128` y `isize` son tipos de datos enteros con signo que representan números enteros con diferentes tamaños y rangos. Estos tipos son fundamentales para el manejo eficiente de números enteros en Rust. A continuación, se presenta una explicación detallada de cada uno, sus usos, métodos comunes y su espacio en memoria.
26 |
27 | ### Tipos Enteros con Signo en Rust
28 |
29 | #### 1. `i8`
30 | - **Descripción:** Representa números enteros con signo de 8 bits.
31 | - **Rango de valores:** -128 a 127.
32 | - **Espacio en memoria:** 1 byte.
33 |
34 | #### 2. `i16`
35 | - **Descripción:** Representa números enteros con signo de 16 bits.
36 | - **Rango de valores:** -32,768 a 32,767.
37 | - **Espacio en memoria:** 2 bytes.
38 |
39 | #### 3. `i32`
40 | - **Descripción:** Representa números enteros con signo de 32 bits.
41 | - **Rango de valores:** -2,147,483,648 a 2,147,483,647.
42 | - **Espacio en memoria:** 4 bytes.
43 |
44 | #### 4. `i64`
45 | - **Descripción:** Representa números enteros con signo de 64 bits.
46 | - **Rango de valores:** -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807.
47 | - **Espacio en memoria:** 8 bytes.
48 |
49 | #### 5. `i128`
50 | - **Descripción:** Representa números enteros con signo de 128 bits.
51 | - **Rango de valores:** -170,141,183,460,469,231,731,687,303,715,884,105,728 a 170,141,183,460,469,231,731,687,303,715,884,105,727.
52 | - **Espacio en memoria:** 16 bytes.
53 |
54 | #### 6. `isize`
55 | - **Descripción:** Representa números enteros con signo que tienen el tamaño de un puntero. Esto significa que su tamaño puede variar dependiendo de la arquitectura del sistema.
56 | - **Rango de valores:** Depende de la arquitectura.
57 | - **Espacio en memoria:** 4 bytes en sistemas de 32 bits, 8 bytes en sistemas de 64 bits.
58 |
59 | ### Usos de los Tipos Enteros con Signo
60 |
61 | - **Almacenamiento de datos:** Se utilizan para almacenar números enteros con signo en diferentes rangos, dependiendo de la precisión requerida por la aplicación.
62 | - **Operaciones aritméticas:** Se utilizan para realizar operaciones matemáticas como suma, resta, multiplicación y división en valores enteros.
63 | - **Índices y tamaños de datos:** `isize` se utiliza comúnmente para índices y tamaños de datos en estructuras de datos, ya que su tamaño se ajusta automáticamente a la arquitectura del sistema.
64 |
65 | ### Métodos Más Comunes
66 |
67 | Los tipos enteros en Rust no tienen métodos específicos asociados, pero se pueden utilizar funciones proporcionadas por Rust para realizar operaciones comunes. Algunas de las funciones más utilizadas son:
68 |
69 | - **`abs()`:** Devuelve el valor absoluto del número.
70 | - **`to_string()`:** Convierte el número en una cadena de caracteres.
71 | - **`overflowing_add()`:** Realiza una suma con desbordamiento silencioso, devolviendo una tupla con el resultado y un indicador de desbordamiento.
72 | - **`wrapping_add()`:** Realiza una suma con desbordamiento modular, devolviendo el resultado con un desbordamiento envuelto.
73 |
74 | ### Ejemplos de Uso en Rust
75 |
76 | ```rust
77 | fn main() {
78 | let a: i32 = -42;
79 | let b: i32 = 56;
80 |
81 | // Operaciones comunes
82 | println!("Valor absoluto de a: {}", a.abs());
83 | println!("a como cadena: {}", a.to_string());
84 | println!("Número de bits en 1 en b: {}", b.count_ones());
85 | println!("Número de bits en 0 en b: {}", b.count_zeros());
86 |
87 | let (sum, overflowed) = a.overflowing_add(b);
88 | println!("Suma con posible desbordamiento: {} (desbordado: {})", sum, overflowed);
89 |
90 | let wrapped_sum = a.wrapping_add(b);
91 | println!("Suma con desbordamiento envuelto: {}", wrapped_sum);
92 | }
93 | ```
94 |
95 | **Gráfico 1: Ejemplo de Operaciones Comunes con Enteros en Rust**
96 |
97 | ```rust
98 | let a: i32 = -42;
99 | let b: i32 = 56;
100 |
101 | a.abs(); // -> 42
102 | a.to_string(); // -> "-42"
103 | b.count_ones(); // -> 5
104 | b.count_zeros(); // -> 27
105 | a.overflowing_add(b) // -> (14, false)
106 | a.wrapping_add(b) // -> 14
107 | ```
108 |
109 | ### Espacio en Memoria
110 |
111 | El espacio en memoria ocupado por los tipos enteros depende del tamaño de cada tipo:
112 |
113 | - **`i8`:** 1 byte
114 | - **`i16`:** 2 bytes
115 | - **`i32`:** 4 bytes
116 | - **`i64`:** 8 bytes
117 | - **`i128`:** 16 bytes
118 | - **`isize`:** 4 bytes en sistemas de 32 bits, 8 bytes en sistemas de 64 bits
119 |
120 | Estos tamaños de memoria son fijos y no dependen de los valores almacenados en las variables.
121 |
122 | **Gráfico 2: Tamaños de Memoria de los Tipos Enteros en Rust**
123 |
124 | ```plaintext
125 | +------+ +------+
126 | | Tipo | | Size |
127 | +------+ +------+
128 | | i8 |----->| 1 B |
129 | +------+ +------+
130 | | i16 |----->| 2 B |
131 | +------+ +------+
132 | | i32 |----->| 4 B |
133 | +------+ +------+
134 | | i64 |----->| 8 B |
135 | +------+ +------+
136 | | i128 |----->| 16 B |
137 | +------+ +------+
138 | | isize|----->| 4 B / 8 B |
139 | +------+ +----------+
140 | ```
141 |
142 | ### Conclusión
143 |
144 | Los tipos enteros con signo en Rust (`i8`, `i16`, `i32`, `i64`, `i128`, `isize`) son fundamentales para manejar números enteros en diversas aplicaciones. Comprender las diferencias en tamaño y rango, así como los métodos comunes para trabajar con ellos, permite a los desarrolladores escribir código eficiente y preciso. Estos tipos proporcionan la flexibilidad necesaria para adaptarse a diferentes necesidades de almacenamiento y procesamiento en Rust.
145 |
--------------------------------------------------------------------------------
/content/2.basic/2.variables.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Variables y Declaraciones'
3 | description: 'Profundizando en las Variables en Rust: Funcionamiento, Almacenamiento y Gestión de Memoria'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 240
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-01-variables-and-mutability'
16 | - name: 'Variables y declaraciones en Rust'
17 | english: false
18 | link: 'https://blog.rustlang-es.org/articles/variables-y-declaraciones'
19 | ---
20 | ## Profundizando en las Variables en Rust: Funcionamiento, Almacenamiento y Gestión de Memoria
21 |
22 | En Rust, las variables juegan un papel crucial en la gestión de datos y la memoria. Este blog post explorará a fondo cómo funcionan las variables en Rust, cómo se almacenan y gestionan en la memoria, y los diferentes tipos de declaración disponibles.
23 |
24 | ### 1. ¿Qué es una Variable en Rust?
25 |
26 | En Rust, una variable es un contenedor que puede almacenar un valor de un tipo específico. Las variables permiten a los programas almacenar y manipular datos de manera eficiente. A diferencia de algunos lenguajes, las variables en Rust son **inmutables** por defecto, lo que significa que no pueden ser reasignadas después de su declaración a menos que se especifiquen como mutables.
27 |
28 | ### 2. Declaración e Inicialización de Variables
29 |
30 | La declaración de una variable en Rust se realiza utilizando la palabra clave `let`. Aquí hay un ejemplo básico:
31 |
32 | ```rust
33 | fn main() {
34 | let x = 5;
35 | println!("El valor de x es: {x}");
36 | }
37 | ```
38 |
39 | En este ejemplo:
40 | - `let x = 5;` declara una variable `x` y la inicializa con el valor `5`.
41 | - `println!("El valor de x es: {x}");` imprime el valor de `x` en la pantalla.
42 |
43 | ### 3. Mutabilidad
44 |
45 | En la programación un problema común es que los desarrolladores crean variables y suele re utilizarlas bastante sin saber su uso en otro momento.
46 |
47 | Por lo que inicialmente se espera que tenga un valor pero en entre un punto y otro se modifica ese valor, eso crea un error, se esperaba que ese valor permanezca con el estado inicial a lo largo de su ejecución.
48 |
49 | En Rust, para solucionar ese problema se tomo la medida de que toda variable sea inmutable por defecto.
50 |
51 | Es decir, a menos que no sea declarada para que sea modificada por futuros programadores esa variable no puede cambiar de valor.
52 |
53 | Para permitir que una variable sea reasignada, debes declararla como mutable usando la palabra clave `mut`:
54 |
55 | ```rust
56 | fn main() {
57 | let mut x = 5;
58 | println!("El valor de x es: {x}");
59 | x = 6;
60 | println!("El valor de x ahora es: {x}");
61 | }
62 | ```
63 |
64 | En este ejemplo:
65 | - `let mut x = 5;` declara una variable mutable `x` y la inicializa con el valor `5`.
66 | - `x = 6;` reasigna `x` con el valor `6`.
67 |
68 | ### 4. Tipos de Datos y Inferencia de Tipos
69 |
70 | Rust es un lenguaje de programación fuertemente tipado, lo que significa que cada variable tiene un tipo específico. Los tipos básicos incluyen:
71 |
72 | - **Enteros** (`i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `u8`, `u16`, `u32`, `u64`, `u128`, `usize`)
73 | - **Flotantes** (`f32`, `f64`)
74 | - **Booleanos** (`bool`)
75 | - **Caracteres** (`char`)
76 | - **Cadenas** (`String`)
77 |
78 | > En otros topicos se detalla mejor cada tipo de dato
79 |
80 | Por lo general Rust puede inferir automáticamente el tipo de una variable basándose en el valor asignado, pero también puedes especificar explícitamente el tipo:
81 |
82 | ```rust
83 | fn main() {
84 | let x: i32 = 5;
85 | let y: f64 = 3.14;
86 | let z: bool = true;
87 | println!("x: {}, y: {}, z: {}", x, y, z);
88 | }
89 | ```
90 |
91 | ### 5. Gestión de Memoria
92 |
93 | Rust utiliza un sistema de gestión de memoria basado en la propiedad y el préstamo. Cada variable en Rust tiene un propietario, y la memoria se libera automáticamente cuando el propietario sale del alcance. Esto elimina la necesidad de un recolector de basura (GC) y reduce la sobrecarga de memoria.
94 |
95 | #### Almacenamiento en Stack y Heap
96 |
97 | - **Stack:** Las variables de tipos primitivos (como enteros y booleanos) se almacenan en la pila (stack). El acceso a la memoria de la pila es rápido y eficiente.
98 | - **Heap:** Las estructuras de datos complejas (como `String` y `Vec`) se almacenan en el montón (heap). El acceso a la memoria del montón es más lento, pero permite una mayor flexibilidad en la gestión de la memoria.
99 |
100 | ```rust
101 | fn main() {
102 | let s1 = String::from("Hello");
103 | let s2 = s1; // s1 se mueve a s2
104 | // println!("{}", s1); // Error: s1 ya no es válido
105 | println!("{}", s2);
106 | }
107 | ```
108 |
109 | En este ejemplo, `s1` se mueve a `s2`, y `s1` ya no es válido. Rust previene errores comunes relacionados con la memoria mediante estas reglas estrictas de propiedad.
110 |
111 | #### Conclusión
112 |
113 | Las variables en Rust son fundamentales para la gestión de datos y la memoria. La combinación de mutabilidad controlada, tipos estrictos, y un sistema de propiedad robusto hace que Rust sea seguro y eficiente. Entender cómo funcionan las variables y cómo se gestionan en memoria es esencial para escribir programas efectivos en Rust. Al dominar estos conceptos, estarás bien encaminado para aprovechar al máximo este potente lenguaje. ¡Feliz codificación!
114 |
--------------------------------------------------------------------------------
/content/2.basic/20.str.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'str'
3 | description: 'El Tipo de Dato `str` en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -50
10 | y: 400
11 | width: 280
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: ''
16 | - name: 'Ferrous System'
17 | english: true
18 | link: ''
19 | - name: 'Ferrocene Language Specification'
20 | english: true
21 | link: 'https://public-docs.ferrocene.dev/main/specification/types-and-traits.html#str-type'
22 | ---
23 | ## El Tipo de Dato `str` en Rust
24 |
25 | En Rust, el tipo de dato `str` es fundamental para trabajar con cadenas de caracteres. A diferencia de muchos otros lenguajes, Rust trata las cadenas de forma única, lo que puede parecer complicado al principio, pero proporciona una gran eficiencia y seguridad. Este artículo detalla las características del tipo `str`, sus usos, métodos comunes y cómo manejarlo en memoria.
26 |
27 | ### Características del Tipo `str`
28 |
29 | #### 1. Inmutabilidad
30 | - **Descripción:** En Rust, las cadenas de tipo `str` son inmutables. Esto significa que una vez creada, una cadena `str` no puede ser modificada.
31 | - **Ventaja:** La inmutabilidad garantiza la seguridad y coherencia de los datos a lo largo de la ejecución del programa.
32 |
33 | #### 2. Almacenamiento en Memoria
34 | - **Descripción:** El tipo `str` en Rust se almacena como una secuencia contigua de bytes en memoria.
35 | - **Codificación:** Las cadenas `str` están codificadas en UTF-8, lo que permite representar una amplia variedad de caracteres Unicode.
36 | - **Referencia:** En general, las cadenas `str` se manipulan mediante referencias (`&str`) para evitar copias innecesarias y mejorar el rendimiento.
37 |
38 | #### 3. Tamaño Dinámico
39 | - **Descripción:** El tamaño de un `str` está determinado en tiempo de ejecución, lo que lo convierte en un tipo de tamaño dinámico (DST, por sus siglas en inglés).
40 | - **Manipulación:** Para trabajar con `str`, generalmente utilizamos una referencia (`&str`) que incluye un puntero al inicio de la cadena y una longitud que indica su tamaño.
41 |
42 | ### Usos del Tipo `str`
43 |
44 | - **Texto Inmutable:** Se utiliza para representar texto que no necesita ser modificado, como mensajes de error, etiquetas y textos constantes.
45 | - **Comparaciones y Búsquedas:** Es útil para realizar comparaciones y búsquedas dentro de cadenas de texto, asegurando eficiencia y seguridad.
46 | - **Datos Multilingües:** Gracias a su codificación en UTF-8, `str` es ideal para manejar texto en múltiples idiomas, incluidos caracteres especiales y emojis.
47 |
48 | ### Métodos Más Comunes
49 |
50 | Aunque el tipo `str` no tiene métodos asociados directamente, Rust proporciona una serie de funciones y métodos a través del tipo de referencia `&str` para manipular y trabajar con cadenas de manera efectiva. Aquí algunos de los métodos más utilizados:
51 |
52 | #### 1. `len()`
53 | - **Descripción:** Devuelve la longitud de la cadena en bytes.
54 | - **Ejemplo:**
55 |
56 | ```rust
57 | let s = "Hola, mundo!";
58 | println!("La longitud de s es: {}", s.len());
59 | ```
60 |
61 | #### 2. `is_empty()`
62 | - **Descripción:** Verifica si la cadena está vacía.
63 | - **Ejemplo:**
64 |
65 | ```rust
66 | let s = "";
67 | println!("¿Está s vacía?: {}", s.is_empty());
68 | ```
69 |
70 | #### 3. `contains()`
71 | - **Descripción:** Comprueba si una subcadena está presente en la cadena.
72 | - **Ejemplo:**
73 |
74 | ```rust
75 | let s = "Hola, mundo!";
76 | println!("¿Contiene 'mundo'?: {}", s.contains("mundo"));
77 | ```
78 |
79 | #### 4. `split()`
80 | - **Descripción:** Divide la cadena en subcadenas basadas en un delimitador.
81 | - **Ejemplo:**
82 |
83 | ```rust
84 | let s = "Hola, mundo!";
85 | for part in s.split(", ") {
86 | println!("{}", part);
87 | }
88 | ```
89 |
90 | #### 5. `to_uppercase()`
91 | - **Descripción:** Convierte la cadena a mayúsculas.
92 | - **Ejemplo:**
93 |
94 | ```rust
95 | let s = "Hola, mundo!";
96 | println!("En mayúsculas: {}", s.to_uppercase());
97 | ```
98 |
99 | ### Ejemplo de Uso en Rust
100 |
101 | ```rust
102 | fn main() {
103 | let saludo: &str = "Hola, mundo!";
104 |
105 | // Métodos comunes
106 | println!("Longitud: {}", saludo.len());
107 | println!("¿Está vacío?: {}", saludo.is_empty());
108 | println!("¿Contiene 'mundo'?: {}", saludo.contains("mundo"));
109 |
110 | // División de la cadena
111 | for parte in saludo.split(", ") {
112 | println!("Parte: {}", parte);
113 | }
114 |
115 | // Conversión a mayúsculas
116 | println!("En mayúsculas: {}", saludo.to_uppercase());
117 | }
118 | ```
119 |
120 | ### Espacio en Memoria
121 |
122 | En Rust, el tipo `str` es almacenado en memoria de manera contigua y codificado en UTF-8, permitiendo una representación eficiente y compacta de texto Unicode. A continuación, se ilustra cómo se gestiona en memoria:
123 |
124 | **Gráfico: Almacenamiento de una Cadena `str` en Memoria**
125 |
126 | ```plaintext
127 | +---+---+---+---+---+---+---+---+---+---+---+---+
128 | | H | o | l | a | , | | m | u | n | d | o | ! |
129 | +---+---+---+---+---+---+---+---+---+---+---+---+
130 | 0 1 2 3 4 5 6 7 8 9 10 11
131 |
132 | Dirección de memoria contigua:
133 | Puntero al inicio -> 0
134 | Longitud en bytes -> 12
135 | ```
136 |
137 | ### Conclusión
138 |
139 | El tipo `str` en Rust es una poderosa herramienta para trabajar con cadenas de texto de manera segura y eficiente. Su inmutabilidad, codificación en UTF-8 y manejo dinámico de tamaños lo hacen ideal para aplicaciones que requieren un manejo robusto de texto. Comprender cómo utilizar `str` y sus métodos asociados permite a los desarrolladores escribir código más seguro y eficiente en Rust.
140 |
--------------------------------------------------------------------------------
/content/2.basic/21.complex-types.yml:
--------------------------------------------------------------------------------
1 | title: 'Tipos de Datos Complejos'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: -50
8 | y: 480
9 | width: 320
10 | align: 'left'
11 | sourcePosition:
12 | none: 'top'
13 | targetPosition:
14 | basic: 'left'
15 |
--------------------------------------------------------------------------------
/content/2.basic/22.tuples.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'tupla'
3 | description: 'Las Tuplas en Rust: Una Introducción'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -50
10 | y: 520
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types#el-tipo-tupla'
16 | - name: 'Libro de Referencia Rust'
17 | english: true
18 | link: 'https://doc.rust-lang.org/reference/types/tuple.html#tuple-types'
19 | ---
20 | ## Las Tuplas en Rust: Una Introducción
21 |
22 | En Rust, las tuplas son un tipo de dato versátil y poderoso que permite agrupar múltiples valores de diferentes tipos en una única entidad. Esta funcionalidad es especialmente útil para retornar múltiples valores de una función o para agrupar datos relacionados de manera estructurada. En este blog post, exploraremos en detalle las características, usos y métodos comunes de las tuplas en Rust.
23 |
24 | ### Características de las Tuplas
25 |
26 | #### 1. Heterogeneidad
27 | - **Descripción:** Las tuplas pueden contener valores de diferentes tipos. Esto las diferencia de las arrays y vectors, que solo pueden contener valores del mismo tipo.
28 | - **Ejemplo:**
29 |
30 | ```rust
31 | let tupla: (i32, f64, char) = (42, 3.14, 'a');
32 | ```
33 |
34 | #### 2. Tamaño Fijo
35 | - **Descripción:** El tamaño de una tupla se define en el momento de su creación y no puede cambiar. Cada tupla tiene un número fijo de elementos, y este número se debe conocer en tiempo de compilación.
36 | - **Ejemplo:**
37 |
38 | ```rust
39 | let tupla: (i32, i32) = (1, 2); // Tamaño fijo de 2 elementos
40 | ```
41 |
42 | #### 3. Acceso por Índice
43 | - **Descripción:** Los elementos de una tupla se pueden acceder por su índice, comenzando desde cero.
44 | - **Ejemplo:**
45 |
46 | ```rust
47 | let tupla: (i32, f64, char) = (42, 3.14, 'a');
48 | println!("El primer elemento es: {}", tupla.0);
49 | println!("El segundo elemento es: {}", tupla.1);
50 | println!("El tercer elemento es: {}", tupla.2);
51 | ```
52 |
53 | ### Usos de las Tuplas
54 |
55 | - **Retorno de Múltiples Valores:** Las tuplas son ideales para funciones que necesitan retornar múltiples valores.
56 | - **Agrupación de Datos Relacionados:** Permiten agrupar datos relacionados de diferentes tipos en una sola estructura.
57 | - **Desestructuración:** Facilita la extracción de valores individuales de una tupla.
58 |
59 | ### Ejemplo de Uso en Rust
60 |
61 | ```rust
62 | fn main() {
63 | let coordenadas: (f64, f64) = (6.0, 8.0);
64 |
65 | // Desestructuración de la tupla
66 | let (x, y) = coordenadas;
67 | println!("Coordenadas: x = {}, y = {}", x, y);
68 |
69 | // Acceso por índice
70 | println!("El primer elemento es: {}", coordenadas.0);
71 | println!("El segundo elemento es: {}", coordenadas.1);
72 |
73 | // Función que retorna una tupla
74 | let resultado = sumar_y_multiplicar(3, 4);
75 | println!("Suma: {}, Multiplicación: {}", resultado.0, resultado.1);
76 | }
77 |
78 | fn sumar_y_multiplicar(a: i32, b: i32) -> (i32, i32) {
79 | (a + b, a * b)
80 | }
81 | ```
82 |
83 | ### Métodos Más Comunes
84 |
85 | Aunque las tuplas no tienen métodos específicos asociados como otros tipos en Rust, se pueden manipular mediante desestructuración y acceso por índice. Sin embargo, algunas operaciones comunes incluyen:
86 |
87 | - **Desestructuración:** Permite asignar los valores de una tupla a variables individuales.
88 | - **Acceso por Índice:** Acceso directo a los elementos individuales de una tupla usando su índice.
89 |
90 | ### Desestructuración de Tuplas
91 |
92 | La desestructuración permite desempaquetar una tupla en sus componentes individuales. Esto es útil cuando se necesitan trabajar con los valores por separado.
93 |
94 | ```rust
95 | fn main() {
96 | let persona: (&str, i32) = ("Alice", 30);
97 |
98 | // Desestructuración
99 | let (nombre, edad) = persona;
100 | println!("Nombre: {}, Edad: {}", nombre, edad);
101 | }
102 | ```
103 |
104 | ### Acceso por Índice
105 |
106 | Cada elemento de una tupla se puede acceder utilizando el índice correspondiente, que empieza desde cero.
107 |
108 | ```rust
109 | fn main() {
110 | let colores: (&str, &str, &str) = ("rojo", "verde", "azul");
111 |
112 | println!("Primer color: {}", colores.0);
113 | println!("Segundo color: {}", colores.1);
114 | println!("Tercer color: {}", colores.2);
115 | }
116 | ```
117 |
118 | ### Espacio en Memoria
119 |
120 | Las tuplas ocupan un tamaño en memoria que es la suma del tamaño de cada uno de sus elementos. Esto garantiza que no haya desperdicio de memoria y que las operaciones con tuplas sean eficientes.
121 |
122 | **Gráfico: Representación de una Tupla en Memoria**
123 |
124 | ```plaintext
125 | +-----------+-----------+-----------+
126 | | i32 | f64 | char |
127 | +-----------+-----------+-----------+
128 | | 4 bytes | 8 bytes | 4 bytes |
129 | +-----------+-----------+-----------+
130 | ```
131 |
132 | ### Conclusión
133 |
134 | Las tuplas en Rust son una herramienta poderosa para agrupar múltiples valores de diferentes tipos en una única entidad. Su capacidad para ser desestructuradas y acceder a sus elementos por índice las hace extremadamente útiles para una variedad de aplicaciones, desde retornar múltiples valores de funciones hasta agrupar datos relacionados. Al entender cómo funcionan las tuplas y cómo utilizarlas de manera efectiva, los desarrolladores pueden escribir código más limpio y eficiente en Rust.
135 |
--------------------------------------------------------------------------------
/content/2.basic/23.array.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Arreglos'
3 | description: 'Los Arreglos en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 32
10 | y: 520
11 | width: 118
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-02-data-types#el-tipo-arreglo'
16 | - name: 'Libro de Referencia Rust'
17 | english: true
18 | link: 'https://doc.rust-lang.org/reference/types/array.html'
19 | ---
20 | ## Los Arreglos en Rust
21 |
22 | En Rust, los arreglos (arrays) son una de las estructuras de datos más básicas y esenciales. Los arreglos permiten almacenar múltiples valores del mismo tipo en una secuencia contigua de elementos. Este blog post explora en detalle las características, usos, métodos comunes y manejo en memoria de los arreglos en Rust.
23 |
24 | ### Características de los Arreglos en Rust
25 |
26 | #### 1. Homogeneidad
27 | - **Descripción:** Todos los elementos de un arreglo deben ser del mismo tipo.
28 | - **Ejemplo:**
29 |
30 | ```rust
31 | let numeros: [i32; 5] = [1, 2, 3, 4, 5];
32 | ```
33 |
34 | #### 2. Tamaño Fijo
35 | - **Descripción:** El tamaño de un arreglo en Rust se debe conocer en tiempo de compilación y no puede cambiar.
36 | - **Ejemplo:**
37 |
38 | ```rust
39 | let letras: [char; 3] = ['a', 'b', 'c'];
40 | ```
41 |
42 | #### 3. Acceso por Índice
43 | - **Descripción:** Los elementos de un arreglo se pueden acceder mediante índices, comenzando desde cero.
44 | - **Ejemplo:**
45 |
46 | ```rust
47 | let dias: [&str; 7] = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"];
48 | println!("El primer día es: {}", dias[0]);
49 | ```
50 |
51 | ### Usos de los Arreglos
52 |
53 | - **Almacenamiento de Datos:** Los arreglos son útiles para almacenar colecciones de datos del mismo tipo, como números, caracteres o strings.
54 | - **Iteraciones y Operaciones:** Facilitan la realización de operaciones repetitivas sobre una colección de elementos.
55 | - **Acceso Rápido:** Proporcionan acceso rápido a los elementos a través de índices.
56 |
57 | ### Ejemplo de Uso en Rust
58 |
59 | ```rust
60 | fn main() {
61 | let numeros: [i32; 5] = [1, 2, 3, 4, 5];
62 |
63 | // Acceso por índice
64 | println!("El primer número es: {}", numeros[0]);
65 |
66 | // Iteración sobre el arreglo
67 | for num in numeros.iter() {
68 | println!("Número: {}", num);
69 | }
70 |
71 | // Modificación de un elemento
72 | let mut mutable_numeros = [1, 2, 3, 4, 5];
73 | mutable_numeros[0] = 10;
74 | println!("El primer número modificado es: {}", mutable_numeros[0]);
75 | }
76 | ```
77 |
78 | ### Métodos Comunes
79 |
80 | Aunque los arreglos en Rust no tienen métodos asociados como las colecciones más complejas, se pueden utilizar en combinación con slices y otros tipos para realizar diversas operaciones. Aquí algunos de los métodos y usos más comunes:
81 |
82 | #### 1. `len()`
83 | - **Descripción:** Devuelve la longitud del arreglo.
84 | - **Ejemplo:**
85 |
86 | ```rust
87 | let numeros: [i32; 5] = [1, 2, 3, 4, 5];
88 | println!("La longitud del arreglo es: {}", numeros.len());
89 | ```
90 |
91 | #### 2. Iteración con `iter()`
92 | - **Descripción:** Devuelve un iterador sobre el arreglo.
93 | - **Ejemplo:**
94 |
95 | ```rust
96 | let frutas: [&str; 3] = ["Manzana", "Banana", "Cereza"];
97 | for fruta in frutas.iter() {
98 | println!("Fruta: {}", fruta);
99 | }
100 | ```
101 |
102 | #### 3. Acceso Mutable
103 | - **Descripción:** Permite modificar los elementos del arreglo.
104 | - **Ejemplo:**
105 |
106 | ```rust
107 | let mut letras: [char; 3] = ['a', 'b', 'c'];
108 | letras[0] = 'z';
109 | println!("La primera letra modificada es: {}", letras[0]);
110 | ```
111 |
112 | ### Espacio en Memoria
113 |
114 | El espacio en memoria ocupado por un arreglo es contiguo y depende del tipo y la cantidad de elementos que contiene. A continuación, se ilustra cómo se gestiona en memoria un arreglo:
115 |
116 | **Gráfico: Representación de un Arreglo en Memoria**
117 |
118 | ```plaintext
119 | +-----------+-----------+-----------+-----------+-----------+
120 | | Elemento1 | Elemento2 | Elemento3 | Elemento4 | Elemento5 |
121 | +-----------+-----------+-----------+-----------+-----------+
122 | | i32 | i32 | i32 | i32 | i32 |
123 | +-----------+-----------+-----------+-----------+-----------+
124 | ```
125 |
126 | ### Ventajas y Desventajas de los Arreglos
127 |
128 | #### Ventajas
129 | - **Acceso Rápido:** Proporcionan acceso constante a los elementos mediante índices.
130 | - **Eficiencia de Memoria:** Ocupan un bloque contiguo de memoria, lo que mejora la eficiencia de acceso y manipulación.
131 |
132 | #### Desventajas
133 | - **Tamaño Fijo:** No se pueden redimensionar una vez creados, lo que puede ser limitante en algunos casos.
134 | - **Homogeneidad:** Solo pueden almacenar elementos del mismo tipo.
135 |
136 | ### Conclusión
137 |
138 | Los arreglos en Rust son una herramienta fundamental para almacenar y manipular colecciones de datos del mismo tipo de manera eficiente y segura. Aunque tienen un tamaño fijo y solo pueden contener elementos del mismo tipo, su simplicidad y rapidez de acceso los hacen ideales para muchas aplicaciones comunes. Al comprender cómo utilizar arreglos y sus métodos asociados, los desarrolladores pueden escribir código más eficiente y organizado en Rust.
139 |
--------------------------------------------------------------------------------
/content/2.basic/24.slices.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Slice'
3 | description: 'Comprendiendo los Slices en Rust: Rendimiento, Uso y Comparación con Arreglos'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 155
10 | y: 520
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch04-03-slices#string-slices'
16 | - name: 'Libro de Referencia Rust'
17 | english: true
18 | link: ''
19 | ---
20 | ## Comprendiendo los Slices en Rust: Rendimiento, Uso y Comparación con Arreglos
21 |
22 | Los slices en Rust son una de las características más poderosas y flexibles del lenguaje. A diferencia de los arreglos, los slices permiten trabajar con subsecciones de datos sin necesidad de copiar o duplicar los datos originales. En este blog post, exploraremos en detalle las características, el rendimiento, la representación en memoria y las diferencias entre los slices y los arreglos.
23 |
24 | ### ¿Qué son los Slices?
25 |
26 | Los slices son vistas de datos que permiten acceder a una porción de una colección, como un arreglo o una cadena (`str`). Son especialmente útiles cuando se necesita trabajar con subsecciones de datos sin crear copias adicionales. Los slices se representan mediante referencias y tienen un tamaño dinámico determinado en tiempo de ejecución.
27 |
28 | ### Características de los Slices
29 |
30 | #### 1. Tamaño Dinámico
31 | - **Descripción:** A diferencia de los arreglos, el tamaño de un slice no se conoce en tiempo de compilación y puede cambiar.
32 | - **Ejemplo:**
33 |
34 | ```rust
35 | let arreglo = [1, 2, 3, 4, 5];
36 | let slice = &arreglo[1..4]; // Slice que incluye los elementos de índice 1 a 3
37 | ```
38 |
39 | #### 2. Inmutabilidad por Defecto
40 | - **Descripción:** Los slices son inmutables por defecto, pero se pueden crear slices mutables.
41 | - **Ejemplo:**
42 |
43 | ```rust
44 | let mut arreglo = [1, 2, 3, 4, 5];
45 | let slice_mut = &mut arreglo[1..4]; // Slice mutable
46 | ```
47 |
48 | #### 3. Representación en Memoria
49 | - **Descripción:** Los slices almacenan una referencia al primer elemento y la longitud del slice. Esta estructura les permite ser eficientes en términos de memoria y rendimiento.
50 | - **Ejemplo:**
51 |
52 | ```plaintext
53 | Slice: &arreglo[1..3]
54 | Memoria:
55 | +-----------+-----------+-----------+-----------+-----------+
56 | | Elemento0 | Elemento1 | Elemento2 | Elemento3 | Elemento4 |
57 | +-----------+-----------+-----------+-----------+-----------+
58 | | 1 | 2 | 3 | 4 | 5 |
59 | +-----------+-----------+-----------+-----------+-----------+
60 | ^ ^
61 | | |
62 | Referencia Longitud
63 | 1 ... 3
64 | ```
65 |
66 | ### Diferencias entre Slices y Arreglos
67 |
68 | | Característica | Arreglo | Slice |
69 | |----------------|---------|-------|
70 | | Tamaño | Fijo | Dinámico |
71 | | Memoria | Contigua y estática | Referencia a un segmento de datos |
72 | | Flexibilidad | Menor | Mayor (permite trabajar con subsecciones) |
73 | | Mutabilidad | Puede ser mutable o inmutable | Inmutable por defecto, puede ser mutable |
74 | | Coste de Copia | Copia completa | No requiere copia, trabaja con referencias |
75 |
76 | ### Ventajas de los Slices
77 |
78 | - **Eficiencia de Memoria:** No requieren copiar datos, lo que los hace eficientes en términos de uso de memoria.
79 | - **Flexibilidad:** Permiten trabajar con partes de colecciones sin la necesidad de manipular la colección completa.
80 | - **Seguridad:** Ofrecen seguridad en tiempo de compilación, garantizando que no se acceda fuera de los límites del slice.
81 |
82 | ### Usos Comunes de los Slices
83 |
84 | - **Subsecciones de Arreglos:** Extraer y manipular partes específicas de un arreglo.
85 | - **Procesamiento de Datos:** Pasar partes de colecciones a funciones para su procesamiento.
86 | - **Manejo de Cadenas:** Trabajar con partes de cadenas sin duplicar los datos.
87 |
88 | ### Ejemplo de Uso en Rust
89 |
90 | ```rust
91 | fn main() {
92 | let arreglo = [10, 20, 30, 40, 50];
93 |
94 | // Crear un slice inmutable
95 | let slice = &arreglo[1..4];
96 | println!("Slice: {:?}", slice);
97 |
98 | // Crear un slice mutable
99 | let mut arreglo_mut = [1, 2, 3, 4, 5];
100 | let slice_mut = &mut arreglo_mut[2..4];
101 | slice_mut[0] = 10; // Modifica el elemento en el slice
102 | println!("Arreglo modificado: {:?}", arreglo_mut);
103 | }
104 |
105 | ```
106 |
107 | ### Representación en Memoria de los Slices
108 |
109 | Los slices se representan en memoria como una referencia al primer elemento del slice y la longitud del slice. Esta representación permite un acceso eficiente y seguro a los datos subyacentes.
110 |
111 | **Gráfico: Representación de un Slice en Memoria**
112 |
113 | ```plaintext
114 | Slice: &arreglo[1..3]
115 | Memoria:
116 | +-----------+-----------+-----------+-----------+-----------+
117 | | Elemento0 | Elemento1 | Elemento2 | Elemento3 | Elemento4 |
118 | +-----------+-----------+-----------+-----------+-----------+
119 | | 10 | 20 | 30 | 40 | 50 |
120 | +-----------+-----------+-----------+-----------+-----------+
121 | ^ ^
122 | | |
123 | Referencia Longitud
124 | 1 ... 3
125 | ```
126 |
127 | ### Rendimiento de los Slices
128 |
129 | El uso de slices es altamente eficiente porque evita la necesidad de copiar datos. Los slices simplemente referencian una porción de una colección existente, lo que reduce el coste de operaciones de memoria y mejora el rendimiento en operaciones de acceso y manipulación de datos.
130 |
131 | ### Conclusión
132 |
133 | Los slices en Rust son una herramienta poderosa para trabajar con subsecciones de datos de manera eficiente y segura. Al entender cómo funcionan los slices, cómo se representan en memoria y cómo se diferencian de los arreglos, los desarrolladores pueden aprovechar mejor las capacidades de Rust para escribir código más limpio, eficiente y seguro. Los slices no solo mejoran el rendimiento de las operaciones de manipulación de datos, sino que también proporcionan una mayor flexibilidad en el diseño de programas.
134 |
--------------------------------------------------------------------------------
/content/2.basic/27.string.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'String'
3 | description: 'El Tipo de Dato `String` en Rust: Un Análisis Completo'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 145
10 | y: 560
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch08-02-strings'
16 | - name: 'Post acerca del manejo correcto de Strings en Rust'
17 | english: false
18 | link: 'https://blog.rustlang-es.org/articles/strings'
19 | - name: 'Comprehensive Rust'
20 | english: false
21 | link: 'https://google.github.io/comprehensive-rust/es/std-types/string.html'
22 | - name: 'Documentacion Oficial sobre el Formateo de texto'
23 | english: true
24 | link: 'https://doc.rust-lang.org/std/fmt'
25 | ---
26 | ## El Tipo de Dato `String` en Rust
27 |
28 | El tipo de dato `String` en Rust es una representación dinámica de una cadena de texto, gestionada en heap, lo que le permite crecer y reducirse en tamaño en tiempo de ejecución. En este post, exploraremos cómo funciona `String` en memoria, cuándo es recomendable usarlo, por qué no tiene la trait `Copy` implementada, el concepto de `Cow`, el uso del macro `format!`, y el coste computacional de su uso, destacando la eficiencia de Rust.
29 |
30 | ### ¿Qué es `String` en Rust?
31 |
32 | En Rust, `String` es un tipo de dato dinámico que permite almacenar y manipular cadenas de texto. A diferencia del tipo `&str`, que es una referencia a una cadena de texto inmutable y con una longitud fija, `String` es mutable y puede crecer o reducirse en tamaño.
33 |
34 | ### Funcionamiento en Memoria
35 |
36 | Una instancia de `String` en Rust se compone de tres partes principales:
37 |
38 | 1. **Puntero a los datos:** Apunta al comienzo del bloque de memoria donde se almacenan los datos de la cadena en el heap.
39 | 2. **Capacidad:** Indica cuánta memoria ha sido reservada para la cadena, lo que puede ser más que la longitud actual de la cadena.
40 | 3. **Longitud:** Representa el número de bytes utilizados actualmente en el bloque de memoria.
41 |
42 | #### Gráfico: Representación en Memoria de un `String`
43 |
44 | ```plaintext
45 | +-----------------+
46 | | Puntero | --> [ H e l l o ]
47 | +-----------------+
48 | | Capacidad: 10 |
49 | +-----------------+
50 | | Longitud: 5 |
51 | +-----------------+
52 | ```
53 |
54 | ### ¿Cuándo Usar `String`?
55 |
56 | Es recomendable usar `String` cuando:
57 |
58 | - Necesitas una cadena de texto mutable.
59 | - La longitud de la cadena no es conocida en tiempo de compilación.
60 | - La cadena de texto necesita ser modificada, concatenada o manipulada dinámicamente.
61 |
62 | Para cadenas de texto estáticas y de longitud conocida, es preferible usar `&str`, ya que es más eficiente en términos de memoria y rendimiento.
63 |
64 | ### Por Qué `String` No Implementa `Copy`
65 |
66 | La trait `Copy` en Rust indica que una variable puede ser copiada simplemente haciendo una copia bit a bit de su valor. Sin embargo, `String` no implementa `Copy` debido a que copiar un `String` implicaría duplicar el bloque de memoria en el heap al que apunta. Esto sería costoso en términos de rendimiento y podría causar problemas de administración de memoria, como fugas de memoria si no se maneja correctamente.
67 |
68 | ### El Concepto de `Cow`
69 |
70 | `Cow` (Clone on Write) es un tipo en Rust que permite optimizar las operaciones que pueden requerir clonación de datos. `Cow` puede ser una referencia inmutable a los datos o una copia de los datos si se necesita una versión mutable.
71 |
72 | #### Ejemplo de Uso de `Cow`
73 |
74 | ```rust
75 | use std::borrow::Cow;
76 |
77 | fn procesar_texto(texto: &str) -> Cow {
78 | if texto.contains("rust") {
79 | let mut owned = texto.to_owned();
80 | owned.push_str(" is awesome!");
81 | Cow::Owned(owned)
82 | } else {
83 | Cow::Borrowed(texto)
84 | }
85 | }
86 |
87 | fn main() {
88 | let texto = "I love rust";
89 | let resultado = procesar_texto(texto);
90 | println!("{}", resultado);
91 | }
92 | ```
93 |
94 | ### El Macro `format!`
95 |
96 | El macro `format!` en Rust es similar a `printf` en C y otros lenguajes. Permite construir cadenas de texto a partir de variables y literales.
97 |
98 | #### Ejemplo de Uso de `format!`
99 |
100 | ```rust
101 | fn main() {
102 | let nombre = "Alice";
103 | let edad = 30;
104 | let mensaje = format!("Hola, {nombre}. Tienes {edad} años.");
105 | println!("{mensaje}");
106 | }
107 | ```
108 |
109 | ### Coste Computacional de Usar `String`
110 |
111 | Manipular cadenas de texto dinámicas con `String` implica ciertas operaciones de gestión de memoria que pueden ser costosas:
112 |
113 | - **Asignación en el Heap:** Crear y expandir una `String` implica asignar y posiblemente realocar memoria en el heap.
114 | - **Copia de Datos:** Operaciones que duplican o concatenan `String`s pueden ser costosas si se requiere copiar grandes cantidades de datos.
115 |
116 | Sin embargo, Rust es extremadamente eficiente en la gestión de memoria y rendimiento gracias a su sistema de préstamos y propiedades de tiempo de vida, que minimizan las asignaciones y copias innecesarias.
117 |
118 | ### Optimización y Eficiencia en Rust
119 |
120 | A pesar de los posibles costes computacionales, Rust proporciona varias características que optimizan el uso de `String`:
121 |
122 | - **Reserva Anticipada:** Usar `String::with_capacity` permite reservar memoria anticipadamente, reduciendo la necesidad de realocaciones.
123 |
124 | ```rust
125 | fn main() {
126 | let mut s = String::with_capacity(10);
127 | s.push_str("Hola");
128 | println!("{}", s);
129 | }
130 | ```
131 |
132 | - **Métodos Eficientes:** Los métodos de `String` están optimizados para operaciones comunes, como concatenación y búsqueda, aprovechando las características de bajo nivel de Rust.
133 |
134 | ### Conclusión
135 |
136 | El tipo de dato `String` en Rust es una herramienta poderosa para trabajar con cadenas de texto dinámicas. Aunque puede implicar costes computacionales debido a la gestión de memoria, Rust optimiza estas operaciones para asegurar eficiencia. Al entender cómo funciona `String` en memoria, cuándo usarlo y cómo optimizar su uso, los desarrolladores pueden aprovechar al máximo las capacidades de Rust para manejar cadenas de texto de manera efectiva y segura.
137 |
--------------------------------------------------------------------------------
/content/2.basic/28.range.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Rangos'
3 | description: 'Explorando los Rangos en Rust: Uso en Slices, Vectores, Iteraciones y Más'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -50
10 | y: 600
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial - Match Binding'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch18-03-pattern-syntax#-bindings'
16 | - name: 'Libro de Referencia Rust'
17 | english: true
18 | link: 'https://doc.rust-lang.org/reference/expressions/range-expr.html'
19 | - name: 'Documentacion Oficial sobre los Rangos'
20 | english: true
21 | link: 'https://doc.rust-lang.org/std/ops/struct.Range.html'
22 | ---
23 | ## Rangos en Rust
24 |
25 | En Rust, los rangos son una característica poderosa y versátil que facilita la manipulación de secuencias y colecciones de datos. Los rangos pueden ser utilizados en diversas situaciones, incluyendo slices, vectores, iteraciones, validaciones, y más. Este blog post ofrece una exploración detallada de los rangos en Rust, mostrando ejemplos prácticos y destacando su utilidad en diferentes contextos.
26 |
27 | > [!IMPORTANT]
28 | > Los rangos son una característica mas que un Tipo.
29 |
30 | ### Concepto Básico de Rangos en Rust
31 |
32 | Un rango en Rust se define utilizando la sintaxis `start..end` o `start..=end`, donde `start` es el valor inicial del rango y `end` es el valor final. La diferencia clave entre estas dos sintaxis es que `..` excluye el valor final, mientras que `..=` lo incluye.
33 |
34 | #### Ejemplo:
35 |
36 | ```rust
37 | fn main() {
38 | let rango_exclusivo = 0..5; // 0, 1, 2, 3, 4
39 | let rango_inclusivo = 0..=5; // 0, 1, 2, 3, 4, 5
40 |
41 | println!("Rango exclusivo: {:?}", rango_exclusivo);
42 | println!("Rango inclusivo: {:?}", rango_inclusivo);
43 | }
44 | ```
45 |
46 | ### Uso de Rangos en Slices
47 |
48 | Los rangos son particularmente útiles cuando se trabaja con slices de arreglos. Permiten seleccionar una subsección de un arreglo de manera simple y eficiente.
49 |
50 | #### Ejemplo:
51 |
52 | ```rust
53 | fn main() {
54 | let arreglo = [1, 2, 3, 4, 5];
55 | let slice = &arreglo[1..4]; // Selecciona los elementos en las posiciones 1, 2 y 3
56 |
57 | println!("Slice: {:?}", slice); // Output: [2, 3, 4]
58 | }
59 | ```
60 |
61 | ### Rangos en Vectores
62 |
63 | De manera similar a los slices, los rangos también pueden ser utilizados para obtener subvecotres de un vector. Esto es útil cuando se necesita manipular o acceder a una parte específica del vector.
64 |
65 | #### Ejemplo:
66 |
67 | ```rust
68 | fn main() {
69 | let vector = vec![10, 20, 30, 40, 50];
70 | let subvector = &vector[2..]; // Selecciona los elementos desde la posición 2 hasta el final
71 |
72 | println!("Subvector: {:?}", subvector); // Output: [30, 40, 50]
73 | }
74 | ```
75 |
76 | ### Iteraciones con Rangos
77 |
78 | Los rangos son frecuentemente utilizados para iterar sobre secuencias de números. Esto es muy útil en bucles `for`, donde se necesita ejecutar un bloque de código un número específico de veces.
79 |
80 | #### Ejemplo:
81 |
82 | ```rust
83 | fn main() {
84 | for i in 0..5 {
85 | println!("Número: {}", i); // Output: 0, 1, 2, 3, 4
86 | }
87 |
88 | for j in 0..=5 {
89 | println!("Número: {}", j); // Output: 0, 1, 2, 3, 4, 5
90 | }
91 | }
92 | ```
93 |
94 | ### Validaciones con Rangos
95 |
96 | Los rangos también se pueden utilizar para realizar validaciones, como verificar si un valor está dentro de un rango específico.
97 |
98 | #### Ejemplo:
99 |
100 | ```rust
101 | fn main() {
102 | let edad = 25;
103 | if (18..=30).contains(&edad) {
104 | println!("La edad está dentro del rango permitido.");
105 | } else {
106 | println!("La edad está fuera del rango permitido.");
107 | }
108 | }
109 | ```
110 |
111 | ### Otras Situaciones Donde los Rangos Pueden Destacar
112 |
113 | 1. **Generación de Números:** Los rangos pueden ser utilizados para generar secuencias de números fácilmente.
114 | 2. **Operaciones en Colecciones:** Facilitan la selección y manipulación de subconjuntos de datos en colecciones.
115 | 3. **Particionamiento de Datos:** Permiten dividir datos en partes más pequeñas de manera eficiente.
116 |
117 | ### Gráficos: Visualizando Rangos
118 |
119 | #### Representación de Rangos en Slices
120 |
121 | ```plaintext
122 | Arreglo: [1, 2, 3, 4, 5]
123 | Slice (1..4): [2, 3, 4]
124 |
125 | +---+---+---+---+---+
126 | | 1 | 2 | 3 | 4 | 5 |
127 | +---+---+---+---+---+
128 | ^ ^ ^ ^
129 | | | | |
130 | |---|---|---|
131 | ```
132 |
133 | ### Conclusión
134 |
135 | Los rangos en Rust son una herramienta versátil que facilita la manipulación y acceso a secuencias de datos. Desde slices y vectores hasta iteraciones y validaciones, los rangos ofrecen una manera simple y eficiente de trabajar con subconjuntos de datos. Al comprender y aprovechar las capacidades de los rangos, los desarrolladores pueden escribir código más limpio, eficiente y expresivo en Rust.
136 |
--------------------------------------------------------------------------------
/content/2.basic/3.const-and-statics.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Constantes y Variables Estáticas'
3 | description: 'Constantes y variables Estáticas en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 280
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-01-variables-and-mutability#constantes'
16 | - name: 'Variables y declaraciones en Rust'
17 | english: false
18 | link: 'https://blog.rustlang-es.org/articles/variables-y-declaraciones'
19 | - name: 'Libro de Referencia - Constants'
20 | english: true
21 | link: 'https://doc.rust-lang.org/reference/items/constant-items.html'
22 | - name: 'Libro de Referencia - Statics'
23 | english: true
24 | link: 'https://doc.rust-lang.org/reference/items/static-items.html'
25 | ---
26 | # Constantes y Variables Estáticas en Rust
27 |
28 | Rust es un lenguaje de programación de sistemas conocido por su seguridad y rendimiento. Una de las características importantes que Rust ofrece para manejar valores que no cambian son las **constantes** y las **variables estáticas**. En este post, exploraremos qué son, cómo se declaran, cómo se almacenan en memoria y qué implicancias tienen, especialmente las constantes evaluadas en tiempo de compilación.
29 |
30 | ## Constantes en Rust
31 |
32 | ### Declaración y Uso
33 |
34 | Las constantes en Rust se declaran usando la palabra clave `const`. A diferencia de las variables normales, las constantes deben ser siempre inmutables y su tipo debe ser anotado explícitamente. Se pueden declarar en cualquier ámbito, incluyendo dentro de funciones.
35 |
36 | ```rust
37 | const MAX_POINTS: u32 = 100_000;
38 | ```
39 |
40 | En este ejemplo, `MAX_POINTS` es una constante de tipo `u32` con un valor de `100,000`. Las constantes pueden ser de cualquier tipo primitivo o compuesto (como arreglos y tuplas), siempre y cuando su valor pueda ser evaluado en tiempo de compilación.
41 |
42 | ### Evaluación en Tiempo de Compilación
43 |
44 | Una de las grandes ventajas de las constantes en Rust es que son evaluadas en tiempo de compilación. Esto significa que el valor de la constante se calcula y se inserta directamente en el binario generado, eliminando la necesidad de calcular el valor en tiempo de ejecución, lo cual puede mejorar el rendimiento.
45 |
46 | ```rust
47 | const SECONDS_IN_A_DAY: u32 = 24 * 60 * 60;
48 | ```
49 |
50 | Aquí, `SECONDS_IN_A_DAY` se calcula durante la compilación, asegurando que el cálculo no tenga que realizarse repetidamente en tiempo de ejecución.
51 |
52 | ## Variables Estáticas en Rust
53 |
54 | ### Declaración y Uso
55 |
56 | Las variables estáticas se declaran con la palabra clave `static`. A diferencia de las constantes, las variables estáticas pueden ser mutables (aunque esto es raramente recomendado debido a cuestiones de seguridad y concurrencia).
57 |
58 | ```rust
59 | static HELLO_WORLD: &str = "Hello, world!";
60 | ```
61 |
62 | En este ejemplo, `HELLO_WORLD` es una variable estática de tipo `&str`.
63 |
64 | ### Variables Estáticas Mutables
65 |
66 | Para declarar una variable estática mutable, se usa la palabra clave `mut` después de `static`. Es importante destacar que el acceso a variables estáticas mutables no es seguro por defecto y requiere el uso de bloques `unsafe`.
67 |
68 | ```rust
69 | static mut COUNTER: u32 = 0;
70 |
71 | unsafe {
72 | COUNTER += 1;
73 | }
74 | ```
75 |
76 | > El uso de `unsafe` indica al compilador que el programador asegura manualmente que el acceso concurrente está controlado, lo que puede llevar a errores si no se maneja adecuadamente.
77 |
78 | ## Almacenamiento en Memoria
79 |
80 | ### Constantes
81 |
82 | Las constantes, debido a su naturaleza inmutable y evaluada en tiempo de compilación, generalmente se almacenan directamente en el segmento de texto del binario, que es una sección de solo lectura de la memoria. Esto permite un acceso rápido y eficiente a estos valores en tiempo de ejecución.
83 |
84 | ### Variables Estáticas
85 |
86 | Las variables estáticas, tanto mutables como inmutables, se almacenan en el segmento de datos estáticos del binario. Este segmento es parte de la memoria que se mantiene durante toda la ejecución del programa, lo que significa que las variables estáticas existen durante toda la vida del programa.
87 |
88 | ## Implicancias de Uso
89 |
90 | ### Seguridad y Rendimiento
91 |
92 | El uso de constantes es muy seguro y eficiente en Rust debido a su evaluación en tiempo de compilación y su almacenamiento en el segmento de solo lectura. Esto reduce el riesgo de errores y mejora el rendimiento.
93 |
94 | Las variables estáticas, aunque útiles para ciertos casos, deben usarse con precaución, especialmente las mutables, debido a los posibles problemas de concurrencia y seguridad que pueden surgir. El uso de `unsafe` para acceder a variables estáticas mutables subraya la necesidad de manejar estos accesos con extremo cuidado.
95 |
96 | ### Mejores Prácticas
97 |
98 | - **Prefiere constantes sobre variables estáticas siempre que sea posible**: Las constantes son más seguras y más eficientes.
99 | - **Minimiza el uso de variables estáticas mutables**: Si necesitas mutabilidad global, considera otras alternativas como el uso de estructuras de datos seguras para concurrencia (`Mutex`, `RwLock`, etc.).
100 | - **Aprovecha la evaluación en tiempo de compilación**: Utiliza constantes para valores que pueden ser computados en tiempo de compilación para aprovechar al máximo las optimizaciones del compilador.
101 |
102 | ## Conclusión
103 |
104 | Entender la diferencia entre constantes y variables estáticas en Rust, así como su almacenamiento y uso adecuado, es crucial para escribir código eficiente y seguro. Las constantes, con su evaluación en tiempo de compilación, proporcionan una forma poderosa de definir valores inmutables, mientras que las variables estáticas ofrecen una solución para la persistencia de datos a nivel global, aunque con ciertas advertencias de uso.
105 |
106 | Rust nos ofrece herramientas poderosas y flexibles para manejar inmutabilidad y persistencia de datos, y aprender a usarlas correctamente es esencial para aprovechar todo el potencial del lenguaje.
107 |
--------------------------------------------------------------------------------
/content/2.basic/30.hashmap.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'HashMap'
3 | description: 'Explorando HashMap en Rust: Almacenamiento y Manipulación Eficiente de Datos Asociativos'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'medium'
8 | position:
9 | x: 120
10 | y: 600
11 | # width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch08-03-hash-maps'
16 | - name: 'Comprehensive Rust'
17 | english: true
18 | link: 'https://google.github.io/comprehensive-rust/es/std-types/hashmap.html'
19 | - name: 'Documentacion Oficial'
20 | english: true
21 | link: 'https://doc.rust-lang.org/std/collections/struct.HashMap.html'
22 | ---
23 | ## HashMap en Rust: Almacenamiento y Manipulación Eficiente de Datos Asociativos
24 |
25 | En Rust, el tipo `HashMap` es una colección poderosa que permite almacenar pares clave-valor de manera eficiente. Los `HashMap` son ampliamente utilizados cuando se necesita un acceso rápido y eficiente a los datos basados en claves únicas. En este blog post, exploraremos el funcionamiento de los `HashMap` en Rust, cómo se utilizan, su representación en memoria, sus ventajas, y algunos patrones de uso comunes.
26 |
27 | ### ¿Qué es un `HashMap`?
28 |
29 | Un `HashMap` es una colección que almacena pares clave-valor, donde cada clave es única y se asocia con un valor. Este tipo de datos es ideal para situaciones en las que se necesita acceder, insertar o eliminar elementos rápidamente mediante una clave.
30 |
31 | ### Funcionamiento en Memoria
32 |
33 | Internamente, un `HashMap` se implementa utilizando una tabla hash. La clave se pasa a través de una función hash para determinar la ubicación en la tabla donde se almacenará el valor correspondiente. Esto permite operaciones de búsqueda, inserción y eliminación muy eficientes.
34 |
35 | #### Gráfico: Representación en Memoria de un `HashMap`
36 |
37 | ```plaintext
38 | HashMap:
39 | +-------+------+-------+------+
40 | | Clave | Hash | Índice | Valor |
41 | +-------+------+-------+------+
42 | | "a" | 1234 | 0 | 10 |
43 | | "b" | 5678 | 1 | 20 |
44 | | "c" | 9101 | 2 | 30 |
45 | +-------+------+-------+------+
46 | ```
47 |
48 | ### Creación y Uso de `HashMap`
49 |
50 | Crear y manipular un `HashMap` en Rust es sencillo. A continuación, se muestran algunos ejemplos básicos:
51 |
52 | #### Ejemplo 1: Creación y Adición de Elementos
53 |
54 | ```rust
55 | use std::collections::HashMap;
56 |
57 | fn main() {
58 | let mut mapa = HashMap::new(); // Crear un nuevo HashMap vacío
59 | mapa.insert("clave1", 10); // Insertar pares clave-valor
60 | mapa.insert("clave2", 20);
61 | mapa.insert("clave3", 30);
62 |
63 | println!("{:?}", mapa); // Output: {"clave1": 10, "clave2": 20, "clave3": 30}
64 | }
65 | ```
66 |
67 | #### Ejemplo 2: Acceso a Elementos
68 |
69 | ```rust
70 | use std::collections::HashMap;
71 |
72 | fn main() {
73 | let mut mapa = HashMap::new();
74 | mapa.insert("clave1", 10);
75 | mapa.insert("clave2", 20);
76 |
77 | if let Some(valor) = mapa.get("clave1") {
78 | println!("El valor para 'clave1' es: {}", valor); // Output: El valor para 'clave1' es: 10
79 | }
80 | }
81 | ```
82 |
83 | #### Ejemplo 3: Iteración sobre un `HashMap`
84 |
85 | ```rust
86 | use std::collections::HashMap;
87 |
88 | fn main() {
89 | let mut mapa = HashMap::new();
90 | mapa.insert("clave1", 10);
91 | mapa.insert("clave2", 20);
92 | mapa.insert("clave3", 30);
93 |
94 | for (clave, valor) in &mapa {
95 | println!("Clave: {}, Valor: {}", clave, valor);
96 | }
97 | }
98 | ```
99 |
100 | ### Ventajas de Usar `HashMap`
101 |
102 | - **Acceso Rápido:** Los `HashMap` proporcionan un acceso constante promedio O(1) a los valores mediante sus claves, lo que los hace muy eficientes para búsquedas rápidas.
103 | - **Flexibilidad:** Permiten almacenar pares clave-valor de cualquier tipo, siempre que las claves implementen las traits `Eq` y `Hash`.
104 | - **Versatilidad:** Son útiles en una amplia gama de aplicaciones, desde bases de datos simples hasta sistemas de caché y configuraciones.
105 |
106 | ### Métodos Comunes de `HashMap`
107 |
108 | - `insert()`: Añade un par clave-valor al `HashMap`.
109 | - `get()`: Recupera un valor asociado con una clave específica.
110 | - `remove()`: Elimina un par clave-valor del `HashMap`.
111 | - `contains_key()`: Verifica si una clave está presente en el `HashMap`.
112 | - `entry()`: Proporciona una manera eficiente de insertar o modificar un valor basado en una clave.
113 |
114 | #### Ejemplo: Métodos Comunes
115 |
116 | ```rust
117 | use std::collections::HashMap;
118 |
119 | fn main() {
120 | let mut mapa = HashMap::new();
121 | mapa.insert("clave1", 10);
122 |
123 | // Verificar si una clave existe
124 | if mapa.contains_key("clave1") {
125 | println!("'clave1' existe en el mapa.");
126 | }
127 |
128 | // Uso de entry para insertar o modificar un valor
129 | mapa.entry("clave2").or_insert(20);
130 | mapa.entry("clave1").and_modify(|v| *v += 10);
131 |
132 | println!("{:?}", mapa); // Output: {"clave1": 20, "clave2": 20}
133 | }
134 | ```
135 |
136 | ### Diferencia con Otros Tipos de Colección
137 |
138 | A diferencia de los vectores (`Vec`), que almacenan elementos en un orden específico y permiten el acceso mediante índices, los `HashMap` almacenan elementos en base a claves únicas y permiten el acceso mediante estas claves. Esto los hace más adecuados para aplicaciones donde se necesita acceso rápido a valores específicos basados en claves, en lugar de operaciones de secuencia ordenada.
139 |
140 | ### Coste Computacional de `HashMap`
141 |
142 | El uso de `HashMap` implica un coste computacional para calcular las funciones hash y manejar posibles colisiones. Sin embargo, Rust optimiza estas operaciones para mantener el acceso a los datos lo más eficiente posible. La mayoría de las operaciones tienen un coste promedio de O(1), lo que las hace muy eficientes en la práctica.
143 |
144 | ### Conclusión
145 |
146 | `HashMap` es una herramienta esencial en Rust para trabajar con colecciones de datos asociativos. Su flexibilidad, eficiencia y compatibilidad con las claves únicas lo hacen adecuado para una amplia gama de aplicaciones. Al comprender cómo funciona `HashMap` en memoria, sus ventajas y cómo utilizar sus métodos comunes, los desarrolladores pueden aprovechar al máximo las capacidades de Rust para manejar datos de manera efectiva y segura.
147 |
--------------------------------------------------------------------------------
/content/2.basic/4.shadowing.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Shadowing'
3 | description: 'Shadowing de Variables en Rust: Concepto, Casos de Uso y Gestión en Memoria'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 320
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-01-variables-and-mutability#shadowing'
16 | - name: 'Comprehensive Rust'
17 | english: false
18 | link: 'https://google.github.io/comprehensive-rust/es/control-flow-basics/blocks-and-scopes.html?highlight=shado#%C3%81mbitos-y--shadowing'
19 | ---
20 | # Shadowing de Variables en Rust: Concepto, Casos de Uso y Gestión en Memoria
21 |
22 | Rust, conocido por su seguridad y eficiencia, también ofrece flexibilidad en la gestión de variables a través de una característica llamada **shadowing**. El shadowing permite declarar una nueva variable con el mismo nombre que una anterior en el mismo contexto, "sombreando" la variable original. En este artículo, exploraremos qué es el shadowing, cuándo y cómo se utiliza, y cómo se gestiona en memoria.
23 |
24 | ## ¿Qué es el Shadowing?
25 |
26 | El shadowing en Rust ocurre cuando una nueva variable se declara con el mismo nombre que una anterior en el mismo contexto. Esto no debe confundirse con la mutabilidad; más bien, se trata de crear una nueva variable que oculta a la anterior, de alli el nombre `shadowing` ya que sombreamos la variable anterior.
27 |
28 | ```rust
29 | fn main() {
30 | let x = 5;
31 | let x = x + 1;
32 | {
33 | let x = x * 2;
34 | println!("El valor de x en el contexto interno es: {}", x); // 12
35 | }
36 | println!("El valor de x en el contexto externo es: {}", x); // 6
37 | }
38 | ```
39 |
40 | En este ejemplo, la variable `x` es "sombreada" dos veces: una vez en el contexto principal y otra dentro del contexto interno. Cada declaración de `x` crea una nueva variable, dejando intactas las versiones anteriores dentro de su propio contexto.
41 |
42 | ## Casos de Uso del Shadowing
43 |
44 | ### Refinamiento de Tipos
45 |
46 | Uno de los usos comunes del shadowing es cambiar el tipo de una variable en una nueva declaración.
47 |
48 | ```rust
49 | let spaces = " ";
50 | let spaces = spaces.len();
51 | ```
52 |
53 | Aquí, `spaces` primero es una cadena de texto, y luego se sombrea con una variable de tipo `usize`, que representa la longitud de la cadena.
54 |
55 | ### Transformaciones Intermedias
56 |
57 | El shadowing es útil para aplicar transformaciones intermedias a una variable sin necesitar nombres adicionales.
58 |
59 | ```rust
60 | let price = 100;
61 | let price = price * 2;
62 | let price = price - 10;
63 | ```
64 |
65 | En este ejemplo, `price` se actualiza en cada paso sin la necesidad de crear nuevas variables como `price1`, `price2`, etc.
66 |
67 | ### Evitar la Mutabilidad
68 |
69 | El shadowing puede evitar la necesidad de usar variables mutables, lo cual es preferido en Rust por razones de seguridad.
70 |
71 | ```rust
72 | let mut count = 1;
73 | count += 1;
74 | ```
75 |
76 | se puede escribir como:
77 |
78 | ```rust
79 | let count = 1;
80 | let count = count + 1;
81 | ```
82 |
83 | ## Interpretación en Memoria
84 |
85 | Cada vez que una variable es sombreada, Rust crea una nueva variable en el stack en lugar de modificar la existente. Esto implica que cada versión sombreada de la variable tiene su propia ubicación en memoria.
86 |
87 | > Esto es importante a tener en cuenta ya que no estamos reutilizando el espacio de memoria anteriormente reservado.
88 |
89 | ### Gestión de Memoria
90 |
91 | 1. **Contexto Principal**: Cuando `x` se declara por primera vez en el contexto principal, se asigna memoria en el stack.
92 | 2. **Shadowing en el Mismo Contexto**: Al sombrear `x` en el mismo contexto, se asigna una nueva ubicación en memoria para la nueva `x`, dejando intacta la primera.
93 | 3. **Contexto Interno**: En un contexto interno, otra nueva `x` se crea en el stack y se elimina al salir del contexto.
94 |
95 | Este comportamiento asegura que cada versión de la variable mantenga su valor original dentro de su propio contexto, y que las variables anteriores no sean modificadas accidentalmente.
96 |
97 | ## Implicaciones y Mejores Prácticas
98 |
99 | ### Ventajas del Shadowing
100 |
101 | - **Inmutabilidad**: Permite trabajar con variables inmutables, mejorando la seguridad y legibilidad del código.
102 | - **Claridad**: Facilita la actualización de variables sin introducir nombres adicionales, lo cual puede hacer el código más claro y conciso.
103 | - **Tipo Seguro**: Permite cambiar tipos de variables de manera segura y explícita.
104 |
105 | ### Precauciones
106 |
107 | - **Confusión Potencial**: Un uso excesivo puede llevar a confusión sobre cuál es la variable actual.
108 | - **Uso Intencionado**: Debe ser utilizado de manera intencionada y clara para mejorar la legibilidad y mantenimiento del código.
109 |
110 | ## Conclusión
111 |
112 | El shadowing de variables en Rust es una característica poderosa que permite redefinir variables dentro del mismo contexto, proporcionando flexibilidad sin sacrificar la seguridad. Al comprender cómo funciona el shadowing y cómo se gestionan las variables en memoria, los desarrolladores pueden aprovechar esta herramienta para escribir código más limpio y eficiente. Utilizado correctamente, el shadowing puede simplificar transformaciones de variables y mejorar la inmutabilidad del código, haciendo que los programas en Rust sean más seguros y fáciles de mantener.
113 |
--------------------------------------------------------------------------------
/content/2.basic/5.control-flow.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Control de Flujo'
3 | description: 'Control de Flujo en Rust, como usar if, if-else, match, loop, while y for'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 360
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch03-05-control-flow'
16 | - name: 'Comprehensive Rust'
17 | english: false
18 | link: 'https://google.github.io/comprehensive-rust/es/control-flow-basics.html'
19 | ---
20 | # Control de Flujo en Rust: if, if-else, match, loop, while y for
21 |
22 | Rust es un lenguaje de programación que combina seguridad y rendimiento con una sintaxis clara y poderosa. El control de flujo en Rust se maneja a través de estructuras conocidas como `if`, `if-else`, `match`, y diversos tipos de bucles (`loop`, `while`, `for`). En este artículo, exploraremos cada una de estas construcciones y cómo se utilizan para controlar el flujo de ejecución en un programa Rust, incluyendo los `named loops`.
23 |
24 | ## Condicionales: if y if-else
25 |
26 | Las estructuras condicionales en Rust se manejan mediante `if` y `if-else`. Estas permiten ejecutar bloques de código basados en condiciones booleanas.
27 |
28 | ### if
29 |
30 | La declaración `if` se utiliza para ejecutar un bloque de código solo si una condición es verdadera.
31 |
32 | ```rust
33 | let number = 7;
34 |
35 | if number < 10 {
36 | println!("El número es menor que 10");
37 | }
38 | ```
39 |
40 | En este ejemplo, el mensaje se imprimirá porque la condición `number < 10` es verdadera.
41 |
42 | ### if-else
43 |
44 | La declaración `if-else` se utiliza cuando se desea ejecutar un bloque de código si la condición es verdadera y otro bloque si es falsa.
45 |
46 | ```rust
47 | let number = 7;
48 |
49 | if number < 10 {
50 | println!("El número es menor que 10");
51 | } else {
52 | println!("El número es mayor o igual a 10");
53 | }
54 | ```
55 |
56 | Aquí, se imprime el primer mensaje porque la condición es verdadera.
57 |
58 | ### if-else if-else
59 |
60 | Para manejar múltiples condiciones, se puede usar `else if`.
61 |
62 | ```rust
63 | let number = 15;
64 |
65 | if number < 10 {
66 | println!("El número es menor que 10");
67 | } else if number < 20 {
68 | println!("El número está entre 10 y 19");
69 | } else {
70 | println!("El número es 20 o mayor");
71 | }
72 | ```
73 |
74 | Este ejemplo imprimirá el segundo mensaje porque la condición `number < 20` es verdadera.
75 |
76 | ## match
77 |
78 | La declaración `match` en Rust es una potente estructura de control de flujo que permite manejar múltiples condiciones de manera más clara y concisa que múltiples `if-else`.
79 |
80 | ```rust
81 | let number = 3;
82 |
83 | match number {
84 | 1 => println!("Uno"),
85 | 2 => println!("Dos"),
86 | 3 => println!("Tres"),
87 | _ => println!("Otro número"),
88 | }
89 | ```
90 |
91 | En este ejemplo, se imprimirá "Tres" porque `number` es igual a 3. El carácter `_` actúa como un comodín que coincide con cualquier valor no especificado anteriormente.
92 |
93 | ## Bucles
94 |
95 | Rust proporciona varias maneras de repetir bloques de código: `loop`, `while`, y `for`.
96 |
97 | ### loop
98 |
99 | El bucle `loop` ejecuta un bloque de código indefinidamente hasta que se encuentre una declaración `break`.
100 |
101 | ```rust
102 | let mut counter = 0;
103 |
104 | loop {
105 | counter += 1;
106 | if counter == 10 {
107 | break;
108 | }
109 | }
110 |
111 | println!("El contador llegó a: {}", counter);
112 | ```
113 |
114 | Este bucle incrementa `counter` hasta que alcanza 10, momento en el cual se sale del bucle con `break`.
115 |
116 | #### Named Loops
117 |
118 | Rust permite etiquetar bucles usando `'label_name` para poder referirse a ellos específicamente, lo que es útil para romper o continuar bucles externos desde un bucle interno.
119 |
120 | ```rust
121 | let mut count = 0;
122 | 'outer: loop {
123 | let mut remaining = 10;
124 |
125 | loop {
126 | if remaining == 9 {
127 | break;
128 | }
129 | if count == 2 {
130 | break 'outer;
131 | }
132 | remaining -= 1;
133 | }
134 |
135 | count += 1;
136 | }
137 |
138 | println!("Count terminó en: {}", count);
139 | ```
140 |
141 | En este ejemplo, `break 'outer` rompe el bucle etiquetado como `'outer`, terminando ambos bucles cuando `count` es igual a 2.
142 |
143 | ### while
144 |
145 | El bucle `while` ejecuta un bloque de código mientras una condición sea verdadera.
146 |
147 | ```rust
148 | let mut number = 3;
149 |
150 | while number != 0 {
151 | println!("{}!", number);
152 | number -= 1;
153 | }
154 |
155 | println!("¡Despegue!");
156 | ```
157 |
158 | En este ejemplo, el bucle `while` decrece `number` hasta que llega a 0, imprimiendo cada número en el proceso.
159 |
160 | ### for
161 |
162 | El bucle `for` en Rust se utiliza para iterar sobre una colección, como un rango o una lista.
163 |
164 | #### Iterando sobre un rango
165 |
166 | ```rust
167 | for number in 1..4 {
168 | println!("El número es: {}", number);
169 | }
170 | ```
171 |
172 | Este bucle imprimirá "El número es: 1", "El número es: 2" y "El número es: 3". El rango `1..4` incluye 1 pero excluye 4.
173 |
174 | #### Iterando sobre una colección
175 |
176 | ```rust
177 | let array = [10, 20, 30, 40, 50];
178 |
179 | for element in array.iter() {
180 | println!("El valor es: {}", element);
181 | }
182 | ```
183 |
184 | Aquí, el bucle `for` itera sobre los elementos del arreglo `array`, imprimiendo cada uno de ellos.
185 |
186 | ## Conclusión
187 |
188 | El control de flujo en Rust es versátil y poderoso, permitiendo a los desarrolladores manejar condiciones y bucles de manera clara y eficiente. Las estructuras `if`, `if-else` y `match` facilitan la toma de decisiones, mientras que los bucles `loop`, `while` y `for` permiten la repetición de bloques de código con gran flexibilidad. Los named loops añaden una capa adicional de control para manejar bucles anidados de manera más precisa. Comprender estas construcciones es esencial para escribir programas Rust robustos y eficientes.
189 |
--------------------------------------------------------------------------------
/content/2.basic/7.pattern-matching.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Pattern Matching/Desestruct'
3 | description: 'Entendiendo Pattern Matching y Desestructuración en Rust: Exhaustividad y Seguridad'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 440
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch06-02-match'
16 | - name: 'Comprehensive Rust'
17 | english: false
18 | link: 'https://google.github.io/comprehensive-rust/es/pattern-matching/destructuring.html'
19 | ---
20 | ### Entendiendo Pattern Matching y Desestructuración en Rust: Exhaustividad y Seguridad
21 |
22 | Rust es un lenguaje de programación que combina eficiencia y seguridad sin sacrificar el control sobre los detalles de bajo nivel. Una de las características más poderosas de Rust es su sistema de pattern matching y desestructuración. Estas herramientas permiten escribir código más expresivo y manejable, garantizando al mismo tiempo la exhaustividad en el control de flujo. En este blog post, exploraremos cómo funcionan el pattern matching y la desestructuración en Rust, así como su exhaustividad y beneficios.
23 |
24 | #### ¿Qué es Pattern Matching?
25 |
26 | Pattern matching es una característica que permite comparar una estructura de datos contra varios patrones y, si hay una coincidencia, descomponer la estructura en sus componentes. Rust utiliza la palabra clave `match` para pattern matching, lo que hace que el código sea más legible y manejable.
27 |
28 | ##### Ejemplo Básico
29 |
30 | ```rust
31 | enum Color {
32 | Red,
33 | Green,
34 | Blue,
35 | }
36 |
37 | fn main() {
38 | let color = Color::Green;
39 |
40 | match color {
41 | Color::Red => println!("Color rojo"),
42 | Color::Green => println!("Color verde"),
43 | Color::Blue => println!("Color azul"),
44 | }
45 | }
46 | ```
47 |
48 | En este ejemplo, `match` se utiliza para determinar el valor de la variable `color` y ejecutar el código correspondiente a cada variante del enum `Color`.
49 |
50 | #### Exhaustividad en Pattern Matching
51 |
52 | Una de las características más importantes del pattern matching en Rust es su exhaustividad. Esto significa que todos los casos posibles deben ser manejados, lo que garantiza que no se pase por alto ningún caso. Si se olvida un caso, el compilador emitirá un error, asegurando que se aborden todas las posibilidades.
53 |
54 | ##### Ejemplo de Exhaustividad
55 |
56 | ```rust
57 | enum Animal {
58 | Perro,
59 | Gato,
60 | }
61 |
62 | fn main() {
63 | let mascota = Animal::Perro;
64 |
65 | match mascota {
66 | Animal::Perro => println!("Es un perro"),
67 | Animal::Gato => println!("Es un gato"),
68 | // Falta un caso: Rust emitirá un error si se agrega una variante nueva sin manejarla
69 | }
70 | }
71 | ```
72 |
73 | En este ejemplo, si se añadiera una nueva variante al enum `Animal`, como `Animal::Pez`, el compilador emitiría un error indicando que el match no es exhaustivo, obligando al desarrollador a manejar el nuevo caso.
74 |
75 | #### Desestructuración
76 |
77 | La desestructuración permite dividir una estructura de datos en sus componentes individuales. Rust facilita la desestructuración de arrays, tuplas, structs y enums, lo cual es útil para trabajar con datos complejos.
78 |
79 | ##### Desestructuración de Tuplas
80 |
81 | ```rust
82 | fn main() {
83 | let tupla = (1, "hola", 3.5);
84 |
85 | let (a, b, c) = tupla;
86 |
87 | println!("a: {}, b: {}, c: {}", a, b, c);
88 | }
89 | ```
90 |
91 | En este ejemplo, la tupla `(1, "hola", 3.5)` se desestructura en las variables `a`, `b` y `c`.
92 |
93 | ##### Desestructuración de Structs
94 |
95 | ```rust
96 | struct Punto {
97 | x: i32,
98 | y: i32,
99 | }
100 |
101 | fn main() {
102 | let punto = Punto { x: 5, y: 10 };
103 |
104 | let Punto { x, y } = punto;
105 |
106 | println!("x: {}, y: {}", x, y);
107 | }
108 | ```
109 |
110 | Aquí, el struct `Punto` se desestructura en sus campos `x` e `y`.
111 |
112 | #### Uso Avanzado de Pattern Matching
113 |
114 | Pattern matching en Rust no se limita a estructuras de datos simples, sino que puede manejar patrones complejos, incluyendo guardas, valores anidados y opciones.
115 |
116 | ##### Match con Guardas
117 |
118 | ```rust
119 | fn main() {
120 | let numero = Some(4);
121 |
122 | match numero {
123 | Some(x) if x < 5 => println!("Menos que 5: {}", x),
124 | Some(x) => println!("Mayor o igual a 5: {}", x),
125 | None => println!("Sin valor"),
126 | }
127 | }
128 | ```
129 |
130 | Las guardas (`if x < 5`) permiten añadir condiciones adicionales a los patrones.
131 |
132 | ##### Patrones Anidados
133 |
134 | ```rust
135 | enum Mensaje {
136 | Saludo { id: i32, contenido: String },
137 | }
138 |
139 | fn main() {
140 | let mensaje = Mensaje::Saludo {
141 | id: 1,
142 | contenido: String::from("Hola"),
143 | };
144 |
145 | match mensaje {
146 | Mensaje::Saludo { id, contenido } => {
147 | println!("ID: {}, Contenido: {}", id, contenido);
148 | }
149 | }
150 | }
151 | ```
152 |
153 | Aquí se desestructura un enum con campos nombrados, extrayendo `id` y `contenido`.
154 |
155 | #### Pattern Matching en Funciones
156 |
157 | Pattern matching también se puede usar directamente en las firmas de las funciones para hacer el código más limpio.
158 |
159 | ```rust
160 | fn procesar_punto(Punto { x, y }: Punto) {
161 | println!("x: {}, y: {}", x, y);
162 | }
163 |
164 | fn main() {
165 | let punto = Punto { x: 5, y: 10 };
166 | procesar_punto(punto);
167 | }
168 | ```
169 |
170 | En este ejemplo, el patrón se aplica directamente en los parámetros de la función `procesar_punto`.
171 |
172 | #### Conclusión
173 |
174 | El pattern matching y la desestructuración en Rust son herramientas poderosas que permiten manejar estructuras de datos complejas de manera más expresiva y eficiente. La exhaustividad del pattern matching asegura que todos los posibles casos se manejen adecuadamente, lo que contribuye a la seguridad y robustez del código. Comprender y utilizar estas características efectivamente puede mejorar significativamente la calidad y la mantenibilidad del código en Rust.
175 |
--------------------------------------------------------------------------------
/content/2.basic/8.ownership-borrowing.yml:
--------------------------------------------------------------------------------
1 | title: 'Ownership y Borrowing'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: -700
8 | y: 520
9 | width: 320
10 | align: 'center'
11 | sourcePosition:
12 | none: 'top'
13 | targetPosition:
14 | basic: 'right'
15 |
--------------------------------------------------------------------------------
/content/2.basic/9.ownership-borrowing-concept.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Concepto Basico'
3 | description: 'Entendiendo el Paradigma de Ownership y Borrowing en Rust'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: -700
10 | y: 560
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch04-00-understanding-ownership'
16 | - name: 'Comprehensive Rust'
17 | english: false
18 | link: 'https://google.github.io/comprehensive-rust/es/borrowing.html'
19 | ---
20 | ## Entendiendo el Paradigma de Ownership y Borrowing en Rust
21 |
22 | ### Introducción
23 |
24 | Rust es un lenguaje de programación que ha ganado mucha popularidad por su enfoque en la seguridad y el rendimiento. Uno de los conceptos más revolucionarios y distintivos de Rust es su sistema de **ownership (propiedad)** y **borrowing (préstamo)**. Estos conceptos no solo representan un cambio de paradigma en la gestión de memoria y recursos, sino que también ofrecen garantías de seguridad que se validan en tiempo de compilación, eliminando muchos errores comunes en lenguajes como C y C++.
25 |
26 | ### Ownership: Propiedad y Control Absoluto
27 |
28 | En Rust, cada valor tiene un único propietario, una variable que se encarga de gestionar ese valor. Cuando el propietario sale de su alcance (scope), el valor es automáticamente liberado. Este mecanismo se conoce como **RAII (Resource Acquisition Is Initialization)**, que asegura que los recursos se liberen correctamente sin necesidad de una intervención explícita del programador.
29 |
30 | Ejemplo básico:
31 | ```rust
32 | fn main() {
33 | let x = String::from("Hello");
34 | println!("{}", x); // x es el propietario de la cadena "Hello"
35 | } // x sale del alcance y "Hello" es liberada automáticamente
36 | ```
37 |
38 | ### Borrowing: Préstamo y Compartición Controlada
39 |
40 | A veces es necesario compartir datos entre diferentes partes del programa sin transferir la propiedad. Aquí es donde entra el concepto de **borrowing**. En Rust, se puede pedir prestado un valor de dos formas: **prestamos inmutables** y **prestamos mutables**.
41 |
42 | - **Préstamos Inmutables:** Permiten múltiples accesos de solo lectura.
43 | ```rust
44 | fn main() {
45 | let s = String::from("Hello");
46 | let len = calculate_length(&s); // Se presta de manera inmutable
47 | println!("La longitud de '{}' es {}.", s, len);
48 | }
49 |
50 | fn calculate_length(s: &String) -> usize {
51 | s.len() // Solo se permite leer s
52 | }
53 | ```
54 |
55 | - **Préstamos Mutables:** Permiten un único acceso de lectura/escritura.
56 | ```rust
57 | fn main() {
58 | let mut s = String::from("Hello");
59 | change(&mut s); // Se presta de manera mutable
60 | println!("{}", s);
61 | }
62 |
63 | fn change(s: &mut String) {
64 | s.push_str(", world");
65 | }
66 | ```
67 |
68 | ### Cambio de Paradigma y Pensamiento
69 |
70 | El sistema de ownership y borrowing de Rust introduce un cambio significativo en la manera de pensar y escribir código. A diferencia de otros lenguajes donde la gestión de memoria se realiza manualmente o mediante un recolector de basura (garbage collector), Rust hace estas validaciones en tiempo de compilación. Esto significa que muchos errores comunes, como los accesos a memoria no válida, fugas de memoria y condiciones de carrera, se detectan antes de que el programa se ejecute.
71 |
72 | ### Beneficios de las Validaciones en Compilación
73 |
74 | 1. **Seguridad en Tiempo de Compilación:** El compilador de Rust garantiza que todas las reglas de ownership y borrowing se cumplan antes de que el código se ejecute. Esto elimina una gran clase de errores de programación que en otros lenguajes solo se detectarían en tiempo de ejecución.
75 |
76 | 2. **Eliminación de Fugas de Memoria:** Al asegurar que cada recurso tiene un único propietario responsable de su liberación, Rust previene las fugas de memoria.
77 |
78 | 3. **Prevención de Condiciones de Carrera:** Al restringir los accesos concurrentes a los datos mediante préstamos mutables, Rust evita las condiciones de carrera, un problema común en la programación concurrente.
79 |
80 | 4. **Rendimiento Predecible:** Sin la sobrecarga de un recolector de basura, Rust puede ofrecer un rendimiento más predecible y eficiente, crucial en sistemas de tiempo real y aplicaciones de alto rendimiento.
81 |
82 | ### Conclusión
83 |
84 | El sistema de ownership y borrowing de Rust no es solo una característica más; es un cambio de paradigma que redefine cómo pensamos y manejamos la memoria y los recursos en nuestros programas. Aunque puede requerir un tiempo de adaptación, las garantías y beneficios que ofrece en términos de seguridad y rendimiento hacen que valga la pena el esfuerzo. Rust demuestra que es posible tener un lenguaje que sea tanto seguro como de alto rendimiento, y lo hace mediante la validación de sus estrictas reglas en tiempo de compilación.
85 |
--------------------------------------------------------------------------------
/content/3.error-handling/1.option.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Options'
3 | description: 'Option es una enumeración en Rust que se utiliza para representar valores que pueden o no estar presentes'
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'start'
8 | position:
9 | x: 320
10 | y: 580
11 | width: 320
12 | externalLinks:
13 | - name: 'Libro Oficial'
14 | english: false
15 | link: 'https://book.rustlang-es.org/ch06-01-defining-an-enum'
16 | - name: 'Comprehensive Rust'
17 | english: false
18 | link: 'https://google.github.io/comprehensive-rust/es/std-types/option.html'
19 | - name: 'Documentacion Oficial'
20 | english: true
21 | link: 'https://doc.rust-lang.org/stable/std/option'
22 | - name: '¿Cómo almacena Rust los enum en memoria?'
23 | english: false
24 | link: 'https://blog.rustlang-es.org/articles/como-almacena-rust-los-enum-en-memoria'
25 | ---
26 | ## Entendiendo el Tipo `Option` en Rust: Seguridad y Ausencia de Valores Nulos
27 |
28 | En Rust, el tipo `Option` es una herramienta fundamental que permite manejar de forma segura la ausencia de un valor sin recurrir al temido null. En lugar de utilizar valores nulos que pueden llevar a errores inesperados, Rust introduce `Option`, que garantiza que el manejo de valores opcionales sea explícito y seguro.
29 |
30 | ### ¿Qué es un `Option`?
31 |
32 | `Option` es un enum predefinido en Rust que puede tomar dos valores:
33 |
34 | ```rust
35 | enum Option {
36 | Some(T),
37 | None,
38 | }
39 | ```
40 |
41 | - `Some(T)` indica que hay un valor presente.
42 | - `None` representa la ausencia de un valor.
43 |
44 | ### Funciones Comunes para Trabajar con `Option`
45 |
46 | Rust ofrece múltiples funciones para manipular opciones de forma segura:
47 |
48 | - **is_some() e is_none():** Verifican si un `Option` contiene un valor o no.
49 |
50 | ```rust
51 | let maybe_value: Option = Some(5);
52 | assert!(maybe_value.is_some());
53 |
54 | let no_value: Option = None;
55 | assert!(no_value.is_none());
56 | ```
57 |
58 | - **unwrap() y expect():** Extraen el valor del `Option`, pero si es `None`, `unwrap()` causará un pánico. `expect()` permite proporcionar un mensaje de error personalizado.
59 |
60 | ```rust
61 | let value = maybe_value.unwrap(); // Devuelve 5 o causa un pánico si es None.
62 | ```
63 |
64 | - **map():** Permite aplicar una función al valor dentro de un `Option`, devolviendo un nuevo `Option`.
65 |
66 | ```rust
67 | let maybe_value: Option = Some(5);
68 | let maybe_double = maybe_value.map(|x| x * 2);
69 | assert_eq!(maybe_double, Some(10));
70 | ```
71 |
72 | - **and(), or() y xor():** Estas funciones permiten combinar opciones de manera segura.
73 |
74 | ```rust
75 | let a: Option = Some(2);
76 | let b: Option = Some(3);
77 | let c: Option = None;
78 |
79 | assert_eq!(a.and(b), Some(3)); // Devuelve Some(3)
80 | assert_eq!(a.or(c), Some(2)); // Devuelve Some(2)
81 | assert_eq!(c.or(a), Some(2)); // Devuelve Some(2)
82 | ```
83 |
84 | ### Pattern Matching con `Option`
85 |
86 | El pattern matching es una forma común de interactuar con `Option`. Permite realizar acciones diferentes según el estado de la opción (si es `Some` o `None`):
87 |
88 | ```rust
89 | let maybe_number = Some(10);
90 |
91 | match maybe_number {
92 | Some(value) => println!("El valor es: {}", value),
93 | None => println!("No hay valor"),
94 | }
95 | ```
96 |
97 | ### Interactuar con Múltiples `Option`
98 |
99 | Cuando trabajas con múltiples `Option`, puedes combinarlas utilizando combinadores como `and_then()` o emplear pattern matching para manejar múltiples opciones simultáneamente:
100 |
101 | ```rust
102 | let x: Option = Some(2);
103 | let y: Option = Some(3);
104 |
105 | let result = x.and_then(|x_val| {
106 | y.map(|y_val| x_val + y_val)
107 | });
108 |
109 | assert_eq!(result, Some(5));
110 | ```
111 |
112 | ### Funcionamiento en Memoria
113 |
114 | Rust optimiza la representación en memoria de `Option`. Si `T` es un tipo que puede tener un valor que represente la ausencia de datos (por ejemplo, punteros o números enteros), Rust puede usar una optimización para no consumir espacio adicional para `Option`. De este modo, `Option` es tan eficiente en memoria como el propio tipo base.
115 |
116 | ### Conclusión
117 |
118 | `Option` es un poderoso reemplazo para los valores nulos, brindando seguridad y claridad al código. Al ser un enum, proporciona flexibilidad y un control robusto sobre situaciones donde un valor puede o no estar presente. Al utilizar funciones como `map()`, `unwrap()`, y combinadores, puedes manejar opciones de forma elegante y segura, mientras el pattern matching te permite gestionar fácilmente las variantes de `Option` según tus necesidades.
119 |
120 | Rust garantiza que al trabajar con `Option`, la ausencia de un valor siempre se trate de manera explícita, evitando así una de las fuentes más comunes de errores en otros lenguajes de programación.
121 |
--------------------------------------------------------------------------------
/content/3.error-handling/index.yml:
--------------------------------------------------------------------------------
1 | title: 'Manejo de Errores'
2 | description: ''
3 | draft: true
4 | data:
5 | type: 'custom'
6 | topicLevel: 'medium'
7 | position:
8 | x: 390
9 | y: 700
10 | sourcePosition:
11 | basic: 'left'
12 | targetPosition:
13 | result: 'top'
14 | cargo: 'bottom'
15 | propagation-operator: 'right'
16 |
--------------------------------------------------------------------------------
/content/5.traits/3.integrated.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Traits Integrados"
3 | description: "Entendiendo los Traits Más Importantes en Rust"
4 | draft: true
5 | data:
6 | type: "custom"
7 | topicLevel: "start"
8 | position:
9 | x: 400
10 | y: 980
11 | ---
12 |
13 | ### Entendiendo los Traits Más Importantes en Rust
14 |
15 | Rust incluye una rica colección de _traits_ estándar que permiten a los tipos integrarse con el lenguaje y aprovechar comportamientos reutilizables. Estos _traits_ son contratos que los tipos pueden implementar para adquirir funcionalidades específicas. Aquí exploraremos algunos de los más importantes, explicando sus conceptos y cómo aplicarlos.
16 |
17 | ### **1. El Trait `Default`: Valores Predeterminados**
18 |
19 | El trait `Default` define un método para crear un valor predeterminado para un tipo. Esto es especialmente útil al inicializar estructuras grandes con valores predecibles.
20 |
21 | #### Definición
22 |
23 | ```rust
24 | pub trait Default {
25 | fn default() -> Self;
26 | }
27 | ```
28 |
29 | #### Ejemplo
30 |
31 | ```rust
32 | struct Config {
33 | retries: u32,
34 | verbose: bool,
35 | }
36 |
37 | impl Default for Config {
38 | fn default() -> Self {
39 | Config {
40 | retries: 3,
41 | verbose: false,
42 | }
43 | }
44 | }
45 |
46 | fn main() {
47 | let default_config = Config::default();
48 | println!("Retries: {}, Verbose: {}", default_config.retries, default_config.verbose);
49 | }
50 | ```
51 |
52 | ### **2. Los Traits `Clone` y `Copy`: Clonación y Copia**
53 |
54 | - **`Clone`**: Proporciona un método explícito para crear una copia profunda de un valor.
55 | - **`Copy`**: Es una versión implícita y más ligera de clonación, aplicable solo a tipos que se pueden copiar de manera trivial (como números primitivos).
56 |
57 | #### Definición
58 |
59 | ```rust
60 | pub trait Clone {
61 | fn clone(&self) -> Self;
62 | }
63 |
64 | pub trait Copy: Clone {}
65 | ```
66 |
67 | #### Ejemplo
68 |
69 | ```rust
70 | #[derive(Clone, Copy)]
71 | struct Point {
72 | x: i32,
73 | y: i32,
74 | }
75 |
76 | fn main() {
77 | let p1 = Point { x: 1, y: 2 };
78 | let p2 = p1; // Copia implícita
79 | let p3 = p1.clone(); // Copia explícita
80 | println!("p1: ({}, {}), p2: ({}, {}), p3: ({}, {})", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
81 | }
82 | ```
83 |
84 | #### Nota sobre `Copy`
85 |
86 | Un tipo que implementa `Copy` no puede tener campos que no lo implementen.
87 |
88 | ### **3. Comparación: `PartialEq` y `Eq`**
89 |
90 | Rust proporciona dos traits para comparar tipos:
91 |
92 | - **`PartialEq`**: Permite verificar si dos valores son iguales (`==`) o diferentes (`!=`).
93 | - **`Eq`**: Es un subtipo de `PartialEq` que asegura que el operador `==` siempre sea reflexivo (es decir, `a == a` siempre es verdadero).
94 |
95 | #### Ejemplo
96 |
97 | ```rust
98 | #[derive(PartialEq, Eq)]
99 | struct User {
100 | id: u32,
101 | name: String,
102 | }
103 |
104 | fn main() {
105 | let user1 = User { id: 1, name: "Alice".to_string() };
106 | let user2 = User { id: 1, name: "Alice".to_string() };
107 |
108 | if user1 == user2 {
109 | println!("Users are equal!");
110 | }
111 | }
112 | ```
113 |
114 | ### **4. Ordenamiento: `PartialOrd` y `Ord`**
115 |
116 | - **`PartialOrd`**: Permite comparar valores con `<`, `>`, `<=`, `>=`.
117 | - **`Ord`**: Extiende `PartialOrd` para tipos totalmente ordenables.
118 |
119 | #### Ejemplo
120 |
121 | ```rust
122 | #[derive(PartialOrd, Ord, PartialEq, Eq)]
123 | struct Item {
124 | price: u32,
125 | }
126 |
127 | fn main() {
128 | let item1 = Item { price: 10 };
129 | let item2 = Item { price: 20 };
130 |
131 | if item1 < item2 {
132 | println!("Item1 is cheaper than Item2");
133 | }
134 | }
135 | ```
136 |
137 | ### **5. Traits de Funciones: `Fn`, `FnMut` y `FnOnce`**
138 |
139 | Estos traits representan diferentes tipos de clausuras (_closures_).
140 |
141 | - **`FnOnce`**: Consumo único.
142 | - **`FnMut`**: Clausura mutable.
143 | - **`Fn`**: Clausura inmutable.
144 |
145 | #### Ejemplo
146 |
147 | ```rust
148 | fn execute(operation: F)
149 | where
150 | F: FnOnce(),
151 | {
152 | operation();
153 | }
154 |
155 | fn main() {
156 | let greeting = "Hello".to_string();
157 | execute(|| println!("{}", greeting)); // FnOnce
158 | }
159 | ```
160 |
161 | ### **6. El Trait `Drop`: Limpiar Recursos**
162 |
163 | Permite ejecutar lógica personalizada cuando un valor sale de alcance.
164 |
165 | #### Ejemplo
166 |
167 | ```rust
168 | struct Resource {
169 | name: String,
170 | }
171 |
172 | impl Drop for Resource {
173 | fn drop(&mut self) {
174 | println!("Releasing resource: {}", self.name);
175 | }
176 | }
177 |
178 | fn main() {
179 | let _res = Resource { name: "FileHandle".to_string() };
180 | } // `_res` se libera aquí automáticamente.
181 | ```
182 |
183 | ### **7. Iteradores: `Iterator`**
184 |
185 | El trait `Iterator` es fundamental para trabajar con iteraciones. Define cómo un tipo produce una secuencia de valores.
186 |
187 | #### Definición
188 |
189 | ```rust
190 | pub trait Iterator {
191 | type Item;
192 | fn next(&mut self) -> Option;
193 | }
194 | ```
195 |
196 | #### Ejemplo
197 |
198 | ```rust
199 | struct Counter {
200 | count: u32,
201 | }
202 |
203 | impl Iterator for Counter {
204 | type Item = u32;
205 |
206 | fn next(&mut self) -> Option {
207 | if self.count < 5 {
208 | self.count += 1;
209 | Some(self.count)
210 | } else {
211 | None
212 | }
213 | }
214 | }
215 |
216 | fn main() {
217 | let mut counter = Counter { count: 0 };
218 | while let Some(value) = counter.next() {
219 | println!("Count: {}", value);
220 | }
221 | }
222 | ```
223 |
224 | ### **Conclusión**
225 |
226 | Estos traits estándar son esenciales en Rust, ya que forman la base para operaciones comunes como clonación, comparación, iteración y manejo de recursos. Entender cómo y cuándo usarlos es clave para aprovechar todo el potencial de Rust y escribir código más limpio, seguro y eficiente.
227 |
--------------------------------------------------------------------------------
/content/6.smart-pointers/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Punteros Inteligentes'
3 | description: ''
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'medium'
8 | position:
9 | x: -400
10 | y: 1100
11 | sourcePosition:
12 | traits: 'right'
13 | targetPosition:
14 | concurrency: 'bottom'
15 | ---
16 | # Titulo
17 |
--------------------------------------------------------------------------------
/content/7.concurrency/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Concurrencia y Paralelismo'
3 | description: ''
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'medium'
8 | position:
9 | x: -300
10 | y: 1400
11 | sourcePosition:
12 | smart-pointers: 'left'
13 | targetPosition:
14 | interop: 'right'
15 | ---
16 | # Titulo
17 |
--------------------------------------------------------------------------------
/content/8.interop/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Interoperabilidad'
3 | description: ''
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'other'
8 | position:
9 | x: 100
10 | y: 1400
11 | sourcePosition:
12 | concurrency: 'left'
13 | targetPosition:
14 | ecosystem: 'bottom'
15 | ---
16 | # Titulo
17 |
--------------------------------------------------------------------------------
/content/9.ecosystem/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Ecosistema y Librerias'
3 | description: ''
4 | draft: true
5 | data:
6 | type: 'custom'
7 | topicLevel: 'other'
8 | position:
9 | x: 100
10 | y: 1800
11 | sourcePosition:
12 | interop: 'top'
13 | targetPosition:
14 | continue: 'bottom'
15 | ---
16 | # Titulo
17 |
--------------------------------------------------------------------------------
/content/continue.yml:
--------------------------------------------------------------------------------
1 | title: 'Continua Aprendiendo'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'other'
6 | position:
7 | x: 100
8 | y: 2000
9 | sourcePosition:
10 | ecosystem: 'top'
11 | targetPosition:
12 | none: 'bottom'
13 |
--------------------------------------------------------------------------------
/content/rust.yml:
--------------------------------------------------------------------------------
1 | title: 'Rust'
2 | description: ''
3 | data:
4 | type: 'transparent'
5 | topicLevel: 'start'
6 | position:
7 | x: 390
8 | y: -100
9 | sourcePosition:
10 | none: 'top'
11 | targetPosition:
12 | introduction: 'bottom'
13 |
--------------------------------------------------------------------------------
/crates/preview/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/crates/preview/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "preview"
3 | version.workspace = true
4 | edition.workspace = true
5 | repository.workspace = true
6 |
7 | [dependencies]
8 | walkdir = "2"
9 | imageproc = "0.25"
10 | ab_glyph = "0.2.28"
11 | image = { version = "0.25", default-features = false, features = ["png"] }
12 | serde = { version = "1", default-features = false, features = ["derive"] }
13 | gray_matter = { version = "0.2", default-features = false, features = ["yaml"] }
14 |
--------------------------------------------------------------------------------
/crates/preview/assets/WorkSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RustLangES/rustmap/e8d905e6a0d285b1377286dbaab7287ca251bf00/crates/preview/assets/WorkSans-Bold.ttf
--------------------------------------------------------------------------------
/crates/preview/assets/WorkSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RustLangES/rustmap/e8d905e6a0d285b1377286dbaab7287ca251bf00/crates/preview/assets/WorkSans-Regular.ttf
--------------------------------------------------------------------------------
/crates/preview/assets/bg_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RustLangES/rustmap/e8d905e6a0d285b1377286dbaab7287ca251bf00/crates/preview/assets/bg_preview.png
--------------------------------------------------------------------------------
/crates/preview/src/img.rs:
--------------------------------------------------------------------------------
1 | use std::time::{Duration, Instant};
2 |
3 | use ab_glyph::FontRef;
4 | use image::{Rgba, RgbaImage};
5 |
6 | use crate::mdx::FrontMatter;
7 | use crate::render_time;
8 |
9 | const BLACK: Rgba = Rgba([0, 0, 0, 255]);
10 |
11 | pub fn generate_preview(
12 | bg: &RgbaImage,
13 | bold_font: &FontRef,
14 | regular_font: &FontRef,
15 | out: &str,
16 | matter: FrontMatter,
17 | ) -> Duration {
18 | let time = Instant::now();
19 | let title = matter.title();
20 | let title = title
21 | .get(..47)
22 | .or_else(|| Some(title))
23 | .map(|s| {
24 | if s.len() >= 47 {
25 | format!("{s}...")
26 | } else {
27 | s.to_owned()
28 | }
29 | })
30 | .unwrap();
31 | let description = matter.description();
32 | let name = matter.name();
33 |
34 | let mut img = imageproc::drawing::draw_text(bg, BLACK, 24, 171, 42., bold_font, &title);
35 |
36 | // Description
37 | for (i, s) in chunked_string(description, 45, 8).iter().enumerate() {
38 | imageproc::drawing::draw_text_mut(
39 | &mut img,
40 | BLACK,
41 | 56,
42 | 317 + 28 + (34 * i as i32 + 1),
43 | 34.,
44 | regular_font,
45 | &s,
46 | );
47 | }
48 |
49 | let out = format!("{out}/{name}.png");
50 | img.save_with_format(&out, image::ImageFormat::Png).unwrap();
51 |
52 | let time = time.elapsed();
53 |
54 | println!("Success ({t}): {name} at {out}", t = render_time(time));
55 | time
56 | }
57 |
58 | pub fn chunked_string(s: &str, line_width: usize, max_lines: usize) -> Vec {
59 | let (lines, last) = s.split_whitespace().fold(
60 | (Vec::new(), String::new()),
61 | |(mut lines, mut current_line), word| {
62 | if current_line.len() + word.len() + (!current_line.is_empty() as usize) > line_width {
63 | if !current_line.is_empty() {
64 | lines.push(current_line);
65 | }
66 | current_line = word.to_string();
67 | } else {
68 | if !current_line.is_empty() {
69 | current_line.push(' ');
70 | }
71 | current_line.push_str(word);
72 | }
73 |
74 | if lines.len() == max_lines - 1 && !current_line.is_empty() {
75 | lines.push(current_line);
76 | return (lines, String::new());
77 | }
78 |
79 | (lines, current_line)
80 | },
81 | );
82 | lines
83 | .into_iter()
84 | .chain(std::iter::once(last))
85 | .take(max_lines)
86 | .collect()
87 | }
88 |
89 | #[cfg(test)]
90 | mod tests {
91 | use super::chunked_string;
92 |
93 | #[test]
94 | fn chunks() {
95 | let chunked = chunked_string("El Tipo de Dato `str` en Rust", 50, 8);
96 | assert_eq!(&chunked[..], &["El Tipo de Dato `str` en Rust"]);
97 |
98 | let chunked = chunked_string("Guía de configuracion para los Editores de Texto Más Comunes (Vs Code, Visual Studio, IntelliJ IDEA, Vim, Neovim, Sublime Text)", 50, 8);
99 | assert_eq!(
100 | &chunked[..],
101 | &[
102 | "Guía de configuracion para los Editores de Texto",
103 | "Más Comunes (Vs Code, Visual Studio, IntelliJ",
104 | "IDEA, Vim, Neovim, Sublime Text)",
105 | ]
106 | );
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/crates/preview/src/main.rs:
--------------------------------------------------------------------------------
1 | use std::time::Duration;
2 |
3 | use ab_glyph::FontRef;
4 | use gray_matter::engine::YAML;
5 | use gray_matter::Matter;
6 |
7 | use crate::img::generate_preview;
8 |
9 | mod img;
10 | mod mdx;
11 |
12 | const BOLD_FONT: &[u8] = include_bytes!("../assets/WorkSans-Bold.ttf");
13 | const REGULAR_FONT: &[u8] = include_bytes!("../assets/WorkSans-Regular.ttf");
14 |
15 | fn main() {
16 | let mut args = std::env::args().skip(1);
17 |
18 | let bg = args
19 | .next()
20 | .expect("The first argument must be the background preset file");
21 |
22 | let out = args
23 | .next()
24 | .expect("The seconds argument must be the output directory");
25 |
26 | let files = if args.len() > 1 {
27 | args.collect::>()
28 | } else {
29 | let dir = args.next().expect(
30 | "The third argument must be the directory with the content or files to be processed",
31 | );
32 |
33 | // get all files recursively on dir
34 | walkdir::WalkDir::new(&dir)
35 | .sort_by_file_name()
36 | .into_iter()
37 | .flat_map(|d| {
38 | let Ok(d) = d else {
39 | return None;
40 | };
41 | if d.file_type().is_file() && d.path().extension().is_some_and(|e| e != "yml") {
42 | return d.path().to_str().map(|d| d.to_string());
43 | }
44 | None
45 | })
46 | .collect()
47 | };
48 |
49 | let matter = Matter::::new();
50 |
51 | if std::fs::metadata(&out).is_err() {
52 | println!("Creating directory");
53 | std::fs::create_dir_all(&out).unwrap();
54 | }
55 |
56 | let bold_font = FontRef::try_from_slice(BOLD_FONT).unwrap();
57 | let regular_font = FontRef::try_from_slice(REGULAR_FONT).unwrap();
58 | let bg = image::open(bg).unwrap().into_rgba8();
59 |
60 | let res = files
61 | .iter()
62 | .map(|f| {
63 | generate_preview(
64 | &bg,
65 | &bold_font,
66 | ®ular_font,
67 | &out,
68 | mdx::from_file(f.as_str(), &matter),
69 | )
70 | })
71 | .collect::>();
72 |
73 | println!("\nTotal Image Processed: {c}", c = res.len());
74 | println!("Total: {time}", time = render_time(res.iter().sum()));
75 | println!(
76 | "Max: {time}",
77 | time = render_time(res.clone().into_iter().max().unwrap())
78 | );
79 | println!(
80 | "Min: {time}",
81 | time = render_time(res.clone().into_iter().min().unwrap())
82 | );
83 | println!(
84 | "Avg: {time}",
85 | time = render_time(
86 | res.iter()
87 | .map(Duration::as_nanos)
88 | .reduce(|acc, x| acc + x)
89 | .map(|total| total / res.len() as u128)
90 | .map(|avg| Duration::from_nanos(avg as u64))
91 | .unwrap()
92 | )
93 | );
94 | }
95 |
96 | pub fn render_time(duration: Duration) -> String {
97 | let seconds = duration.as_secs();
98 | let milliseconds = duration.subsec_millis();
99 | let nanoseconds = duration.subsec_nanos();
100 |
101 | format!("{seconds}s {milliseconds}ms {nanoseconds}ns")
102 | }
103 |
--------------------------------------------------------------------------------
/crates/preview/src/mdx.rs:
--------------------------------------------------------------------------------
1 | use gray_matter::engine::YAML;
2 | use gray_matter::Matter;
3 | use serde::{Deserialize, Serialize};
4 |
5 | #[derive(Serialize, Deserialize)]
6 | pub struct FrontMatter {
7 | title: String,
8 | description: String,
9 | pub draft: bool,
10 |
11 | #[serde(skip)]
12 | name: String,
13 | }
14 |
15 | impl FrontMatter {
16 | pub fn name(&self) -> &str {
17 | &self.name
18 | }
19 |
20 | pub fn title(&self) -> &str {
21 | &self.title
22 | }
23 |
24 | pub fn description(&self) -> &str {
25 | &self.description
26 | }
27 | }
28 |
29 | pub fn from_file(path: &str, matter: &Matter) -> FrontMatter {
30 | let content = std::fs::read_to_string(path).unwrap();
31 | let raw = matter.parse(&content).data.unwrap().deserialize().unwrap();
32 |
33 | FrontMatter {
34 | name: path
35 | .replace("./", "")
36 | .replace(".md", "")
37 | .split('/')
38 | .map(|p| p.split('.').skip(1).collect::())
39 | .collect::>()
40 | .join("-")
41 | .trim_matches('-')
42 | .to_string(),
43 | ..raw
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "fenix": {
4 | "inputs": {
5 | "nixpkgs": "nixpkgs",
6 | "rust-analyzer-src": "rust-analyzer-src"
7 | },
8 | "locked": {
9 | "lastModified": 1710829337,
10 | "narHash": "sha256-uDsDTHN7hlx1k9OCukv1DQ9LoTXiM6joTXNV+6LLY1E=",
11 | "owner": "nix-community",
12 | "repo": "fenix",
13 | "rev": "c3383b4ebf6191410babd6c11b4be5e295ec69b1",
14 | "type": "github"
15 | },
16 | "original": {
17 | "owner": "nix-community",
18 | "repo": "fenix",
19 | "type": "github"
20 | }
21 | },
22 | "flake-utils": {
23 | "inputs": {
24 | "systems": "systems"
25 | },
26 | "locked": {
27 | "lastModified": 1710146030,
28 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
29 | "owner": "numtide",
30 | "repo": "flake-utils",
31 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
32 | "type": "github"
33 | },
34 | "original": {
35 | "owner": "numtide",
36 | "repo": "flake-utils",
37 | "type": "github"
38 | }
39 | },
40 | "nixpkgs": {
41 | "locked": {
42 | "lastModified": 1710631334,
43 | "narHash": "sha256-rL5LSYd85kplL5othxK5lmAtjyMOBg390sGBTb3LRMM=",
44 | "owner": "nixos",
45 | "repo": "nixpkgs",
46 | "rev": "c75037bbf9093a2acb617804ee46320d6d1fea5a",
47 | "type": "github"
48 | },
49 | "original": {
50 | "owner": "nixos",
51 | "ref": "nixos-unstable",
52 | "repo": "nixpkgs",
53 | "type": "github"
54 | }
55 | },
56 | "nixpkgs_2": {
57 | "locked": {
58 | "lastModified": 1710806803,
59 | "narHash": "sha256-qrxvLS888pNJFwJdK+hf1wpRCSQcqA6W5+Ox202NDa0=",
60 | "owner": "NixOS",
61 | "repo": "nixpkgs",
62 | "rev": "b06025f1533a1e07b6db3e75151caa155d1c7eb3",
63 | "type": "github"
64 | },
65 | "original": {
66 | "owner": "NixOS",
67 | "ref": "nixos-unstable",
68 | "repo": "nixpkgs",
69 | "type": "github"
70 | }
71 | },
72 | "root": {
73 | "inputs": {
74 | "fenix": "fenix",
75 | "flake-utils": "flake-utils",
76 | "nixpkgs": "nixpkgs_2"
77 | }
78 | },
79 | "rust-analyzer-src": {
80 | "flake": false,
81 | "locked": {
82 | "lastModified": 1710800801,
83 | "narHash": "sha256-MYfxHeKLAhgwgha88ON0SkpNmydpg3Ib93Qny6RQZao=",
84 | "owner": "rust-lang",
85 | "repo": "rust-analyzer",
86 | "rev": "4de0204d58125392aa14d4f224b29f3c54a274e5",
87 | "type": "github"
88 | },
89 | "original": {
90 | "owner": "rust-lang",
91 | "ref": "nightly",
92 | "repo": "rust-analyzer",
93 | "type": "github"
94 | }
95 | },
96 | "systems": {
97 | "locked": {
98 | "lastModified": 1681028828,
99 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
100 | "owner": "nix-systems",
101 | "repo": "default",
102 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
103 | "type": "github"
104 | },
105 | "original": {
106 | "owner": "nix-systems",
107 | "repo": "default",
108 | "type": "github"
109 | }
110 | }
111 | },
112 | "root": "root",
113 | "version": 7
114 | }
115 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
4 | fenix.url = "github:nix-community/fenix";
5 | flake-utils.url = "github:numtide/flake-utils";
6 | };
7 |
8 | outputs = {
9 | self,
10 | nixpkgs,
11 | flake-utils,
12 | ...
13 | } @ inputs:
14 | flake-utils.lib.eachSystem (flake-utils.lib.defaultSystems) (
15 | system: let
16 | pkgs = nixpkgs.legacyPackages.${system};
17 | fenix = inputs.fenix.packages;
18 | # fenix: rustup replacement for reproducible builds
19 | toolchain = fenix.${system}.fromToolchainFile {
20 | file = ./rust-toolchain.toml;
21 | sha256 = "sha256-Ngiz76YP4HTY75GGdH2P+APE/DEIx2R/Dn+BwwOyzZU=";
22 | };
23 | in {
24 | # `nix develop`
25 | devShells.default = pkgs.mkShell {
26 | packages = with pkgs; [
27 | toolchain
28 | pkg-config
29 | cargo-dist
30 | git-cliff
31 | ];
32 | };
33 | }
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/generateContentRoutes.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs').promises;
2 | const path = require('path');
3 |
4 | const contentDir = path.join(process.cwd(), 'content');
5 |
6 | async function walkDir(dir) {
7 | let filesList = [];
8 | const files = await fs.readdir(dir, { withFileTypes: true });
9 | for (const file of files) {
10 | const res = path.resolve(dir, file.name);
11 | if (file.isDirectory()) {
12 | filesList = filesList.concat(await walkDir(res));
13 | } else if (file.isFile() && path.extname(file.name).toLowerCase() === '.md' || path.extname(file.name) != 'yml') {
14 | filesList.push(res);
15 | }
16 | }
17 | return filesList;
18 | }
19 |
20 | function filePathToRoute(filePath) {
21 | let route = filePath
22 | .replace(contentDir, '')
23 | .replace(/\.md$/, '')
24 | .replace(/\\/g, '/'); // Reemplazar backslashes con forward slashes para compatibilidad
25 |
26 | // Manejar index.md
27 | if (route.endsWith('/index')) {
28 | route = route.replace('/index', '');
29 | }
30 |
31 | // Manejar _dir.md (directorios)
32 | route = route.replace(/\/_([^/]+)/g, '');
33 |
34 | // Eliminar números al inicio de los segmentos de la ruta
35 | route = route.split('/').map(segment => segment.replace(/^\d+\./, '')).join('/');
36 |
37 | // Asegurarse de que la ruta comience con '/'
38 | if (!route.startsWith('/')) {
39 | route = '/' + route;
40 | }
41 |
42 | return route || '/';
43 | }
44 |
45 | async function generateContentRoutes() {
46 | const filePaths = await walkDir(contentDir);
47 | const routes = filePaths.map(filePath => filePathToRoute(filePath));
48 | return routes;
49 | }
50 |
51 | generateContentRoutes()
52 | .then(routes => {
53 | console.log('Content Routes:');
54 | console.log(JSON.stringify(routes, null, 2));
55 | })
56 | .catch(error => {
57 | console.error('Error generating routes:', error);
58 | });
59 |
60 | module.exports = generateContentRoutes;
61 |
--------------------------------------------------------------------------------
/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/layouts/hero.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |