ইটার এবং এর_টার মধ্যে পার্থক্য কী?


175

আমি জাস্ট বাই উদাহরণ টিউটোরিয়াল করছি যা এই কোড স্নিপেট আছে:

// Vec example
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];

// `iter()` for vecs yields `&i32`. Destructure to `i32`.
println!("2 in vec1: {}", vec1.iter()     .any(|&x| x == 2));
// `into_iter()` for vecs yields `i32`. No destructuring required.
println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));

// Array example
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];

// `iter()` for arrays yields `&i32`.
println!("2 in array1: {}", array1.iter()     .any(|&x| x == 2));
// `into_iter()` for arrays unusually yields `&i32`.
println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2));

আমি পুঙ্খানুপুঙ্খভাবে বিভ্রান্ত হয়েছি - একটি Vecপুনরাবৃত্তির জন্য iterউত্পাদনের উল্লেখগুলি থেকে ফিরে আসে এবং পুনরুক্তি into_iterফলনের মান থেকে ফিরে আসে তবে একটি অ্যারের জন্য এই পুনরাবৃত্তিগুলি কী অভিন্ন?

এই দুটি পদ্ধতির ব্যবহারের ক্ষেত্রে / এপিআই কী?

উত্তর:


147

টি এল; ডিআর:

  • দ্বারা পুনরুদ্ধার করা আয়রক্ষেত্রটি প্রসঙ্গের উপর নির্ভর করে যে into_iterকোনও একটি T, &Tবা ফলন করতে পারে &mut T
  • পুনরাবৃত্তি দ্বারা ফিরে iterআসবে &Tকনভেনশন অনুসারে।
  • পুনরাবৃত্তি দ্বারা ফিরে iter_mutআসবে &mut Tকনভেনশন অনুসারে।

প্রথম প্রশ্নটি: "কী into_iter?"

into_iterIntoIteratorবৈশিষ্ট্য থেকে আসে :

pub trait IntoIterator 
where
    <Self::IntoIter as Iterator>::Item == Self::Item, 
{
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
}

কোনও নির্দিষ্ট ধরণের কীভাবে পুনরুক্তিতে রূপান্তর করতে হয় তা নির্দিষ্ট করতে চাইলে আপনি এই বৈশিষ্ট্যটি প্রয়োগ করেন। সবচেয়ে উল্লেখযোগ্যভাবে, যদি কোনও প্রকার প্রয়োগ করে তবে IntoIteratorএটি forলুপে ব্যবহার করা যেতে পারে ।

উদাহরণস্বরূপ, Vecসরঞ্জাম IntoIterator... তিনবার!

impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>

প্রতিটি বৈকল্পিক কিছুটা আলাদা।

এই এক হ্রাস Vecএবং তার পুনরুক্তিকারীর উৎপাদনের মান ( Tসরাসরি):

impl<T> IntoIterator for Vec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(mut self) -> IntoIter<T> { /* ... */ }
}

অন্য দু'জন রেফারেন্স দ্বারা ভেক্টর নেন ( উভয় ক্ষেত্রে একটি রেফারেন্স into_iter(self)কারণ এর স্বাক্ষর দ্বারা বোকা বানাবেন না self) এবং তাদের পুনরাবৃত্তকারীগুলি অভ্যন্তরের উপাদানগুলির জন্য রেফারেন্স তৈরি করবে Vec

এই এক উৎপাদ অপরিবর্তনীয় রেফারেন্স :

impl<'a, T> IntoIterator for &'a Vec<T> {
    type Item = &'a T;
    type IntoIter = slice::Iter<'a, T>;

    fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }
}

এই এক যদিও উৎপাদ চপল রেফারেন্স :

impl<'a, T> IntoIterator for &'a mut Vec<T> {
    type Item = &'a mut T;
    type IntoIter = slice::IterMut<'a, T>;

    fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }
}

তাই:

মধ্যে পার্থক্য কি iterএবং into_iter?

