Capítulo 1. Verdad o consecuencia

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Y la verdad es que no sabemos nada

They Might Be Giants, "Ana Ng" (1988)

En este capítulo, te mostraré cómo organizar, ejecutar y probar un programa Rust. Utilizaré una plataforma Unix (macOS) para explicar algunas ideas básicas sobre los programas de línea de comandos.Sólo algunas de estas ideas se aplican al sistema operativo Windows, pero los programas Rust en sí funcionarán igual independientemente de la plataforma que utilices.

Aprenderás a hacer lo siguiente:

  • Compilar código Rust en un ejecutable

  • Utiliza Cargo para iniciar un nuevo proyecto

  • Utiliza la variable de entorno $PATH

  • Incluir cajas Rust externas de crates.io

  • Interpretar el estado de salida de un programa

  • Utilizar comandos y opciones comunes del sistema

  • Escribe versiones en Rust de los programas true y false

  • Organizar, escribir y ejecutar pruebas

Empezar con "¡Hola, mundo!"

Parece que la forma universalmente aceptada de empezar a aprender un lenguaje de programación es imprimir "¡Hola, mundo!" en la pantalla. Cambia a un directorio temporal con cd /tmp para escribir este primer programa. Sólo estamos trasteando, así queaún nonecesitamos undirectorioreal.A continuación, enciende un editor de texto y escribe el siguiente código en un archivo llamado hola.rs:

fn main() { 1
    println!("Hello, world!"); 2
} 3
1

Las funciones se definen mediante fn. El nombre de esta función es main.

2

println! (imprimir línea) es una macro e imprimirá texto en STDOUT (pronunciado salida estándar). El punto y coma indica el final de la sentencia.

3

El cuerpo de la función se encierra entre llaves.

Rust se iniciará automáticamente en la función main. Los argumentos de la función aparecen dentro de los paréntesis que siguen al nombre de la función. Como no hay argumentos en main(), la función no toma argumentos. Lo último que señalaré aquí es que println! parece una función, pero en realidad es una macro, que en esencia es código que escribe código. Todas las demás macros que utilizo en este libro -como assert! y vec!-también terminan con un signo de exclamación.

Para ejecutar este programa, primero debes utilizar el compilador de Rust, rustc, para compilar el código de forma que tu ordenador pueda ejecutarlo:

$ rustc hello.rs

En Windows, utilizarás este comando:

> rustc.exe .\hello.rs

Si todo va bien, no saldrá nada del comando anterior, pero ahora deberías tener un nuevo archivo llamado hola en macOS y Linux o hola.exe en Windows. Se trata de un archivo codificado en binario que puede ser ejecutado directamente por tu sistema operativo, por lo que es habitual llamarlo ejecutable o binario. En macOS, puedes utilizar el comando file para ver qué tipo de archivo es:

$ file hello
hello: Mach-O 64-bit executable x86_64

Deberías poder ejecutar el programa para ver un mensaje encantador y sincero:

$ ./hello 1
Hello, world!
1

El punto (.) indica el directorio actual.

Consejo

En breve hablaré de la variable de entorno $PATH, que enumera los directorios en los que buscar programas para ejecutarlos. El directorio de trabajo actual nunca se incluye en esta variable para evitar que se ejecute subrepticiamente código malicioso. Por ejemplo, un malhechor podría crear un programa llamado ls que ejecutara rm -rf / en un intento de borrar todo tu sistema de archivos. Si por casualidad lo ejecutaras como usuario root, te arruinaría todo el día.

En Windows, puedes ejecutarlo así:

> .\hello.exe
Hello, world!

Enhorabuena si ése ha sido tu primer programa en Rust. A continuación, te mostraré cómo organizar mejor tu código.

Organizar un directorio de proyectos de óxido

