เหตุใด 'find' จึงใช้พารามิเตอร์โดยการอ้างอิงแล้วจึงทำการอ้างอิงอีกครั้ง [ทำซ้ำ]

ในตัวอย่างต่อไปนี้ ฉันไม่เข้าใจว่าเหตุใดการปิดจึงใช้พารามิเตอร์ s โดยการอ้างอิง (&s) จากนั้นจึงยกเลิกการอ้างอิง (*s):

fn main() {
    let needle = "list".to_string();
    let haystack = [
       "some".to_string(), 
        "long".to_string(),
        "list".to_string(),
        "of".to_string(),
        "strings".to_string(),
    ].to_vec();

    if let Some(str) = haystack.iter().find(|&s| *s == needle) {
        println!("{}", needle);
    } else {
        println!("Nothing there...");
    }
}

ฉันพลาดบางสิ่งบางอย่างที่ชัดเจนไปหรือเปล่า?


person Pat Shaughnessy    schedule 01.03.2019    source แหล่งที่มา
comment
คงจะดีไม่น้อยหากคุณระบุ สิ่งที่ ทำให้คุณสับสนให้ชัดเจนยิ่งขึ้นอีกเล็กน้อย การใช้ ||, การไม่มี return, ความจริงที่ว่า needle ไม่ได้ถูกบันทึกอย่างชัดเจน (ดังนั้นจะเป็นอย่างไรไม่ว่าจะบันทึกโดยการอ้างอิงหรือตามค่า), ...   -  person Matthieu M.    schedule 01.03.2019
comment
ขออภัย: สิ่งที่ทำให้ฉันสับสนคือการใช้ |&s| ในพารามิเตอร์การปิด และในขณะที่จำเป็นต้องใช้ *s ภายในการปิดด้วย   -  person Pat Shaughnessy    schedule 01.03.2019
comment
find(|&s| s == &needle) ดูดีสำหรับฉัน   -  person Boiethios    schedule 01.03.2019
comment
อ่า น่าสนใจ ฉันไม่ได้คิดอย่างนั้น ขอบคุณ &needle ความหมายของ Matthieu โดยการจับภาพโดยการอ้างอิงคืออะไร   -  person Pat Shaughnessy    schedule 01.03.2019
comment
ฉันคิดว่า if haystack.contains(&needle) เป็นสำนวนมากกว่าสำหรับ Vec   -  person Stargateur    schedule 01.03.2019
comment
สิ่งนี้ถูกเรียกโดยเฉพาะใน เอกสารประกอบสำหรับวิธีการที่คุณใช้: เนื่องจาก find() ใช้การอ้างอิง และผู้วนซ้ำจำนวนมากวนซ้ำการอ้างอิง สิ่งนี้นำไปสู่สถานการณ์ที่อาจเกิดความสับสนโดยที่อาร์กิวเมนต์เป็นการอ้างอิงซ้ำซ้อน คุณสามารถเห็นเอฟเฟกต์นี้ได้ในตัวอย่างด้านล่าง โดยมี &&x.   -  person Shepmaster    schedule 01.03.2019


คำตอบ (1)


มันเป็นสำนวน บางคนอาจมีการตั้งค่าที่แตกต่างกันสำหรับสิ่งที่จะถูกยกเลิกการอ้างอิงเมื่อใด และ/หรือใช้ .as_str() แทนการยกเลิกการอ้างอิง แต่โดยทั่วไปก็ไม่เป็นไร


ในกรณีของคุณ .iter() วนซ้ำมากกว่า Strings โดยการอ้างอิง ดังนั้นจึงให้ &String องค์ประกอบ

จากนั้น .find() จะทำให้คุณสามารถเข้าถึงแต่ละองค์ประกอบที่วนซ้ำโดยการอ้างอิง อีกครั้ง ดังนั้นคุณจึงได้อาร์กิวเมนต์ &&String แม้ว่าการอ้างอิงการอ้างอิงนั้นไม่เหมาะในกรณีนี้ แต่ .find() ก็เป็นฟังก์ชันทั่วไปที่ต้องทำงานกับประเภทใดๆ อย่างสม่ำเสมอ ดังนั้นจึงสร้างการอ้างอิงแบบสุ่มสี่สุ่มห้า


ในอาร์กิวเมนต์ &s เป็นสิ่งที่ ตรงกันข้าม ของการอ้างอิง ไวยากรณ์ของอาร์กิวเมนต์การปิดคือ:

|pattern: type|

และประเภทนั้นเป็นทางเลือก ดังนั้นสิ่งที่คุณเหลือคือ รูปแบบ

การปิดของคุณคือ:

|pattern: &&String|

และด้วยรูปแบบของคุณ:

|&s: &&String| 

ตรงกับระดับหนึ่งที่ & ดังนั้นคุณจะได้ s เป็น &String

จากนั้นคุณต้องการเปรียบเทียบ s ประเภท &String กับ String หากต้องการเปรียบเทียบประเภทที่เท่ากัน คุณจะต้องอ้างอิง &String ถึง String ด้วย *s

person Kornel    schedule 01.03.2019
comment
&s ตรงกันข้ามกับการโต้แย้งโดยการอ้างอิง — ไม่ มันไม่ใช่ มันยังคงใช้การโต้แย้งโดยการอ้างอิง เพียงแต่จะยกเลิกการอ้างอิงทันที foo(bar: &String) และ foo(bar: String) อยู่ตรงข้ามกันในมิตินี้ - person Shepmaster; 01.03.2019