¿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<‘_>
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 deBufWriter
. Así es cómo se puede hacer:En esta implementación, creamos un
Box<dyn write="">
que puede contener cualquier tipo que implemente el rasgoWrite
, incluidos tantoBufWriter<file>
comoBufWriter<stdoutlock>
. Esto nos permite crear una instancia deBox<dyn write="">
utilizando una expresiónmatch
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
?
.