En tus proyectos de Rust de , probablemente escribirás muchos archivos de código fuente y también utilizarás código de otras personas de lugares como crates.io. Lo mejor es crear un directorio para cada proyecto, con un subdirectorio src para los archivos de código fuente de Rust.En un sistema Unix, primero tendrás que eliminar el binario hello con el comando rm hello porque ése es el nombre del directorio que vas a crear.A continuación, puedes utilizar el siguiente comando para crear la estructura del directorio:

$ mkdir -p hello/src 1
1

El comando mkdir creará un directorio. La opción -p dice que hay que crear directorios padre antes de crear directorios hijo. PowerShell no requiere esta opción.

Mueve el archivo fuente hello.rs a hello/src utilizando el comando mv:

$ mv hello.rs hello/src

Utiliza el comando cd para cambiar a ese directorio y volver a compilar tu programa:

$ cd hello
$ rustc src/hello.rs

Ahora deberías tener un ejecutable hello en el directorio. Utilizaré el comando tree (que puede que necesites instalar) para mostrarte el contenido de mi directorio:

$ tree
.
├── hello
└── src
    └── hello.rs

Esta es la estructura básica de un proyecto Rust sencillo.

Crear y ejecutar un proyecto con Cargo

Una forma más fácil de empezar un nuevo proyecto Rust es utilizar la herramienta Cargo. Puedes borrar tu directorio temporal hello:

$ cd .. 1
$ rm -rf hello 2
1

Cambia al directorio padre, que se indica con dos puntos (..).

2

La opción -r recursiva eliminará el contenido de un directorio, y la opción -f forzar omitirá cualquier error.

Si quieres guardar el siguiente programa, cámbiate al directorio de soluciones de tus proyectos. A continuación, inicia de nuevo tu proyecto utilizando Cargo de esta forma:

$ cargo new hello
     Created binary (application) `hello` package

Esto debería crear un nuevo directorio hola en el que puedes cambiar. Utilizaré de nuevo tree para mostrarte el contenido:

$ cd hello
$ tree
.
├── Cargo.toml 1
└── src 2
    └── main.rs 3
1

Cargo.toml es un archivo de configuración del proyecto. La extensión .toml significa Lenguaje Mínimo y Obvio de Tom.

2

El directorio src es para los archivos del código fuente de Rust.

3

main.rs es el punto de inicio por defecto de los programas Rust.

Puedes utilizar el siguiente comando cat (para concatenar) para ver el contenido del único archivo fuente que Cargo ha creado (en el Capítulo 3, escribirás una versión Rust de cat):

$ cat src/main.rs
fn main() {
    println!("Hello, world!");
}

Más bien que utilizar rustc para compilar el programa, esta vez utiliza cargo run para compilar el código fuente y ejecutarlo en un solo comando:

$ cargo run
   Compiling hello v0.1.0 (/private/tmp/hello) 1
    Finished dev [unoptimized + debuginfo] target(s) in 1.26s
     Running `target/debug/hello`
Hello, world! 2
1

Las tres primeras líneas son información sobre lo que está haciendo Cargo.

2

Este es el resultado del programa.

Si quieres que Cargo no imprima mensajes de estado sobre la compilación y ejecución del código, puedes utilizar la opción -q, o --quiet:

$ cargo run --quiet
Hello, world!

Después de ejecutar el programa utilizando Cargo, utiliza el comando ls para listar el contenido del directorio de trabajo actual.(Escribirás una versión Rust de ls en el Capítulo 14.) Debería haber un nuevo directorio llamado target. Por defecto, Cargo construirá un target de depuración, por lo que verás el directorio target/debug que contiene los artefactos de construcción:

$ ls
Cargo.lock  Cargo.toml  src/        target/

Puedes utilizar el comando tree de antes o el comando find (escribirás una versión Rust de find en el Capítulo 7) para ver todos los archivos que Cargo y Rust crearon.El archivo ejecutable que se ejecutó debe existir como target/debug/hello. Puedes ejecutarlo directamente:

$ ./target/debug/hello
Hello, world!

En resumen, Cargo encontró el código fuente en src/main.rs, utilizó la función main de allí para construir el archivo binario target/debug/hello, y luego lo ejecutó. Pero, ¿por qué el archivo binario se llamaba hello y no main? Para responder a eso, mira Cargo.toml:

$ cat Cargo.toml
[package]
name = "hello" 1
version = "0.1.0" 2
edition = "2021" 3

# See more keys and their definitions at 4
# https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies] 5
1

Éste era el nombre del proyecto que creé con Cargo, así que también será el nombre del ejecutable.

2

Esta es la versión del programa.

3

Esta es la edición de Rust que debe utilizarse para compilar el programa. Las ediciones son la forma en que la comunidad de Rust introduce cambios que no son compatibles con versiones anteriores. Utilizaré la edición 2021 para todos los programas de este libro.

4

Esta es una línea de comentario que incluiré sólo esta vez. Si quieres, puedes eliminar esta línea de tu archivo.

5

Aquí es donde enumerarás las cajas externas que utiliza tu proyecto. Este proyecto no tiene ninguna en este momento, así que esta sección está en blanco.

Nota

Las bibliotecas de Rust se llaman crates, y se espera que utilicen números de versión semánticos de la forma major.minor.patchde modo que 1.2.4 sea versión mayor 1, versión menor 2, versión parche 4. Un cambio en la versión mayor indica un cambio de última hora en la interfaz pública de programación de aplicaciones (API) de la crate.

Escribir y ejecutar pruebas de integración

"Más que el acto de probar, el acto de diseñar pruebas es uno de los mejores preventivos de errores que se conocen. La reflexión que hay que hacer para crear una prueba útil puede descubriryeliminar errores antes de que se codifiquen; de hecho, la reflexión sobre el diseño de las pruebas puede descubriry eliminar errores en cada fase de la creación del software, desde la concepción a la especificación, pasando por el diseño, la codificación y el resto."

Boris Beizer, Técnicas de comprobación de software (Van Nostrand Reinhold)

Aunque "¡Hola, mundo!" es bastante simple, todavía hay cosas que podrían soportar pruebas. Hay dos grandes categorías de pruebas que mostraré en este libro.Las pruebasde dentroa fuera o unitarias son cuando escribes pruebas para las funciones dentro de tu programa. Presentaré las pruebas unitarias en el Capítulo 5. Las pruebas defuera a dentro o de integración son cuando escribes pruebas que ejecutan tus programas como podría hacerlo el usuario, y eso es lo que haremos para este programa. La convención en los proyectos Rust es crear un directorio de pruebas paralelo al directorio src para probar el código, y puedes utilizar el comando mkdir tests para ello.

El objetivo es probar el programa hello ejecutándolo en la línea de comandos como lo hará el usuario. Crea el archivo tests/cli.rs para la interfaz de línea de comandos (CLI) con el siguiente código.Ten en cuenta que esta función pretende mostrar la prueba más sencilla posible en Rust, pero aún no hace nada útil:

#[test] 1
fn works() {
    assert!(true); 2
}
1

El atributo #[test] indica a Rust que ejecute esta función al realizar la prueba.

2

La macroassert! afirma que una expresión booleana es true.

Ahora tu proyecto debería tener este aspecto:

$ tree -L 2
.
├── Cargo.lock 1
├── Cargo.toml
├── src 2
│   └── main.rs
├── target 3
│   ├── CACHEDIR.TAG
│   ├── debug
│   └── tmp
└── tests 4
    └── cli.rs
1

El archivoCargo.lock registra las versiones exactas de las dependencias utilizadas para construir tu programa. No debes editar este archivo.

2

El directorio src es para los archivos del código fuente de Rust para construir el programa.

3

El directorio de destino contiene los artefactos de construcción.

4

El directorio tests contiene el código fuente Rust para probar el programa.

Todas las pruebas de este libro utilizarán assert! para verificar que alguna expectativa es true, o assert_eq! para verificar que algo es un valor esperado. Dado que esta prueba evalúa el valor literal true, siempre tendrá éxito. Para ver esta prueba en acción, ejecuta cargo testDeberías ver estas líneas entre la salida:

