Lost traits Borrow
and AsRef
son muy similares, pero diferentes. He aquí un breve repaso acerca de lo que significan dichos traits:
El trait Borrow
se usa cuando estamos escribiendo un estructura de datos, y deseamos usar un tipo owned o un tipo borrowed como sinónimo por alguna razón.
Por ejemplo, HashMap
posee un metodo get
que usa Borrow
:
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Hash + Eq
Esta firma es complicada. El parametro K
es en lo que estamos interesados ahora. Se refiere a un parametro del HashMap
en si mismo:
struct HashMap<K, V, S = RandomState> {
El parametro K
es el tipo de la clave que usa el HashMap
. Al ver de nuevo la firma de get()
, solo podemos usar get()
cuando la clave implementa Borrow<Q>
. De esta manera, podemos crear un HashMap
que use claves String
pero al momento de buscar use &str
s:
use std::collections::HashMap; let mut map = HashMap::new(); map.insert("Foo".to_string(), 42); assert_eq!(map.get("Foo"), Some(&42));
Esto es debido a que la biblioteca estándar posee una impl Borrow<str> for String
.
Para la mayoría de los tipos, cuando desees tomar un tipo ya sea owned o borrowed, un &T es suficiente. Pero un area en la cual Borrow
es efectivo es cuando hay mas de un tipo de valor borrowed. Esto es especialmente cierto en referencias y slices: puedes tener ambos un &T
un &mut T
. Si queremos aceptar ambos tipos Borrow
es lo que necesitamos:
use std::borrow::Borrow; use std::fmt::Display; fn foo<T: Borrow<i32> + Display>(a: T) { println!("a es un borrowed: {}", a); } let mut i = 5; foo(&i); foo(&mut i);
This will print out a es un borrowed: 5
dos veces.
El trait AsRef
es un trait de conversion. Es usado para convertir algún valor a una referencia en código generico. Como esto:
let s = "Hola".to_string(); fn foo<T: AsRef<str>>(s: T) { let slice = s.as_ref(); }
Podemos ver como ambos son una especie de lo mismo: ambos lidian con las versiones owned y borrowed de algún tipo. Sin embargo, son diferentes.
Escoge Borrow
cuando quieras abstraerte por encima de diferentes tipos de borrowing, o cuando estas construyendo una estructura de datos que trata los valores owned y borrowed de formas equivalentes, como el hashing y la comparación.
Usa AsRef
cuando desees convertir algo directamente en una referencia, y estés escribiendo código genérico.