into_iterএটির পুনরুক্তি প্রাপ্ত একটি জেনেরিক পদ্ধতি, এই পুনরুক্তিটি মান দেয় কিনা, পরিবর্তনীয় রেফারেন্স বা পরিবর্তনীয় রেফারেন্সটি প্রাসঙ্গিক নির্ভর এবং কখনও কখনও অবাক হওয়ার মতো হতে পারে।

iterএবং iter_mutঅ্যাড-হক পদ্ধতি। তাদের রিটার্নের ধরণ তাই প্রসঙ্গে স্বতন্ত্র এবং প্রথাগতভাবে যথাক্রমে অপরিবর্তনীয় রেফারেন্স এবং পরিবর্তনীয় রেফারেন্স প্রদানকারী পুনরাবৃত্তিকারী হবে।

দ্য রাস্ট বাই উদাহরণ পোস্টের লেখক যে প্রসঙ্গে বলা হয় (যেমন, টাইপ) তার উপর নির্ভরতা থেকে আগত বিস্ময়ের চিত্র তুলে ধরেছেন এবং into_iterএই সত্যটি ব্যবহার করে সমস্যাটিকে আরও জটিল করে তুলছেন:

  1. IntoIterator[T; N]শুধুমাত্র &[T; N]এবং এর জন্য বাস্তবায়িত হয় না&mut [T; N]
  2. একটি পদ্ধতি একটি মান জন্য প্রয়োগ করা না থাকে, এটি স্বয়ংক্রিয়ভাবে অনুসন্ধান করা হয় রেফারেন্স যে মান পরিবর্তে

যা into_iterসমস্ত ধরণের (ব্যতীত [T; N]) সমস্ত 3 প্রকরণের (মান এবং রেফারেন্স) এর জন্য এটি বাস্তবায়নের জন্য অত্যন্ত আশ্চর্যজনক । অ্যারের পক্ষে এমন একটি পুনরুক্তি কার্যকর করা সম্ভব নয় যা মানগুলি দেয় কারণ এটি তার আইটেমগুলি ছেড়ে দিতে "সঙ্কুচিত" করতে পারে না।

অ্যারেগুলি কেন প্রয়োগ করে IntoIterator(যেমন একটি আশ্চর্যজনক ফ্যাশনে): এটি forলুপগুলিতে তাদের উল্লেখগুলি নিয়ে পুনরাবৃত্তি করা সম্ভব করে তোলে ।


14
আমি এই ব্লগ পোস্টটি সহায়ক বলে মনে করেছি: hermanradtke.com/2015/06/22/…
poy

> এই পুনরুক্তি মান দেয় কি না, পরিবর্তনীয় রেফারেন্স বা পরিবর্তনীয় রেফারেন্স প্রসঙ্গ নির্ভর, এর অর্থ কী এবং কীভাবে এটি মোকাবেলা করতে হবে? উদাহরণস্বরূপ, কীভাবে কেউ ইটার_মটকে পারস্পরিক পরিবর্তন আনতে বাধ্য করবে?
ড্যান এম

@ ড্যানএম .: (১) এর অর্থ into_iterহ'ল গ্রহণকারী কোনও মান, রেফারেন্স বা পরিবর্তনীয় রেফারেন্স কিনা তার ভিত্তিতে একটি বাস্তবায়ন বেছে নেয়। (২) মরিচায় কোনও পরিবর্তনীয় মান নেই, বা এর পরিবর্তে কোনও মানই আপনার মালিকানা হওয়ায় পরিবর্তনযোগ্য।
ম্যাথিউ এম।

@ ম্যাথিউইউএম.এইচএম, আমার পরীক্ষাগুলিতে এটি মনে হয় না। আমি IntoIter প্রয়োগ করেছি &'a MyStructএবং &mut 'a MyStructএবং বর্তমান যদি এমনকি যদি আমি নামক প্রথম এক সবসময় নির্বাচিত হয়েছে into_iter().for_each()উপর mutদিয়ে মান &mutল্যামডা মধ্যে আর্গুমেন্ট।
ড্যান এম