running 1 test
test works ... ok

Para observar una prueba fallida de , cambia true por false en el archivo tests/cli.rs:

#[test]
fn works() {
    assert!(false);
}

Entre la salida, deberías ver la siguiente prueba fallida:

running 1 test
test works ... FAILED
Consejo

Puedes tener tantas llamadas a assert! y assert_eq! en una función de prueba como quieras. Al primer fallo de una de ellas, falla toda la prueba.

Ahora, vamos a crear una prueba más útil que ejecute un comando y compruebe el resultado.El comando ls funciona tanto en Unix como en Windows PowerShell, así que empezaremos con él. Sustituye el contenido de tests/cli.rs por el siguiente código:

use std::process::Command; 1

#[test]
fn runs() {
    let mut cmd = Command::new("ls"); 2
    let res = cmd.output(); 3
    assert!(res.is_ok()); 4
}
1

Importa std::process::Command. El std nos dice que esto está en la biblioteca estándar y es código de Rust tan universalmente útil que se incluye con el lenguaje.

2

Crea un nuevo Command para ejecutar ls. La palabra clavelet vinculará un valor a una variable. La palabra clavemut hará mutable esta variable para que pueda cambiar.

3

Ejecuta el comando y captura la salida, que será un archivo Result.

4

Comprueba que el resultado es una variante de Ok, lo que indica que la acción se ha realizado correctamente.

Consejo

Por defecto, las variables de Rust son inmutables, lo que significa que sus valores no pueden cambiarse.

Ejecuta cargo test y comprueba que ves una prueba superada entre todos los resultados:

running 1 test
test runs ... ok

Actualiza tests/cli.rs con el siguiente código para que la función runs ejecute hello en lugar de ls:

use std::process::Command;

#[test]
fn runs() {
    let mut cmd = Command::new("hello");
    let res = cmd.output();
    assert!(res.is_ok());
}

Ejecuta de nuevo la prueba y observa que falla porque no se encuentra el programa hello:

running 1 test
test runs ... FAILED

Recuerda que el binario existe en target/debug/hello. Si intentas ejecutar hello en la línea de comandos, verás que no se encuentra el programa:

$ hello
-bash: hello: command not found

Cuando ejecutes cualquier comando, tu sistema operativo buscará en un conjunto predefinido de directorios algo con ese nombre.1 En los sistemas de tipo Unix, puedes inspeccionar la variable de entorno PATH de tu shell para ver esta lista de directorios, que están delimitados por dos puntos. (En Windows, es $env:Path.) Puedo utilizar tr (traducir caracteres) para sustituir los dos puntos (:) por nuevas líneas (\n) para mostrarte mi PATH:

$ echo $PATH | tr : '\n' 1
/opt/homebrew/bin
/Users/kyclark/.cargo/bin
/Users/kyclark/.local/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
1

$PATH indica a bash que interpola la variable. Utiliza una tubería (|) para enviar esto a tr.

Aunque cambie al directorio de destino/depuración, hello sigue sin encontrarse debido a las restricciones de seguridad antes mencionadas que excluyen el directorio de trabajo actual de mi PATH:

$ cd target/debug/
$ hello
-bash: hello: command not found

Debo hacer referencia explícita al directorio de trabajo actual para que el programa se ejecute:

$ ./hello
Hello, world!

A continuación, necesito encontrar una forma de ejecutar binarios que sólo existan en el crate actual.

Añadir dependencias del proyecto

Actualmente, el programa hello sólo existe en el directorio target/debug.Si lo copio en cualquiera de los directorios de mi PATH (ten en cuenta que incluyo el directorio $HOME/.local/bin para los programas privados), puedo ejecutarlo y realizar la prueba con éxito. Pero no quiero copiar mi programa para probarlo, sino que quiero probar el programa que vive en el crate actual.Puedo utilizar el crate assert_cmd para encontrar el programa en mi directorio crate.También añadiré el crate pretty_assertions para utilizar una versión de la macro assert_eq! que muestre las diferencias entre dos cadenas mejor que la versión por defecto.

