নেস্টেড অ্যারে ইনডেক্সে "অপরিবর্তনীয় হিসাবে orrowণ নিতে পারে না কারণ এটি পরিবর্তনীয় হিসাবেও নেওয়া হয়" এর অর্থ কী?


16

এই ক্ষেত্রে ত্রুটিটির অর্থ কী:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
    v[v[1]] = 999;
}
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
 --> src/main.rs:3:7
  |
3 |     v[v[1]] = 999;
  |     --^----
  |     | |
  |     | immutable borrow occurs here
  |     mutable borrow occurs here
  |     mutable borrow later used here

আমি দেখতে পেয়েছি যে সূচকগুলি Indexএবং IndexMutবৈশিষ্ট্যগুলির মাধ্যমে প্রয়োগ করা হয় এবং v[1]এটি সিনট্যাকটিক চিনি *v.index(1)। এই জ্ঞান দিয়ে সজ্জিত, আমি নিম্নলিখিত কোডটি চালানোর চেষ্টা করেছি:

use std::ops::{Index, IndexMut};

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
    *v.index_mut(*v.index(1)) = 999;
}

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


2
কোডের আগমনের সাথে জাস্ট শিখছেন? স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম, এবং দুর্দান্ত প্রশ্নের জন্য ধন্যবাদ!
সোভেন মারনাচ

অবিকল; ) এটি করার আমার এটি তৃতীয় বছর (এর আগে 2x হাস্কেল) - আমি নিম্ন স্তরের জিনিসগুলিতে আরও আগ্রহী হতে শুরু করার পরে
রাস্টকে ঘূর্ণি দেবার কথা ভাবি

@ লুকাসবাউক এটি মজার, আমি সাধারণত আমার প্রকল্পের জন্য মরিচা ব্যবহার করি তবে আমি হাসকেলে এই এসও লিখি। তারা উভয়ই তাদের ডোমেনের দুর্দান্ত ভাষা।
বোয়িথিওস

উত্তর:


16

পছন্দসই সংস্করণ আপনার কাছে যা আছে তার থেকে কিছুটা আলাদা। লাইন

v[v[1]] = 999;

আসলে desugars

*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;

এটি একই ত্রুটির বার্তায় প্রকাশিত হয় তবে টীকাগুলি কী ঘটছে তার ইঙ্গিত দেয়:

error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
 --> src/main.rs:7:48
  |
7 |     *IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
  |      ------------------- ------                ^^ immutable borrow occurs here
  |      |                   |
  |      |                   mutable borrow occurs here
  |      mutable borrow later used by call

আপনার পছন্দসই সংস্করণে গুরুত্বপূর্ণ পার্থক্য হল মূল্যায়ন আদেশ। ফাংশন কলের আর্গুমেন্টগুলি ফাংশন কল করার আগে তালিকাভুক্ত ক্রমে বাম থেকে ডানদিকে মূল্যায়ন করা হয়। এই ক্ষেত্রে এর অর্থ হ'ল প্রথমে &mut vমূল্যায়ন করা হয়, পারস্পরিকভাবে ablyণ নেওয়া v। এরপরে, Index::index(&v, 1)মূল্যায়ন করা উচিত, তবে এটি সম্ভব নয় - vইতিমধ্যে পরস্পর ধার করা হয়েছে। পরিশেষে, সংকলকটি দেখায় যে ফাংশন কলের জন্য এখনও পরিবর্তনীয় রেফারেন্সের প্রয়োজন আছে index_mut(), তাই ভাগ করে নেওয়া রেফারেন্সটি চেষ্টা করার পরে পরিবর্তিত রেফারেন্সটি এখনও বেঁচে থাকবে।

প্রকৃতপক্ষে সংকলিত সংস্করণটির কিছুটা আলাদা মূল্যায়নের ক্রম রয়েছে।

*v.index_mut(*v.index(1)) = 999;

প্রথমত, পদ্ধতি কলগুলিতে ফাংশন আর্গুমেন্টগুলি বাম থেকে ডানদিকে *v.index(1)মূল্যায়ন করা হয় , অর্থাত প্রথমে মূল্যায়ন করা হয়। এর ফলে একটি হয় usizeএবং সাময়িকভাবে ভাগ করা orrowণ vআবার প্রকাশ করা যেতে পারে। তারপরে, প্রাপককে index_mut()মূল্যায়ন করা হয়, অর্থ vপারস্পরিকভাবে ধার করা হয়। ভাগ করে নেওয়া alreadyণ ইতিমধ্যে চূড়ান্ত হয়ে গেছে এবং পুরো প্রকাশটি orrowণ পরীক্ষককে পাস করে, এটি কাজ করে।