1
@ আইএক্সএক্স: ধন্যবাদ এটি খুব দরকারী। উত্তরের মাঝখানে কবর দেওয়া এড়াতে আমি প্রশ্নের শীর্ষে একটি টিএল; ডিআর সরবরাহ করার সিদ্ধান্ত নিয়েছি, আপনি কী ভাবেন?
ম্যাথিউ এম।

78

আমি (একটি জং নবাগত) গুগল থেকে এখানে একটি সহজ উত্তর চেয়েছিলাম যা অন্য উত্তরগুলির দ্বারা সরবরাহ করা হয়নি। এখানে যে সহজ উত্তর:

  • iter() রেফারেন্স দ্বারা আইটেমগুলি পুনরাবৃত্তি
  • into_iter() আইটেমগুলির উপর পুনরাবৃত্তি করে এগুলিকে নতুন স্কোপে নিয়ে যায়
  • iter_mut() প্রতিটি আইটেমের পরিবর্তিত রেফারেন্স প্রদান করে আইটেমগুলির উপরে পুনরাবৃত্তি হয়

তাই for x in my_vec { ... }মূলত সমতূল্য my_vec.into_iter().for_each(|x| ... )উভয় - moveউপাদান my_vecমধ্যে ...সুযোগ।

আপনার যদি কেবলমাত্র ডেটা "দেখার" দরকার হয় iter, আপনি যদি এটি সম্পাদনা / রূপান্তর করতে চান iter_mutতবে ব্যবহার করুন , এবং যদি আপনাকে এটির নতুন মালিক দেওয়ার দরকার হয় তবে ব্যবহার করুন into_iter

এটি সহায়ক ছিল: http://hermanradtke.com/2015/06/22/effectively-used-iterators-in-rust.html

এটিকে একটি সম্প্রদায়ের উইকি তৈরি করা যাতে আশা করা যায় যে আমি কোনও ভুল করেছি তবে কোনও জাস্ট প্রো এটি উত্তরটি সম্পাদনা করতে পারে।


7
ধন্যবাদ ... এটি দেখতে কিভাবে গৃহীত উত্তর স্পষ্টভাবে উচ্চারণ মধ্যে একটি পার্থক্য কঠিন iterএবং into_iter
এমএমডাব্লু

ঠিক আমি যা খুঁজছিলাম!
সাইরাস্মিথ

6

.into_iter()একটি অ্যারে নিজেই প্রয়োগ করা হয় না, তবে কেবল &[]। তুলনা করা:

impl<'a, T> IntoIterator for &'a [T]
    type Item = &'a T

সঙ্গে

impl<T> IntoIterator for Vec<T>
    type Item = T

যেহেতু IntoIteratorকেবলমাত্র সংজ্ঞায়িত করা হয়েছে &[T], স্লাইসটি নিজেই সেইভাবে ফেলে দেওয়া যাবে না Vecযখন আপনি মানগুলি ব্যবহার করেন। (মানগুলি সরানো যায় না)

এখন, কেন বিষয়টি কেসটি আলাদা বিষয় এবং আমি নিজে শিখতে চাই। অনুমান: অ্যারে নিজেই ডেটা, স্লাইস এটিতে কেবল একটি দর্শন। অনুশীলনে আপনি অ্যারেটিকে অন্য কোনও ফাংশনে মান হিসাবে স্থানান্তর করতে পারবেন না, কেবল এটির একটি ভিউ পাস করুন, সুতরাং আপনি এটি সেখানে ব্যবহার করতে পারবেন না।


IntoIteratorএছাড়াও বাস্তবায়িত হয় &'a mut [T], যাতে এটি অ্যারে থেকে জিনিসগুলি সরিয়ে নিতে পারে। আমি মনে করি এটি রিটার্ন স্ট্রাক্টের IntoIter<T>সাথে আজীবন যুক্তি রাখে Iter<'a, T>না এর সাথে সম্পর্কিত, তাই প্রাক্তন কোনও টুকরো ধরে রাখতে পারে না।
রডরিগো

mutএর অর্থ হ'ল আপনি মানগুলি পরিবর্তন করতে পারবেন, এগুলি নয় যে আপনি সেগুলি সরিয়ে নিতে পারেন।
ভাইরাপটার