Primero tengo que añadirlas como dependencias de desarrollo a Cargo.toml.Esto indica a Cargo que necesito estas cajas sólo para pruebas y evaluaciones comparativas:

[package]
name = "hello"
version = "0.1.0"
edition = "2021"

[dependencies]

[dev-dependencies]
assert_cmd = "2.0.13"
pretty_assertions = "1.4.0"

Entonces puedo utilizar assert_cmd para crear un Command que busque en los directorios binarios de Cargo.La siguiente prueba no verifica que el programa produzca la salida correcta, sólo que parece tener éxito.Actualiza tu tests/cli.rs con el siguiente código para que la función runs utilice assert_cmd::Command en lugar de std::process::Command:

use assert_cmd::Command; 1

#[test]
fn runs() {
    let mut cmd = Command::cargo_bin("hello").unwrap(); 2
    cmd.assert().success(); 3
}
1

Importa assert_cmd::Command.

2

Crea un Command para ejecutar hello en la caja actual. Esto devuelve un Result, y el código llama a Result::unwrap porque el binario debería encontrarse. Si no lo hace, unwrap provocará un pánico y la prueba fallará, lo cual es bueno.

3

Utiliza Assert::success para asegurarte de que la orden se ha ejecutado correctamente.

Nota

Tendré más que decir sobre el tipo Result en capítulos posteriores. Por ahora, basta con saber que se trata de una forma de modelar algo que puede tener éxito o fracasar para lo que existen dos variantes posibles, Ok y Err, respectivamente.

Ejecuta cargo test de nuevo y comprueba que ahora ves una prueba superada:

running 1 test
test runs ... ok

Comprender los valores de salida del programa

¿Qué significa que un programa se ejecute correctamente?Los programas de línea de comandos deben informar de un estado de salida final al sistema operativo para indicar éxito o fracaso. Los estándares de la Interfaz de Sistemas Operativos Portátiles (POSIX) dictan que el código de salida estándar es 0 para indicar éxito (piensa en cero errores) y cualquier número del 1 al 255 en caso contrario.Puedo mostrarte esto utilizando el intérprete de comandos bash y el comando true. Aquí está la página del manual de man true para la versión que existe en macOS:

TRUE(1)                   BSD General Commands Manual                  TRUE(1)

NAME
     true -- Return true value.

SYNOPSIS
     true

DESCRIPTION
     The true utility always returns with exit code zero.

SEE ALSO
     csh(1), sh(1), false(1)

STANDARDS
     The true utility conforms to IEEE Std 1003.2-1992 (''POSIX.2'').

BSD                              June 27, 1991                             BSD

Como indica la documentación, este programa no hace nada excepto devolver el código de salida cero.Si ejecuto trueno produce ninguna salida, pero puedo inspeccionar la variable bash $? para ver el estado de salida del comando más reciente:

$ true
$ echo $?
0

El comando false es un corolario en el sentido de que siempre sale con un código de salida distinto de cero:

$ false
$ echo $?
1

Se espera que todos los programas que escribas en este libro devuelvan cero cuando terminen normalmente y un valor distinto de cero cuando se produzca un error. Puedes escribir versiones de true y false para comprobarlo. Empieza creando un directorio src/bin utilizando mkdir src/biny luego crea src/bin/true.rs con el siguiente contenido:

fn main() {
    std::process::exit(0); 1
}
1

Utiliza la funciónstd::process::exit para salir del programa con el valor cero.

Tu directorio src debería tener ahora la siguiente estructura:

$ tree src/
src/
├── bin
│   └── true.rs
└── main.rs

Ejecuta el programa y comprueba manualmente el valor de salida:

$ cargo run --quiet --bin true 1
$ echo $?
0
1

La opción --bin es el nombre del objetivo binario a ejecutar.