নোট করুন যে সংস্করণটি সংকলন করে কেবল এটি "অ-লেসিকাল লাইফটাইমস" প্রবর্তনের পরে তা করে। মরিচের পূর্ববর্তী সংস্করণগুলিতে, ভাগ করা theণ প্রকাশের শেষ অবধি বেঁচে থাকবে এবং ফলস্বরূপ ত্রুটি ঘটবে।

আমার মতে সবচেয়ে পরিষ্কার সমাধান হল একটি অস্থায়ী পরিবর্তনশীল ব্যবহার:

let i = v[1];
v[i] = 999;

ওহো! এখানে অনেক কিছু চলছে! সময় দেওয়ার জন্য ধন্যবাদ ব্যাখ্যা করার জন্য! (আকর্ষণীয়ভাবে এই ধরণের "quirks" একটি ভাষা আমার কাছে আরও আকর্ষণীয় করে তোলে ...)। আপনি সম্ভবত একটি ইঙ্গিতও দিতে পারেন কেন *v.index_mut(*v.index_mut(1)) = 999;"একবারের চেয়ে বেশি পার্সোনাল হিসাবে v হিসাবে bণ নিতে পারে না" ails> সংকলক হওয়া উচিত নয়, কারণ *v.index_mut(*v.index(1)) = 999;অভ্যন্তরীণ orrowণ আর দরকার নেই তা নির্ধারণ করতে সক্ষম হওয়া উচিত ?
লুকাস বাউকে

@ লুকাসউউক জাস্টের কয়েকটি ক্যারিক্স রয়েছে যা কখনও কখনও কিছুটা অসুবিধেয় হয় তবে বেশিরভাগ ক্ষেত্রে সমাধান এর চেয়ে সহজ হয়, যেমনটি এই ক্ষেত্রে। কোডটি এখনও বেশ পঠনযোগ্য, আপনার কাছে যা ছিল তার চেয়ে সামান্য কিছুটা আলাদা , তাই বাস্তবে এটি কোনও বড় বিষয় নয়।
সোভেন মার্নাচ

@ লুকাসবুকার দুঃখিত, আমি এখন পর্যন্ত আপনার সম্পাদনাটি দেখিনি। ফলাফলটি *v.index(1)সেই সূচকটিতে সঞ্চিত মান , এবং সেই মানটি valive ণকে জীবিত রাখার প্রয়োজন হয় না । *v.index_mut(1)অন্যদিকে, ফলাফলটি একটি পরিবর্তনীয় স্থানের অভিব্যক্তি যা তাত্ত্বিকভাবে নির্ধারিত হতে পারে, সুতরাং এটি orrowণকে জীবিত রাখে। পৃষ্ঠতলে, orrowণ চেকারকে এটি শেখানো সম্ভব হবে যে মূল্য প্রকাশের প্রসঙ্গে একটি স্থানের অভিব্যক্তিটিকে একটি মূল্য প্রকাশ হিসাবে বিবেচনা করা যেতে পারে, সুতরাং এটি মরচে কিছু ভবিষ্যতের সংস্করণে সংকলন করবে।
সোভেন মার্নাচ

কোনও আরএফসি কীভাবে এটির জন্য ডিজাইন করবেন:{ let index = *Index::index(&v, 1); let value = 999; *IndexMut::index_mut(&mut v, index) = value; }
বোয়াইথিয়াস

@ ফ্রেঞ্চবয়েথিয়োস আপনি কীভাবে এটি আনুষ্ঠানিক করবেন তা আমার কোনও ধারণা নেই এবং আমি নিশ্চিত যে এটি কখনই উড়ে বেড়াবে না। আপনি যদি এটিকে সম্বোধন করতে চান তবে একমাত্র আমি seeণ চেকারের উন্নতি করে দেখছি, উদাহরণস্বরূপ এটি সনাক্ত করে যে পরিবর্তনীয় orrowণ পরবর্তী সময়ে শুরু হতে পারে, যেহেতু সত্যই এটি প্রাথমিক পর্যায়ে দরকার নেই। (এই নির্দিষ্ট ধারণাটি সম্ভবত কার্যকর হয় না))
সোভেন মারনাচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.