Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Display

fmt::Debug escasamente parece compacto y limpio, por lo que a menudo es ventajoso personalizar la apariencia de salida. Esto se hace implementando manualmentefmt::Display, que usa el marcador {}. Implementarlo se ve así:

#![allow(unused)]
fn main() {
// Importar (a través de `use`) el módulo `fmt` para ponerlo a disposición.
use std::fmt;

// Defina una estructura para la cual se implementará `fmt::Display`. Esto es
 // una estructura de tupla llamada `Estructura` que contiene un `i32`. 
struct Structure(i32);

// Para usar el marcador `{}`, el trait `fmt::Display` debe implementarse
// manualmente para el tipo. 
impl fmt::Display for Structure {
    // Este trait requiere de `fmt` con estos tipos exactos.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Escribe sólo el primer elemento en la salida suministrada 
// stream: `f`. Devuelve `fmt::Result` que indica si
// la operación tuvo éxito o falló. Tenga en cuenta que 'write!` usa una sintaxis que 
// es muy similar a `println!`. 
        write!(f, "{}", self.0)
    }
}
}

fmt::Display puede ser más limpio que fmt::Debug pero esto presenta un problemapara la biblioteca std. ¿Cómo se deben mostrar los tipos ambiguos? Por ejemplo, si la biblioteca std implementó un sólo estilo para todos los Vec<T>, ¿qué estilo debería ser? ¿Sería cualquiera de estos dos?

  • Vec<path>: /:/etc:/home/usuario:/bin (split on :)
  • Vec<numero>: 1,2,3 (partido en ,)

No, porque no hay un estilo ideal para todos los tipos y la biblioteca std no presume dictar uno. fmt::Display no se implementa para Vec<T> o para cualquier otro contenedor genérico. Fmt::Debug debe usarse para estos casos genéricos.

Sin embargo, esto no es un problema porque para cualquier nuevo tipo contenedor que sea_no_ genérico, se puede implementar fmt::Display.

use std::fmt; // Importar `fmt`

// Una estructura que contiene dos números. Se derivará `Debug` para que los resultadospuedan// ser contrastados con `Display`.
#[derive(Debug)]
struct MinMax(i64, i64);

// Implementa `Display` para `MinMax`.
impl fmt::Display for MinMax {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Usa `self.number` para referirte a cada dato posicional.
        write!(f, "({}, {})", self.0, self.1)
    }
}

// Define una estructura donde los campos se puedan nombrar para compararse.
#[derive(Debug)]
struct Point2D {
    x: f64,
    y: f64,
}

// Similarmente, implementa `Display` para `Point2D`.
impl fmt::Display for Point2D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Personalízalo para que sólo `x` y `y` sean denotados.
        write!(f, "x: {}, y: {}", self.x, self.y)
    }
}

fn main() {
    let minmax = MinMax(0, 14);

    println!("Compara estructuras:");
    println!("Display: {}", minmax);
    println!("Debug: {:?}", minmax);

    let big_range =   MinMax(-300, 300);
    let small_range = MinMax(-3, 3);

    println!("El rango grande es {big} y el pequeño es {small}",
             small = small_range,
             big = big_range);

    let point = Point2D { x: 3.3, y: 7.2 };

    println!(" Compara Puntos:");
    println!("Display: {}", point);
    println!("Debug: {:?}", point);

    // Error. Ambos `Debug` y `Display` fueron implementados, pero `{:b}`
   // requiere implementar `fmt::Binary`. Esto no funcionará.
   // println!("¿Cómo se ve el Punto2D en binario: {:b}?", point);
}

Entonces, fmt::Display se ha implementado pero fmt::Binary no, ypor lo tanto, no se puede usar. std::fmt tiene muchos de estos traits y cada uno requiere suimplementación. Esto se detalla aún más en std::fmt.

Actividad

Después de verificar la salida del ejemplo anterior, use la estructura Point2D como una guía para agregar una estructura Complex al ejemplo. Cuando se imprime de la misma manera, la salida debería ser:

Display: 3.3 +7.2i
Debug: Complex { real: 3.3, imag: 7.2 }

Display: 4.7 -2.3i
Debug: Complex { real: 4.7, imag: -2.3 }

Bonus: Add a space before the +/- signs.

Hints in case you get stuck:

  • Check the documentation for Sign/#/0 in std::fmt.
  • Bonus: Check if-else branching and the abs function.

Ver también

derive, std::fmt, macros, struct, trait, y use