Añade la siguiente prueba a tests/cli.rs para asegurarte de que funciona correctamente. No importa si la añades antes o después de la función runs existente:

#[test]
fn true_ok() {
    let mut cmd = Command::cargo_bin("true").unwrap();
    cmd.assert().success();
}

Si ejecutas cargo testdeberías ver los resultados de las dos pruebas:

running 2 tests
test true_ok ... ok
test runs ... ok
Nota

Las pruebas no se ejecutan necesariamente en el mismo orden en que se declaran en el código. Esto se debe a que Rust es un lenguaje seguro para escribir código concurrente, lo que significa que el código puede ejecutarse a través de múltiples hilos. Las pruebas aprovechan esta concurrencia para ejecutar muchas pruebas en paralelo, por lo que los resultados de las pruebas pueden aparecer en un orden diferente cada vez que las ejecutas. Se trata de una característica, no de un error. Si quieres ejecutar las pruebas en orden, puedes ejecutarlas en un único subproceso mediante cargo test -- --test-threads=1.

Los programas Rust saldrán con el valor cero por defecto. Recuerda que src/main. rs no llama explícitamente a std::process::exit. Esto significa que el programa true puede no hacer nada en absoluto. ¿Quieres estar seguro? Cambia src/bin/true.rs por lo siguiente:

fn main() {}

Ejecuta el conjunto de pruebas y comprueba que sigue pasando. A continuación, vamos a escribir una versión del programa false con el siguiente código fuente en src/bin/false.rs:

fn main() {
    std::process::exit(1); 1
}
1

Sal con cualquier valor entre 1 y 255 para indicar un error.

Comprueba manualmente que el valor de salida del programa no es cero:

$ cargo run --quiet --bin false
$ echo $?
1

A continuación, añade esta prueba a tests/cli.rs para verificar que el programa informa de un fallo cuando se ejecuta:

#[test]
fn false_not_ok() {
    let mut cmd = Command::cargo_bin("false").unwrap();
    cmd.assert().failure(); 1
}
1

Utiliza la funciónAssert::failure para asegurarte de que el comando ha fallado.

Ejecuta cargo test para comprobar que todos los programas funcionan como se espera:

running 3 tests
test runs ... ok
test true_ok ... ok
test false_not_ok ... ok

Otra forma de escribir el programa false utiliza std::process::abort. Cambia src/bin/false.rs por lo siguiente:

fn main() {
    std::process::abort();
}

De nuevo, ejecuta el conjunto de pruebas para asegurarte de que el programa sigue funcionando como se esperaba.

Probar la salida del programa

Aunque es bueno saber que mi programa hello sale correctamente, me gustaría asegurarme de que realmente imprime la salida correcta en STDOUT, que es el lugar estándar donde debe aparecer la salida y suele ser la consola.Actualiza tu función runs en tests/cli.rs a losiguiente:

use assert_cmd::Command;
use pretty_assertions::assert_eq; 1

#[test]
fn runs() {
    let mut cmd = Command::cargo_bin("hello").unwrap();
    let output = cmd.output().expect("fail"); 2
    assert!(output.status.success()); 3
    let stdout = String::from_utf8(output.stdout).expect("invalid UTF-8"); 4
    assert_eq!(stdout, "Hello, world!\n"); 5
}
1

Importa la macro pretty_assertions::assert_eq para comparar valores en lugar de la versión estándar de Rust.

2

Llama a Command::output para ejecutar el comando hello. Utiliza Result::expect para obtener la salida del comando o muere con el mensaje "fallo".

3

Comprueba que el comando se ha ejecutado correctamente.

4

Convierte la salida del programa a UTF-8, de lo que hablaré más detenidamente en el capítulo 4.

5

Compara la salida del programa con un valor esperado. Ten en cuenta que esto utilizará la versión pretty_assertions de la macro assert_eq.

Ejecuta las pruebas y comprueba que, efectivamente, hello funciona correctamente. A continuación, modifica src/main.rs para añadir algunos signos de exclamación más:

fn main() {
    println!("Hello, world!!!");
}

