1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
|
---
language: rust
contributors:
- ["P1start", "http://p1start.github.io/"]
translators:
- ["Razican", "https://www.razican.com/"]
filename: learnrust-es.rs
lang: es-es
---
Rust es un lenguaje de programación desarrollado por Mozzilla Research. Rust
combina el control del rendimiento a bajo nivel con la comodidad del alto nivel
y garantías de seguridad.
Consigue cumplir estos objetivos sin necesidad de un recolector de basura o
runtime, haciendo posible usar las librerías de Rust como sustituto de C.
La primera versión de Rust, la 0.1, fue lanzada en enero de 2012, y durante 3
años el desarrollo fue tan rápido que hasta hace poco el uso de las versiones
estables no era recomendable, y se aconsejaba usar las compilaciones nocturnas.
El 15 de mayo de 2015 se lanzó Rust 1.0, con una garantía completa de
retrocompatibilidad. A día de hoy los tiempos de compilación han mejorado mucho
desde ese lanzamiento, así como otros aspectos del lenguaje y el compilador.
Rust ha adoptado un modelo de desarrollo por series de publicaciones periódicas,
con lanzamientos cada 6 semanas. Junto con cada lanzamiento, se lanza la beta de
la siguiente versión.
A pesar de que Rust es un lenguaje relativamente de bajo nivel, tiene conceptos
funcionales que generalmente se encuentran en lenguajes de más alto nivel. Esto
hace que Rust sea rápido y al mismo tiempo fácil y eficiente a la hora de
programar.
```rust
// Esto es un comentario. Los comentarios de una sola línea se hacen así...
/* ...y los de múltiples líneas así */
//////////////////////////
// 1. Conceptos básicos //
//////////////////////////
// Funciones
// `i32` es el tipo para enteros de 32 bits con signo
fn suma2(x: i32, y: i32) -> i32 {
// Retorno implícito (sin punto y coma)
x + y
}
// Función principal
fn main() {
// N;umeros //
// Bindings (variables) inmutables
let x: i32 = 1;
// Sufijos para enteros / floats
let y: i32 = 13i32;
let f: f64 = 1.3f64;
// Inferencia de tipos
// La mayor parte del tiempo, el compilador de Rust puede inferir el tipo de
// una variable, por lo que no necesitas escribir una anotación de tipo
// explícita. A lo largo de este tutorial, los tipos están anotados
// explícitamente en varios sitios, pero solo con propósito demostrativo. La
// inferencia de tipos puede manejar esto por ti la mayor parte del tiempo.
let x_implicita = 1;
let f_implicita = 1.3;
// Aritmética
let sum = x + y + 13;
// Variable mutable
let mut mutable = 1;
mutable = 4;
mutable += 2;
// Strings (cadenas de caracteres) //
// Strings literales
let x: &str = "hola mundo!";
// Impresión por consola
println!("{} {}", f, x); // 1.3 hola mundo!
// Un `String` – una cadena en memoria dinámica (heap)
let s: String = "hola mundo".to_string();
// Una porión de cadena (slice) – una vista inmutable a otra cadena
// Esto es básicamente un puntero inmutable a un string string – en realidad
// no contiene los caracteres de la cadena, solo un puntero a algo que los
// tiene (en este caso, `s`)
let s_slice: &str = &s;
println!("{} {}", s, s_slice); // hola mundo hola mundo
// Vectores/arrays //
// A fixed-size array
let cuatro_enteros: [i32; 4] = [1, 2, 3, 4];
// Un array dinámico (vector)
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
vector.push(5);
// Una porción (slice) – una vista inmutable a un vector o array
// Esto es parecido a un slice de un string, pero para vectores
let slice: &[i32] = &vector;
// Usa `{:?}` para imprimir algo en estilo debug
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
// Tuplas //
// Una tupla es un conjunto de tamaño fijo de valores. Pueden ser de diferente tipo.
let x: (i32, &str, f64) = (1, "hola", 3.4);
// Desestructurando `let`
let (a, b, c) = x;
println!("{} {} {}", a, b, c); // 1 hola 3.4
// Indexando
println!("{}", x.1); // hola
//////////////
// 2. Tipos //
//////////////
// Estructuras
struct Punto {
x: i32,
y: i32,
}
let origen: Punto = Punto { x: 0, y: 0 };
// Una estructura con campos sin nombre, una ‘estructura de tupla’
struct Punto2(i32, i32);
let origen2 = Punto2(0, 0);
// Enums básicos como en C
enum Direccion {
Izquierda,
Derecha,
Arriba,
Abajo,
}
let arriba = Direccion::Arriba;
// Enum con campos
enum OpcionalI32 {
UnI32(i32),
Nada,
}
let dos: OpcionalI32 = OpcionalI32::UnI32(2);
let nada = OpcionalI32::Nada;
// Genéricos //
struct Foo<T> { bar: T }
// Esto está definido en la librería estándar como `Option`
enum Opcional<T> {
AlgunVal(T),
SinVal,
}
// Métodos //
impl<T> Foo<T> {
// Los métodos reciben un parámetro explícito `self`
fn get_bar(self) -> T {
self.bar
}
}
let un_foo = Foo { bar: 1 };
println!("{}", un_foo.get_bar()); // 1
// Traits (conocidos como interfaces o typeclasses en otros lenguajes) //
trait Frobnicate<T> {
fn frobnicate(self) -> Option<T>;
}
impl<T> Frobnicate<T> for Foo<T> {
fn frobnicate(self) -> Option<T> {
Some(self.bar)
}
}
let otro_foo = Foo { bar: 1 };
println!("{:?}", otro_foo.frobnicate()); // Some(1)
/////////////////////////////////
// 3. Comparación con patrones //
/////////////////////////////////
let foo = OpcionalI32::UnI32(1);
match foo {
OpcionalI32::UnI32(n) => println!("es un i32: {}", n),
OpcionalI32::Nada => println!("no es nada!"),
}
// comparación de patrones avanzada
struct FooBar { x: i32, y: OpcionalI32 }
let bar = FooBar { x: 15, y: OpcionalI32::UnI32(32) };
match bar {
FooBar { x: 0, y: OpcionalI32::UnI32(0) } =>
println!("Los números son cero!"),
FooBar { x: n, y: OpcionalI32::UnI32(m) } if n == m =>
println!("Los números son iguales"),
FooBar { x: n, y: OpcionalI32::UnI32(m) } =>
println!("Números diferentes: {} {}", n, m),
FooBar { x: _, y: OpcionalI32::Nada } =>
println!("El segudo número no es nada!"),
}
/////////////////////////
// 4. Flujo de control //
/////////////////////////
// bucles `for`
let array = [1, 2, 3];
for i in array.iter() {
println!("{}", i);
}
// Rangos
for i in 0u32..10 {
print!("{} ", i);
}
println!("");
// imprime `0 1 2 3 4 5 6 7 8 9 `
// `if`
if 1 == 1 {
println!("Las matemáticas funcionan!");
} else {
println!("Oh no...");
}
// `if` como una expresión
let valor = if true {
"bueno"
} else {
"malo"
};
// bucle `while`
while 1 == 1 {
println!("El universo está funcionando correctamente.");
}
// Bucle infinito
loop {
println!("Hola!");
}
////////////////////////////////////////
// 5. Seguridad de memoria y punteros //
////////////////////////////////////////
// Posesión de punteros – solo uno puede ‘poseer’ un puntero en cada momento
// Esto significa que cuando la `Box` queda fuera del ámbito, puede ser
// liberada automáticamente de manera segura.
let mut mio: Box<i32> = Box::new(3);
*mio = 5; // dereferenciar
// Aquí, `ahora_es_mio`, toma posesión de `mio`. En otras palabras, `mio` se
// mueve.
let mut ahora_es_mio = mio;
*ahora_es_mio += 2;
println!("{}", ahora_es_mio); // 7
// println!("{}", mio); // esto no compilaría, porque `now_its_mine` es el
// que posee el puntero
// Referencia – un puntero inmutable que referencia a otro dato
// Cuando se crea una referencia a un valor, decimos que el valor ha sido
// ‘tomado prestado’.
// Mientras un valor está prestado como inmutable, no puede ser modificado o
// movido.
// Una prestación dura hasta el fin del ámbito en el que se creó.
let mut var = 4;
var = 3;
let ref_var: &i32 = &var;
println!("{}", var); // A diferencia de `mio`, `var` se puede seguir usando
println!("{}", *ref_var);
// var = 5; // esto no compilaría, porque `var` está prestada
// *ref_var = 6; // esto tampoco, porque `ref_var` es una referencia
// inmutable
// Referencia mutable
// Mientras que un valor está prestado como mutable, no puede ser accedido
// desde ningún otro sitio.
let mut var2 = 4;
let ref_var2: &mut i32 = &mut var2;
*ref_var2 += 2; // '*' se usa para apuntar al var2 prestado como mutable
println!("{}", *ref_var2); // 6 , //var2 no compilaría. //ref_var2 es de
// tipo &mut i32, por lo que guarda una
// referencia a un i32 no el valor.
// var2 = 2; // esto no compilaría porque `var2` está prestado
}
```
## Lectura adicional
Rust es mucho más que esto. Esto es solo lo más básico para que puedas entender
las cosas más importantes. Para aprender más sobre Rust, lee [The Rust
Programming Language](http://doc.rust-lang.org/book/index.html) y echa un
vistazo al subreddit [/r/rust](http://reddit.com/r/rust). Los compañeros en el
canal #rust en irc.mozilla.org también son muy buenos con los recien llegados.
También puedes acceder a [Rust users](https://users.rust-lang.org/) a pedir
ayuda o a [Rust internals](https://internals.rust-lang.org/) para aprender más
sobre el lenguaje y colaborar en su desarrollo.
También puedes probar Rust con un compilador online en el oficial [Rust
playpen](http://play.rust-lang.org) o en la [web principal de
Rust](http://rust-lang.org).
|