Rust
ऑटो dereferencing
खोज…
डॉट ऑपरेटर
द .
रस्ट में ऑपरेटर बहुत जादू के साथ आता है! आप का उपयोग करते हैं .
संकलक deref "पेड़" नीचे विधि खोजने के लिए आवश्यक कई *
s (dereferencing संचालन) के रूप में सम्मिलित करेंगे। जैसा कि संकलन समय पर होता है, विधि खोजने की कोई रनटाइम लागत नहीं है।
let mut name: String = "hello world".to_string();
// no deref happens here because push is defined in String itself
name.push('!');
let name_ref: &String = &name;
// Auto deref happens here to get to the String. See below
let name_len = name_ref.len();
// You can think of this as syntactic sugar for the following line:
let name_len2 = (*name_ref).len();
// Because of how the deref rules work,
// you can have an arbitrary number of references.
// The . operator is clever enough to know what to do.
let name_len3 = (&&&&&&&&&&&&name).len();
assert_eq!(name_len3, name_len);
Auto dereferencing किसी भी प्रकार के std::ops::Deref
trait को लागू करने के लिए भी काम करता है।
let vec = vec![1, 2, 3];
let iterator = vec.iter();
यहाँ, iter
Vec<T>
की विधि नहीं है, बल्कि [T]
की एक विधि है। यह काम करता है क्योंकि Vec<T>
लागू Deref
साथ Target=[T]
जो की सुविधा देता है Vec<T>
में बदल जाते हैं [T]
जब से dereferenced *
ऑपरेटर (जो संकलक एक के दौरान सम्मिलित हो सकते हैं .
)।
डेरेफ़ ज़बरदस्ती
दो प्रकार T
और U
को देखते हुए, &T
&U
यदि केवल और केवल T
लागू करता है तो Deref<Target=U>
रूप में बदलना होगा।
यह हमें इस तरह की चीजें करने की अनुमति देता है:
fn foo(a: &[i32]) {
// code
}
fn bar(s: &str) {
// code
}
let v = vec![1, 2, 3];
foo(&v); // &Vec<i32> coerces into &[i32] because Vec<T> impls Deref<Target=[T]>
let s = "Hello world".to_string();
let rc = Rc::new(s);
// This works because Rc<T> impls Deref<Target=T> ∴ &Rc<String> coerces into
// &String which coerces into &str. This happens as much as needed at compile time.
bar(&rc);
फ़ंक्शन तर्कों के लिए Deref और AsRef का उपयोग करना
ऐसे कार्यों के लिए जिन्हें वस्तुओं का संग्रह करने की आवश्यकता होती है, स्लाइस आमतौर पर एक अच्छा विकल्प होता है:
fn work_on_bytes(slice: &[u8]) {}
क्योंकि Vec<T>
और सरणियां [T; N]
Deref<Target=[T]>
लागू Deref<Target=[T]>
, उन्हें आसानी से एक स्लाइस के लिए मजबूर किया जा सकता है:
let vec = Vec::new();
work_on_bytes(&vec);
let arr = [0; 10];
work_on_bytes(&arr);
let slice = &[1,2,3];
work_on_bytes(slice); // Note lack of &, since it doesn't need coercing
हालांकि, स्पष्ट रूप से एक स्लाइस की आवश्यकता के बजाय, फ़ंक्शन को किसी भी प्रकार को स्वीकार करने के लिए बनाया जा सकता है जिसे स्लाइस के रूप में इस्तेमाल किया जा सकता है:
fn work_on_bytes<T: AsRef<[u8]>>(input: T) {
let slice = input.as_ref();
}
इस उदाहरण में फ़ंक्शन work_on_bytes
किसी भी प्रकार का T
as_ref()
जो कि as_ref()
लागू as_ref()
, जो [u8]
संदर्भ देता है।
work_on_bytes(vec);
work_on_bytes(arr);
work_on_bytes(slice);
work_on_bytes("strings work too!");
विकल्प और आवरण संरचना के लिए डेरेफ़ कार्यान्वयन
use std::ops::Deref;
use std::fmt::Debug;
#[derive(Debug)]
struct RichOption<T>(Option<T>); // wrapper struct
impl<T> Deref for RichOption<T> {
type Target = Option<T>; // Our wrapper struct will coerce into Option
fn deref(&self) -> &Option<T> {
&self.0 // We just extract the inner element
}
}
impl<T: Debug> RichOption<T> {
fn print_inner(&self) {
println!("{:?}", self.0)
}
}
fn main() {
let x = RichOption(Some(1));
println!("{:?}",x.map(|x| x + 1)); // Now we can use Option's methods...
fn_that_takes_option(&x); // pass it to functions that take Option...
x.print_inner() // and use it's own methods to extend Option
}
fn fn_that_takes_option<T : std::fmt::Debug>(x: &Option<T>) {
println!("{:?}", x)
}
सरल Deref उदाहरण
Deref
एक सरल नियम है: यदि आप एक प्रकार है T
और यह लागू करता Deref<Target=F>
, तो &T
को coerces &F
, संकलक इस कई बार के रूप एफ पाने के लिए की जरूरत है, उदाहरण के लिए के रूप में दोहराया जाएगा:
fn f(x: &str) -> &str { x }
fn main() {
// Compiler will coerce &&&&&&&str to &str and then pass it to our function
f(&&&&&&&"It's a string");
}
उदाहरण के लिए, Box
या Arc
जैसे पॉइंटर प्रकारों के साथ काम करते समय डेरेफ़ ज़बरदस्ती विशेष रूप से उपयोगी है:
fn main() {
let val = Box::new(vec![1,2,3]);
// Now, thanks to Deref, we still
// can use our vector method as if there wasn't any Box
val.iter().fold(0, |acc, &x| acc + x ); // 6
// We pass our Box to the function that takes Vec,
// Box<Vec> coerces to Vec
f(&val)
}
fn f(x: &Vec<i32>) {
println!("{:?}", x) // [1,2,3]
}