Ejecuta de nuevo las pruebas para observar una prueba fallida:

running 3 tests
test true_ok ... ok
test false_not_ok ... ok
test runs ... FAILED

failures:

---- runs stdout ----
thread runs panicked at tests/cli.rs:10:5:
assertion failed: `(left == right)`

Diff < left / right > :
<Hello, world!!!
>Hello, world!

El resultado de la prueba anterior se esfuerza por mostrarte cómo la salida esperada (la "derecha") difiere de la salida real (la "izquierda").La salida del terminal incluye incluso texto en rojo y verde y texto resaltado que no puede reproducirse aquí. Aunque se trata de un programa trivial, espero que puedas ver el valor de comprobar automáticamente todos los aspectos de los programas que escribimos.

Los valores de salida hacen que los programas sean componibles

Informar correctamente del estado de salida es una característica de los programas de línea de comandos que se comportan bien.El valor de salida es importante porque un proceso fallido utilizado junto con otro proceso debe hacer que la combinación falle. Por ejemplo, puedo utilizar el operador lógico y && en bash para encadenar los dos comandos true y ls. Sólo si el primer proceso informa de que ha tenido éxito, se ejecutará el segundo proceso:

$ true && ls
Cargo.lock  Cargo.toml  src/        target/     tests/

Si en su lugar ejecuto false && lsel resultado es que el primer proceso falla y ls nunca se ejecuta.Además, el estado de salida de todo el comando es distinto de cero:

$ false && ls
$ echo $?
1

Garantizar que los programas de línea de comandos informen correctamente de los errores hace que sean compatibles con otros programas. En los entornos Unix es muy habitual combinar muchos comandos pequeños para crear programas ad hoc en la línea de comandos. Si un programa encuentra un error pero no informa de él al sistema operativo, los resultados podrían ser incorrectos. Es mucho mejor que un programa aborte para que se puedan solucionar los problemas subyacentes.

Resumen

Este capítulo te ha presentado algunas ideas clave sobre la organización de un proyecto Rust y algunas ideas básicas sobre los programas de línea de comandos. Recapitulando:

  • El compilador de Rust rustc compila el código fuente de Rust en un archivo ejecutable por la máquina en Windows, macOS y Linux.

  • La herramienta Cargo creará un nuevo proyecto Rust, además de compilar, ejecutar y probar el código.

  • Por defecto cargo new crea un nuevo programa Rust que imprime "¡Hola, mundo!".

  • Las herramientas de línea de comandos como ls, cd, mkdir y rm suelen aceptar argumentos de línea de comandos como nombres de archivos o directorios, así como opciones como -f o -p.

  • Los programas compatibles con POSIX deben salir con un valor de 0 para indicar éxito y con cualquier valor entre 1 y 255 para indicar un error.

  • Aprendiste a añadir dependencias de crates a Cargo.toml y a utilizar los crates en tu código.

  • Has creado un directorio de pruebas para organizar el código de pruebas, y has utilizado #[test] para marcar las funciones que deben ejecutarse como pruebas.

  • Has aprendido a comprobar el estado de salida de un programa y a comprobar el texto impreso en STDOUT.

  • Aprendiste a escribir, ejecutar y probar binarios alternativos en un proyecto Cargo creando archivos de código fuente en el directorio src/bin.

  • Escribiste tus implementaciones de los programas true y false junto con pruebas para verificar que tienen éxito y fallan según lo esperado. Has visto que, por defecto, un programa Rust saldrá con el valor cero y que la función std::process::exit puede utilizarse para salir explícitamente con un código determinado. Además, la función std::process::abort puede utilizarse para salir con un código de error distinto de cero.

En el próximo capítulo, te mostraré cómo escribir un programa que utilice argumentos de la línea de comandos para modificar la salida.

1 Los alias de shell y las funciones también pueden ejecutarse como comandos, pero en este punto sólo estoy hablando de encontrar programas para ejecutar.

Get Línea de comandos Óxido now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.