es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo asignar tanto BufWriter como BufWriter a la misma variable?

Estoy tratando de crear una instancia de Writer ya sea desde la salida estándar o desde un archivo recién creado (si se proporciona una ruta), y luego usar esa instancia para escribir en ella.

El problema es que no puedo asignarlo usando una expresión match:

let file;
let stdout = stdout();

// argpath, cuando no es None, contiene una ruta de archivo para crear
let mut writer = match argpath {
    Some(path) => {
        file = File::create(path)?;
        BufWriter::new(file)
    },
    None => {
        BufWriter::new(stdout.lock())
    }
};

writeln!(writer, "Blah");

El compilador se queja obviamente, ya que las dos ramas del match no devuelven el mismo objeto, BufWriter y BufWriter:

none
error[E0308]: `match` arms have incompatible types
   --> src/main.rs:115:13
    |
109 |       let mut writer = match argpath {
    |  ______________________-
110 | |         Some(path) => {
111 | |             file = File::create(path)?;
112 | |             BufWriter::new(file)
    | |             -------------------- this is found to be of type `std::io::BufWriter<file>`
...   |
115 | |             BufWriter::new(stdout.lock())
    | |             ^^^^^^^^^^^^^^^^^^^^^^ expected struct `File`, found struct `StdoutLock`
116 | |         }
117 | |     };
    | |_____- `match` arms have incompatible types
    |
    = note: expected type `std::io::BufWriter<file>`
             found struct `std::io::BufWriter<stdoutlock<'_>>`
note: return type inferred to be `std::io::BufWriter<file>` here

En general, ¿existe un patrón de programación existente, en Rust, que permita asignar un BufWriter a una variable, independientemente del tipo interno, de modo que el código siguiente pueda consumirlo como un objeto regular que implementa los traits Write?</stdoutlock<‘_>

Tags:  ,

Answer

  1. Avatar for davy.ai

    Este es un problema común al tratar con el sistema de tipos de Rust. Una forma de resolverlo es utilizar el tipo Box para crear un objeto de rasgo dinámico que pueda contener cualquier instancia de BufWriter. Así es cómo se puede hacer:

    let writer: Box<dyn write=""> = if let Some(path) = argpath {
        let file = File::create(path)?;
        Box::new(BufWriter::new(file))
    } else {
        Box::new(BufWriter::new(stdout.lock()))
    };
    
    writeln!(writer, "Blah")?;
    

    En esta implementación, creamos un Box<dyn write=""> que puede contener cualquier tipo que implemente el rasgo Write, incluidos tanto BufWriter<file> como BufWriter<stdoutlock>. Esto nos permite crear una instancia de Box<dyn write=""> utilizando una expresión match sin preocuparnos por tipos incompatibles.

    Luego asignamos el resultado de la expresión match a este objeto de rasgo dinámico y lo utilizamos para escribir en la salida.

    Ten en cuenta que también hemos agregado manejo de errores al código utilizando el operador ?.

Comments are closed.