Sintaxis Básica de Rust
En este capítulo exploraremos los fundamentos de la sintaxis de Rust. Aprenderás sobre variables, funciones, comentarios y las convenciones básicas del lenguaje.
Tu Primer Programa
fn main () {
println! ( "¡Hola, mundo!" );
}
Este simple programa ilustra varios conceptos importantes:
fn define una función
main es el punto de entrada del programa
println! es un macro (nota el !)
Los bloques de código van entre llaves {}
Variables y Mutabilidad
En Rust, las variables son inmutables por defecto . Esta es una característica de seguridad fundamental.
Variables Inmutables
fn main () {
let x = 5 ;
println! ( "El valor de x es: {x}" );
// x = 6; // ¡Esto causaría un error de compilación!
}
Variables Mutables
Para hacer una variable mutable, usa la palabra clave mut:
fn main () {
let mut x = 5 ;
println! ( "El valor de x es: {x}" );
x = 6 ; // ¡Ahora esto es válido!
println! ( "El valor de x es: {x}" );
}
Constantes
Las constantes son siempre inmutables y deben tener un tipo explícito:
const TRES_HORAS_EN_SEGUNDOS : u32 = 60 * 60 * 3 ;
fn main () {
println! ( "Tres horas son {} segundos" , TRES_HORAS_EN_SEGUNDOS );
}
Diferencias entre constantes y variables inmutables:
Las constantes se evalúan en tiempo de compilación
Se pueden declarar en cualquier scope, incluyendo el global
Solo pueden asignarse a expresiones constantes
Por convención, se nombran en MAYÚSCULAS con guiones bajos
Shadowing (Sombreado)
Puedes declarar una nueva variable con el mismo nombre que una anterior:
fn main () {
let x = 5 ;
let x = x + 1 ; // Nueva variable x que "sombrea" la anterior
{
let x = x * 2 ; // Otra nueva variable x en este scope
println! ( "El valor de x en el scope interno es: {x}" ); // 12
}
println! ( "El valor de x es: {x}" ); // 6
}
Ventajas del shadowing:
Puedes cambiar el tipo de la variable
Mantiene la inmutabilidad por defecto
Evita tener que inventar nombres como x_str, x_num
fn main () {
let espacios = " " ; // String
let espacios = espacios . len (); // usize - ¡diferente tipo!
println! ( "Número de espacios: {espacios}" );
}
Funciones
Las funciones son bloques de código reutilizables. En Rust, el estilo es usar snake_case para nombres de funciones.
Función Básica
fn main () {
println! ( "¡Hola, mundo!" );
otra_funcion ();
}
fn otra_funcion () {
println! ( "Esta es otra función." );
}
Funciones con Parámetros
fn main () {
saludar ( "Alice" , 25 );
saludar ( "Bob" , 30 );
}
fn saludar (nombre : & str , edad : u32 ) {
println! ( "¡Hola {nombre}! Tienes {edad} años." );
}
Importante: En Rust, debes especificar el tipo de cada parámetro.
Funciones que Retornan Valores
fn main () {
let resultado = sumar ( 5 , 3 );
println! ( "5 + 3 = {resultado}" );
let (suma, producto) = sumar_y_multiplicar ( 4 , 7 );
println! ( "4 + 7 = {suma}, 4 * 7 = {producto}" );
}
fn sumar (a : i32 , b : i32 ) -> i32 {
a + b // Expresión de retorno (sin punto y coma)
}
fn sumar_y_multiplicar (a : i32 , b : i32 ) -> ( i32 , i32 ) {
(a + b, a * b) // Retornando una tupla
}
Conceptos importantes:
-> indica el tipo de retorno
Las expresiones no llevan punto y coma
Las declaraciones terminan con punto y coma
La última expresión se retorna automáticamente
También puedes usar return explícitamente
Statements vs Expressions
fn main () {
// Statement (declaración) - no retorna un valor
let x = 5 ;
// Expression (expresión) - retorna un valor
let y = {
let x = 3 ;
x + 1 // Sin punto y coma - es una expresión
};
println! ( "El valor de y es: {y}" ); // 4
// Esto sería un error porque las declaraciones no retornan valores:
// let x = (let y = 6); // ERROR!
}
Comentarios
Comentarios de Línea
fn main () {
// Este es un comentario de línea
println! ( "¡Hola!" ); // También puedes comentar al final de la línea
}
Comentarios de Documentación
/// Esta función suma dos números.
///
/// # Ejemplos
///
/// ```
/// let resultado = sumar(2, 3);
/// assert_eq!(resultado, 5);
/// ```
fn sumar (a : i32 , b : i32 ) -> i32 {
a + b
}
/// Esta estructura representa una persona.
///
/// # Campos
///
/// * `nombre` - El nombre de la persona
/// * `edad` - La edad de la persona
struct Persona {
nombre : String ,
edad : u32 ,
}
Los comentarios /// generan documentación HTML con cargo doc.
Macros Básicos
println! - Imprimir en Consola
fn main () {
// Impresión básica
println! ( "¡Hola, mundo!" );
// Con variables
let nombre = "Alice" ;
let edad = 30 ;
println! ( "Mi nombre es {nombre} y tengo {edad} años" );
// Con posiciones
println! ( "Me llamo {0} y tengo {1} años. Sí, {0} es mi nombre." , nombre, edad);
// Con nombres
println! ( "Me llamo {nombre} y tengo {edad} años" , nombre = "Bob" , edad = 25 );
// Con formato
println! ( "Pi es aproximadamente {:.2}" , 3.14159 ); // 3.14
println! ( "En hexadecimal: {:x}" , 255 ); // ff
println! ( "En binario: {:b}" , 8 ); // 1000
}
print! vs println!
fn main () {
print! ( "Este texto " );
print! ( "está en " );
println! ( "la misma línea" );
println! ( "Esta es una nueva línea" );
}
eprintln! - Imprimir Errores
fn main () {
println! ( "Esto va a stdout" );
eprintln! ( "Esto va a stderr" );
}
Convenciones de Nombres
Rust tiene convenciones específicas para nombres:
snake_case
Variables : mi_variable
Funciones : mi_funcion
Módulos : mi_modulo
SCREAMING_SNAKE_CASE
Constantes : MI_CONSTANTE
Valores estáticos : MI_VALOR_ESTATICO
PascalCase
Tipos (structs, enums) : MiStruct
Traits : MiTrait
// Ejemplos de convenciones
const PI : f64 = 3.14159 ;
static MAX_USUARIOS : u32 = 1000 ;
struct Usuario {
nombre_completo : String ,
edad : u32 ,
}
fn crear_usuario (nombre : String , edad : u32 ) -> Usuario {
Usuario {
nombre_completo : nombre,
edad,
}
}
fn main () {
let nuevo_usuario = crear_usuario ( String :: from ( "Alice" ), 30 );
println! ( "Usuario creado: {}" , nuevo_usuario . nombre_completo);
}
Ejercicios Prácticos
Ejercicio 1: Calculadora Básica
fn main () {
let a = 10 ;
let b = 3 ;
println! ( "{a} + {b} = {}" , sumar (a, b));
println! ( "{a} - {b} = {}" , restar (a, b));
println! ( "{a} * {b} = {}" , multiplicar (a, b));
println! ( "{a} / {b} = {}" , dividir (a, b));
}
fn sumar (a : i32 , b : i32 ) -> i32 {
a + b
}
fn restar (a : i32 , b : i32 ) -> i32 {
a - b
}
fn multiplicar (a : i32 , b : i32 ) -> i32 {
a * b
}
fn dividir (a : i32 , b : i32 ) -> f64 {
a as f64 / b as f64
}
Ejercicio 2: Temperatura
fn main () {
let celsius = 25.0 ;
let fahrenheit = celsius_a_fahrenheit (celsius);
println! ( "{celsius}°C = {fahrenheit:.1}°F" );
let fahrenheit = 77.0 ;
let celsius = fahrenheit_a_celsius (fahrenheit);
println! ( "{fahrenheit}°F = {celsius:.1}°C" );
}
fn celsius_a_fahrenheit (celsius : f64 ) -> f64 {
celsius * 9.0 / 5.0 + 32.0
}
fn fahrenheit_a_celsius (fahrenheit : f64 ) -> f64 {
(fahrenheit - 32.0 ) * 5.0 / 9.0
}
Puntos Clave para Recordar
Las variables son inmutables por defecto - usa mut cuando necesites mutabilidad
Las funciones requieren tipos explícitos para parámetros y valores de retorno
Las expresiones no llevan punto y coma al final si quieres que retornen un valor
Usa snake_case para variables y funciones , PascalCase para tipos
Los comentarios /// generan documentación
println! es un macro , no una función (nota el !)
Anterior
Configuracion Entorno
Siguiente
Tipos Datos