rust - lenguaje - para que sirve c++
¿Por qué no se puede usar el rasgo implícito para devolver tipos múltiples/condicionales? (2)
DK. ya ha explicado por qué , pero me gustaría proporcionar una solución alternativa.
Como se menciona en la iteración condicional sobre uno de varios posibles iteradores , puede crear una enumeración que implemente un rasgo si ambos tipos de componentes lo hacen. Por ejemplo:
extern crate rand; // 0.6.5
use rand::{rngs::OsRng, thread_rng, RngCore};
fn rng() -> impl RngCore {
match OsRng::new() {
Ok(rng) => EitherRng::Left(rng),
Err(_) => EitherRng::Right(thread_rng()),
}
}
enum EitherRng<L, R> {
Left(L),
Right(R),
}
impl<L, R> RngCore for EitherRng<L, R>
where
L: RngCore,
R: RngCore,
{
fn next_u32(&mut self) -> u32 {
match self {
EitherRng::Left(l) => l.next_u32(),
EitherRng::Right(r) => r.next_u32(),
}
}
fn next_u64(&mut self) -> u64 {
match self {
EitherRng::Left(l) => l.next_u64(),
EitherRng::Right(r) => r.next_u64(),
}
}
fn fill_bytes(&mut self, b: &mut [u8]) {
match self {
EitherRng::Left(l) => l.fill_bytes(b),
EitherRng::Right(r) => r.fill_bytes(b),
}
}
fn try_fill_bytes(&mut self, b: &mut [u8]) -> Result<(), rand::Error> {
match self {
EitherRng::Left(l) => l.try_fill_bytes(b),
EitherRng::Right(r) => r.try_fill_bytes(b),
}
}
}
Cualquiera de las dos cajas proporciona muchos de estos tipos de implementaciones para rasgos fundamentales.
Ver también:
- ¿Cómo devuelvo condicionalmente diferentes tipos de futuros?
Estoy tratando de obtener un generador de números aleatorios.
Como
OsRng::new()
puede fallar, me gustaría volver a
thread_rng()
si tengo que:
extern crate rand; // 0.6.5
use rand::{rngs::OsRng, thread_rng, RngCore};
fn rng() -> impl RngCore {
match OsRng::new() {
Ok(rng) => rng,
Err(e) => thread_rng(),
}
}
Sin embargo, recibo este mensaje de error que no puedo entender:
error[E0308]: match arms have incompatible types
--> src/lib.rs:6:5
|
6 | / match OsRng::new() {
7 | | Ok(rng) => rng,
8 | | Err(e) => thread_rng(),
| | ------------ match arm with an incompatible type
9 | | }
| |_____^ expected struct `rand::rngs::OsRng`, found struct `rand::prelude::ThreadRng`
|
= note: expected type `rand::rngs::OsRng`
found type `rand::prelude::ThreadRng`
¿Por qué el compilador espera
rand::OsRng
aquí en lugar de una implementación de
RngCore
?
Si
thread_rng()
la
match
y devuelvo directamente
thread_rng()
, no
thread_rng()
mensaje de error anterior.
No creo que este sea un duplicado de
¿Cómo devuelvo una instancia de un rasgo de un método?
, como la otra pregunta es sobre
cómo
se puede devolver un rasgo de una función, y esta pregunta es sobre
por qué
el compilador no me permite devolver un rasgo, pero quiere que yo devuelva un
OsRng
que no sea el tipo de retorno de la función .
impl Trait
no es equivalente a devolver una interfaz o un objeto de clase base.
Es una forma de decir "No quiero escribir el nombre del tipo específico que estoy devolviendo".
Todavía está devolviendo un valor de un tipo único y específico;
simplemente no estás diciendo
qué
tipo.
Cada una de esas ramas está devolviendo diferentes tipos, de ahí el problema. Implementar el mismo rasgo no es suficiente.
Lo que probablemente desee en este caso específico es un objeto de rasgo como
Box<dyn RngCore>
.
extern crate rand; // 0.6.5
use rand::{rngs::OsRng, thread_rng, RngCore};
fn rng() -> Box<dyn RngCore> {
match OsRng::new() {
Ok(rng) => Box::new(rng),
Err(_) => Box::new(thread_rng()),
}
}
Nota
: si está utilizando una versión un poco más antigua de Rust, es posible que deba eliminar la palabra clave
dyn
.
Es opcional en la edición actual (2015) de Rust.