Rust में Vec<T> के स्लाइस: यह कैसे काम करता है और इसकी आवश्यकता क्यों है?
\n\nयदि आपने कभी Rust में लिखा है और सोचा है "How do I get a slice of a Vec<T> in Rust?" — तो आप अकेले नहीं हैं। यह Stack Overflow पर सबसे लोकप्रिय प्रश्नों में से एक है, जिसे हज़ारों बार देखा गया है। और यह कोई संयोग नहीं है: वैक्टर और उनके स्लाइस के साथ काम करना एक मौलिक कौशल है, जिसके बिना Rust में किसी भी गंभीर प्रोजेक्ट की कल्पना नहीं की जा सकती।
\n\nइस लेख में, हम केवल यह नहीं दिखाएंगे कि स्लाइस कैसे प्राप्त करें। हम 2025 की सर्वोत्तम प्रथाओं पर चर्चा करेंगे, सामान्य जाल से बचना सीखेंगे, और समझेंगे कि Rust हमें उधार के बारे में इतना सोचने के लिए क्यों मजबूर करता है। चलिए शुरू करते हैं!
\n\nRust में स्लाइस (slice) क्या है?
\n\nस्लाइस लेने से पहले, आइए समझें कि यह क्या है। स्लाइस मेमोरी में तत्वों के एक सतत अनुक्रम का एक संदर्भ है। Rust में, स्लाइस को &[T] के रूप में दर्शाया जाता है। यह एक स्वामित्व वाली डेटा संरचना नहीं है — यह केवल किसी और (जैसे वेक्टर या ऐरे) के स्वामित्व वाले डेटा के एक हिस्से को "देखता" है।
स्लाइस का मुख्य लाभ सुरक्षा है। Rust कंपाइलर गारंटी देता है कि आप मेमोरी सीमा से बाहर नहीं जाएंगे, और उधार प्रणाली आपको डेटा को बदलने की अनुमति नहीं देगी जब तक उस पर सक्रिय संदर्भ हों।
\n\nसीधे वेक्टर का उपयोग क्यों न करें?
\n\nवेक्टर (Vec<T>) एक स्वामित्व वाली संरचना है। यदि आप इसे किसी फ़ंक्शन में पास करते हैं, तो आप या तो इसे स्थानांतरित कर देते हैं (पहुँच खो देते हैं) या एक संदर्भ पास करते हैं। स्लाइस आपको लचीलापन देते हैं: आप डेटा के केवल एक हिस्से को कॉपी किए बिना या मूल वेक्टर पर नियंत्रण खोए बिना पास कर सकते हैं।
उदाहरण के लिए, आप बड़े डेटा ऐरे के साथ काम कर रहे हैं और विश्लेषण के लिए इसके एक टुकड़े को किसी फ़ंक्शन में पास करना चाहते हैं। स्लाइस एक आदर्श उपकरण है: यह हल्का है (केवल दो शब्द: पॉइंटर और लंबाई) और सुरक्षित है।
\n\nVec<T> का स्लाइस प्राप्त करने के मुख्य तरीके
\n\nआइए अभ्यास की ओर बढ़ते हैं। वेक्टर से स्लाइस प्राप्त करने के कई तरीके हैं। हम सबसे लोकप्रिय और सुविधाजनक तरीकों पर विचार करेंगे।
\n\n1. इंडेक्सिंग ऑपरेटर: &vec[start..end]
\n\nसबसे सीधा तरीका रेंज ऑपरेटर .. का उपयोग करना है:
let vec = vec![1, 2, 3, 4, 5];\nlet slice: &[i32] = &vec[1..4]; // इंडेक्स 1 से 4 तक स्लाइस (4 शामिल नहीं)\nprintln!("{:?}", slice); // [2, 3, 4]\n\nयह विधि रनटाइम बाउंड चेकिंग का उपयोग करती है। यदि आप वेक्टर की सीमा से बाहर जाते हैं, तो प्रोग्राम पैनिक (panic) करेगा। शैक्षिक उदाहरणों के लिए यह ठीक है, लेकिन प्रोडक्शन कोड में सावधान रहना चाहिए।
\n\nआप रेंज के विभिन्न रूपों का उपयोग कर सकते हैं:
\n\n- \n
&vec[..]— पूरा वेक्टर \n&vec[2..]— इंडेक्स 2 से अंत तक \n&vec[..3]— शुरू से इंडेक्स 3 तक (शामिल नहीं) \n&vec[1..=3]— 1 से 3 तक (दोनों शामिल) \n
2. विधि .as_slice()
\n\nयह विधि पूरे वेक्टर पर एक स्लाइस लौटाती है। यह &vec[..] से अधिक सुरक्षित है, क्योंकि यह स्पष्ट रूप से इरादा व्यक्त करता है:
let vec = vec![10, 20, 30];\nlet slice: &[i32] = vec.as_slice();\nprintln!("{:?}", slice); // [10, 20, 30]\n\nas_slice() विधि विशेष रूप से तब उपयोगी होती है जब आप इस बात पर जोर देना चाहते हैं कि आप स्लाइस के साथ काम कर रहे हैं, न कि वेक्टर के साथ। यह कोड को अधिक पठनीय और स्व-दस्तावेजीकरण बनाता है।
3. परिवर्तनीय स्लाइस प्राप्त करना: as_mut_slice()
\n\nयदि आपको स्लाइस के अंदर तत्वों को बदलने की आवश्यकता है (लेकिन स्वयं वेक्टर को नहीं), तो as_mut_slice() का उपयोग करें:
let mut vec = vec![1, 2, 3];\nlet slice: &mut [i32] = vec.as_mut_slice();\nslice[0] = 100;\nprintln!("{:?}", vec); // [100, 2, 3]\n\nध्यान दें: वेक्टर को mut के रूप में घोषित किया जाना चाहिए। साथ ही, आप एक साथ अपरिवर्तनीय और परिवर्तनीय स्लाइस नहीं रख सकते — यह उधार के नियमों का उल्लंघन करेगा।