@rodrigo let mut a = ["abc".to_string()]; a.into_iter().map(|x| { *x });=> "ত্রুটি: ধার করা বিষয়বস্তু থেকে সরানো যায় না"
ভাইরাপটর

হ্যাঁ, আমি মনে করি আপনি সঠিক এবং মানগুলি অ্যারে থেকে সরানো যাবে না। যাইহোক, আমি এখনও মনে করি যে ArrayIntoIterগ্রন্থাগারের অংশ হিসাবে অনিরাপদ মরিচা ব্যবহার করে এক ধরণের কাঠামো বাস্তবায়ন করা উচিত ... সম্ভবত এটি মূল্যহীন নয়, যেভাবে Vecযাইহোক আপনার এই ক্ষেত্রে ব্যবহার করা উচিত ।
রডরিগো

সুতরাং আমি বুঝতে পারি না ... এটিই সেই কারণটি array.into_iterফিরে আসে &T- কারণ এটি স্বয়ংক্রিয়ভাবে এটিকে রূপান্তরিত করার জন্য যাদু করছে &array.into_iterand এবং যদি তাই হয় তবে চলন্ত মানগুলি বা চলমান মানগুলির সাথে এর কী কী আছে তা আমি বুঝতে পারি না। বা এটি যেমন @rodrigo বলেছিল, আপনি রেফারেন্সটি কেবলমাত্র পেয়েছেন কারণ (কোনও কারণে) আপনি মানগুলি অ্যারে থেকে সরিয়ে নিতে পারবেন না ? তবুও খুব বিভ্রান্ত।
ভিট্রিয়াল

2

আমি মনে করি আরও কিছু স্পষ্ট করার মতো কিছু আছে। সংগ্রহের ধরণের, যেমন Vec<T>এবং এর VecDeque<T>এমন into_iterপদ্ধতি রয়েছে যা ফলিত করে Tকারণ তারা প্রয়োগ করে IntoIterator<Item=T>। আমাদের Foo<T>পুনরুক্তি করা হয় এমন ধরণের তৈরি করতে আমাদের থামানোর মতো কিছুই নেই , তবে এটি Tঅন্য কোনও প্রকারের নয় U। যে, Foo<T>প্রয়োগ IntoIterator<Item=U>

বাস্তবে, কয়েকটি উদাহরণ রয়েছে std: &Path প্রয়োগ IntoIterator<Item=&OsStr>&UnixListener প্রয়োগ IntoIterator<Item=Result<UnixStream>>


into_iterএবং মধ্যে পার্থক্যiter

into_iterএবং এর মধ্যে পার্থক্য সম্পর্কে মূল প্রশ্নে ফিরে যান iter। অন্যরা যেমন নির্দেশ করেছে তার অনুরূপ, পার্থক্যটি into_iterহ'ল একটি প্রয়োজনীয় পদ্ধতি IntoIteratorযা নির্দিষ্ট কোনও ধরণের ফলন করতে পারে IntoIterator::Item। সাধারণত, যদি কোনও প্রকার প্রয়োগ করে IntoIterator<Item=I>, কনভেনশন অনুসারে এর দুটি অ্যাড-হক পদ্ধতিও রয়েছে: iterএবং iter_mutযা উত্পাদন করে &Iএবং &mut Iযথাক্রমে।

এর অর্থ যা বোঝায় তা হ'ল আমরা এমন একটি ফাংশন তৈরি করতে into_iterপারি যা একটি বৈশিষ্ট্যযুক্ত বাউন্ড ব্যবহার করে পদ্ধতি (যেমন এটি একটি পুনরাবৃত্তিযোগ্য) পায় এমন একটি প্রকার গ্রহণ করে:

fn process_iterable<I: IntoIterator>(iterable: I) {
    for item in iterable {
        // ...
    }
}

যাইহোক, আমরা *iter পদ্ধতি বা iter_mutপদ্ধতি থাকতে কোনও ধরণের প্রয়োজনের জন্য আবদ্ধ বৈশিষ্ট্যটি ব্যবহার করতে পারি না , কারণ তারা কেবল কনভেনশন। আমরা বলতে পারি into_iterআরও ব্যাপক ভাবে চেয়ে ব্যবহারযোগ্য হয় iterবা iter_mut

বিকল্প iterএবংiter_mut

আরেকটি আকর্ষণীয় পালন করা হয় iterকোনো ইটারেটরে উৎপাদনের যে পেতে একমাত্র উপায় নয় &T। কনভেনশন দ্বারা (আবার), সংগ্রহ ধরনের SomeCollection<T>মধ্যে stdযা আছে iterপদ্ধতি তাদের অপরিবর্তনীয় রেফারেন্স ধরনের &SomeCollection<T>বাস্তবায়ন IntoIterator<Item=&T>। উদাহরণস্বরূপ, &Vec<T> প্রয়োগগুলি IntoIterator<Item=&T> , সুতরাং এটি আমাদের পুনরাবৃত্তি করতে সক্ষম করে &Vec<T>:

let v = vec![1, 2];

// Below is equivalent to: `for item in v.iter() {`
for item in &v {
    println!("{}", item);
}

যদি উভয়ই বাস্তবায়নের v.iter()সমতুল্য হয় তবে কেন মরিচা উভয় সরবরাহ করে? এটি এর্গোনমিক্সের জন্য। ইন লুপ, এটা ব্যবহার করা একটি বিট আরো সংক্ষিপ্ত এর চেয়ে ; কিন্তু অন্যান্য ক্ষেত্রে, তুলনায় অনেক পরিষ্কার হয় :&vIntoIterator<Item=&T>for&vv.iter()v.iter()(&v).into_iter()

let v = vec![1, 2];

let a: Vec<i32> = v.iter().map(|x| x * x).collect();
// Although above and below are equivalent, above is a lot clearer than below.
let b: Vec<i32> = (&v).into_iter().map(|x| x * x).collect();

একইভাবে, forলুপগুলিতে, এর v.iter_mut()সাথে প্রতিস্থাপন করা যেতে পারে &mut v:

let mut v = vec![1, 2];

// Below is equivalent to: `for item in v.iter_mut() {`
for item in &mut v {
    *item *= 2;
}

কখন কোনও প্রকারের জন্য (প্রয়োগ করা) into_iterএবং iterপদ্ধতিগুলি সরবরাহ করতে হবে

যদি টাইপটির পুনরাবৃত্তি হওয়ার জন্য কেবল একটি "উপায়" থাকে তবে আমাদের উভয়টি প্রয়োগ করা উচিত। যাইহোক, যদি দুটি উপায় বা তার বেশি থাকে তবে এটি পুনরাবৃত্তি হতে পারে, পরিবর্তে আমাদের প্রতিটি উপায়ে একটি অ্যাড-হক পদ্ধতি সরবরাহ করা উচিত।

উদাহরণস্বরূপ, Stringসরবরাহ করে না into_iterবা iterকারণ এটির পুনরাবৃত্তি করার দুটি উপায় রয়েছে: বাইটগুলিতে এর উপস্থাপনা পুনরাবৃত্তি করা বা অক্ষরগুলিতে এর প্রতিনিধিত্ব পুনরাবৃত্তি করা। পরিবর্তে, এটি দুটি পদ্ধতি সরবরাহ করে: bytesবাইটগুলি charsপুনরাবৃত্তি করার জন্য এবং অক্ষরের পুনরাবৃত্তির জন্য, iterপদ্ধতির বিকল্প হিসাবে ।


* ঠিক আছে, প্রযুক্তিগতভাবে আমরা একটি বৈশিষ্ট্য তৈরি করে এটি করতে পারি। তবে তারপরে আমরা implপ্রতিটি ধরণের ব্যবহার করতে চাই তার জন্য আমাদের সেই বৈশিষ্ট্যটি প্রয়োজন । ইতিমধ্যে, stdইতিমধ্যে প্রয়োগ অনেক ধরণের IntoIterator

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.