क्या Rust वाकई इतना मूल्यवान था?
(medium.com/@jsoverson)- WebAssembly पर ध्यान केंद्रित करने के लिए JavaScript से Rust में जाने के बाद 3 वर्षों में Wick, production deployments, ebook और crates.io पर लगभग 100 packages बनाते हुए Rust के वास्तविक मूल्य का आकलन किया गया
- borrow checker, समृद्ध type system, functional patterns और
nullकी अनुपस्थिति compile चरण में कई errors रोकती है, जिससे कम tests के साथ बड़े codebase को maintain करना संभव हुआ - Clippy और Cargo workspace शक्तिशाली हैं, लेकिन global lint settings और workspace deployment जैसी tools और ecosystem की कमियां operational cost में बदल जाती हैं
- async, refactoring, generic·lifetime·trait constraint management JavaScript या Go की तुलना में अब भी अधिक friction वाले क्षेत्र बने हुए हैं
- Rust मजबूत और बहुमुखी है, लेकिन hiring, learning, fast iteration और issue tracking की लागत ज्यादा है; इसलिए यह तब अधिक उपयुक्त है जब scope स्पष्ट हो या initial cost उठाई जा सके
WebAssembly ने Rust चुनने की दिशा दी
- कुछ साल पहले WebAssembly पर 100% focus करने के लिए मौजूदा काम छोड़ दिया गया, और उस समय Rust का WebAssembly compile support सबसे अच्छा था
- feature-rich WebAssembly runtimes भी Rust-based थे, इसलिए विकल्पों में Rust सबसे practical option था
- बाद में Wick बनाया गया, जो WebAssembly को core module system के रूप में इस्तेमाल करने वाला application framework और runtime है
- 3 वर्षों में कई production deployments, एक ebook, और crates.io पर लगभग 100 packages deploy करने के दौरान Rust का अनुभव बढ़ा
कम tests से ज्यादा code maintain करना
- Rust में सामान्य languages की तरह tests लिखते समय यह महसूस हुआ कि ऐसे tests लिखे जा रहे हैं जो compile हो जाने पर fail हो ही नहीं सकते
unsafe {}blocks और.unwrap()जैसे panic के लिए आसान methods से बचने पर कई समस्याएं default रूप से टल जाती हैं- borrow checker, समृद्ध type system, functional patterns और libraries, तथा
nullvalue की अनुपस्थिति testing effort को कम करती है - Wick project के 70,000 से अधिक lines of code को दूसरी languages में जितने tests चाहिए होते, उससे बहुत कम tests के साथ maintain किया गया
- जब tests की जरूरत होती है, तो Rust के integrated test harness की वजह से उन्हें code के पास आसानी से जोड़ा जा सकता है
Rust ने दूसरी languages में coding habits भी बदल दीं
- Rust compiler उस code पर भी लगातार आपत्ति जताता है जिसे दूसरी languages में सामान्य माना जाता, और इस प्रक्रिया से coding habits बदल गईं
- अब दूसरी languages में भी code lines का order अजीब लगे या return values check न की जाएं, तो असहजता महसूस होती है
- runtime errors आने पर भी पहले से कहीं ज्यादा तीखी अस्वीकृति महसूस होती है
- Rust की strictness असुविधाजनक है, लेकिन compiler द्वारा सुरक्षा देने के अनुभव की आदत पड़ जाए तो दूसरी languages में लौटना कठिन हो जाता है
Clippy linter से बढ़कर उपयोगी है
- Clippy Rust का linter है, लेकिन यह सिर्फ check करने वाले tool से ज्यादा, alternative code सुझाने वाला friendly assistant tool जैसा है
- Rust standard library बहुत बड़ी है, और functionality कई types, traits, macros और functions में फैली हुई है, इसलिए जरूरी API ढूंढना कठिन हो सकता है
- कई rules ऐसे common patterns पहचानते हैं जिन्हें standard library methods या types से बेहतर replace किया जा सकता है
- उदाहरण: manual_is_ascii_check
- सैकड़ों rules performance, readability और unnecessary indirection को address करते हैं, और जहां संभव हो alternative code भी देते हैं
- Project-wide lint settings Cargo issue के जरिए संभव होती दिख रही थीं, लेकिन तब तक Wick को दर्जनों crates की inline lint settings scripts से auto-update करनी पड़ती थीं
Ecosystem में ऐसी कमियां हैं जिन्हें स्वीकार करना पड़ता है
- global Clippy settings की समस्या Rust tools और libraries में अक्सर मिलने वाली ecosystem gaps का एक उदाहरण है
- संबंधित issues अभी बंद हो चुके हैं, लेकिन वे कई सालों तक खुले रहे और समाधान में लंबा समय लगा
- Rust लंबे समय तक “सबसे पसंदीदा language” चुने जाने लायक नए users को आकर्षित करता रहा, लेकिन यह flow सीधे libraries और tools में नाटकीय सुधारों में नहीं बदला
- किसी specific use case को संभालने के लिए one-off forks बनने के मामले कई थे, और Wick में भी PR डालने की कोशिश के दौरान ऐसी ही स्थिति आई
- संभावित वजहों में stable API बनाए रखने का दबाव और finely segmented type system शामिल हैं
- library owners के लिए छोटे बदलाव भी major version change तक ले जा सकते हैं, इसलिए उन्हें स्वीकार करना मुश्किल होता है
- सभी की जरूरतों को पूरा करने वाला Rust code लिखने का बोझ भी बड़ा है
Cargo, crates.io और workspace deployment में friction
- Wick repository structure popular projects को देखकर बनाया गया था और शुरुआत में reasonable लगा, लेकिन deployment stage में समस्याएं सामने आईं
- Cargo से module-sized crate को build, test और use करना आसान है, लेकिन crates.io deployment अलग समस्या है
- crates.io पर package publish करने के लिए refer किए गए सभी crates अलग-अलग deploy हुए होने चाहिए
- local filesystem में ही मौजूद packages पर dependent crate deploy न होने देना उचित है
- लेकिन बड़े project को छोटे internal modules में बांटने वाली natural structure में parent crate के अंदर ही मौजूद sub-crate को include करके publish नहीं किया जा सकता
- एक correction था कि local dev dependency वाले crate को भी publish किया जा सकता है, अगर
Cargo.tomlमेंversioninclude न हो - Cargo workspace support अपने आप में शानदार है, और बड़े projects manage करने का अनुभव ज्यादातर languages से बेहतर है
- लेकिन workspace deployment problem हल नहीं करता, और configuration के कई तरीके होने पर भी आसानी से deploy होने वाला “सही जवाब” ढूंढना मुश्किल है
- cargo workspace publish से जुड़े utility crates की बड़ी संख्या खुद समस्या को दिखाती है
- Wick publish करते समय manual repetitive work और केवल आंशिक रूप से काम करने वाले tools को combine करना पड़ता था, और अक्सर इसमें 1 घंटे से अधिक लग जाता था
async सबसे बड़े frictions में से एक है
- Rust का async ऐसा लगता है जैसे language पहले बन जाने के बाद जोड़ा गया feature हो, और practical use में भी यह अक्सर late-added feature की तरह बाधा बनता है
- errors समझना और fix करना मुश्किल है, और solution ढूंढते समय भी अलग-अलग runtimes और उनके अपने async तरीकों के आधार पर filter करना पड़ता है
- कुछ async libraries specific async runtime के बाहर इस्तेमाल नहीं की जा सकने की संभावना रखती हैं
- 20 साल JavaScript इस्तेमाल करने और Go का अनुभव रखने के नजरिए से Rust async frustration और friction का सबसे बड़ा स्रोत है
- यह असंभव समस्या नहीं है, लेकिन async issues कभी भी सामने आ सकते हैं—इसके लिए हमेशा तैयार रहना पड़ता है
- दूसरी languages में async लगभग invisible जितना natural तरीके से काम करता है
Refactoring मेहनत वाला काम हो सकता है
- Rust का समृद्ध type system फायदा भी है और नुकसान भी
- Rust types के जरिए सोचना अच्छा है, लेकिन Rust types को manage करना nightmare बन सकता है
- data और function signatures में generic type, generic lifetime और trait constraint हो सकते हैं
- constraints खुद भी generic type और lifetime रख सकते हैं, इसलिए कई बार actual code से ज्यादा type constraints होते हैं
- उदाहरण: rxRust observable.rs
- हर
implमें generics define करने पड़ते हैं, इसलिए शुरुआत में लिखना भी झंझट भरा है, और refactoring के समय छोटा बदलाव chain reaction बनकर बड़े modifications में बदल सकता है- उदाहरण: Wasmtime Cranelift iter.rs
- जब वही constraints या generic lists कई जगह repeat करनी पड़ें, तो उन्हें alias करने या central definition से reference करने का language/tool-level तरीका नहीं है, इसलिए duplication burden बना रहता है
अंतिम निर्णय: शक्तिशाली, लेकिन महंगा
- Rust इतना versatile है कि system-level code, CLI apps, web servers और web clients एक ही language में लिखे जा सकते हैं
- WebAssembly का उपयोग करके वही binary LLM को browser और command line में चला सकती है
- Rust programs बहुत robust हो सकते हैं, और Rust जिन समस्याओं से बचाता है उन्हें महसूस करने के बाद दूसरी language में लौटना मुश्किल होता है
- थोड़े समय के लिए Go पर लौटने पर development speed फिर आकर्षक लगी, लेकिन runtime panic का सामना करने के बाद वह फायदा कमजोर पड़ गया
- Rust की स्पष्ट कमियां हैं
- hiring मुश्किल है
- learning धीमी है
- fast iteration के लिए यह बहुत rigid है
- खासकर async code में memory और performance issues track करना कठिन है
- सभी libraries safe code के लिए पर्याप्त अच्छी नहीं हैं
- development tools में और सुधार की गुंजाइश है
- छोटी team के साथ बेहतरीन काम किया गया, लेकिन बड़े अवरोध भी थे; और Rust के अधिक उपयुक्त होने के technical कारण भी थे, इसलिए Wick के लिए Rust मूल्यवान था या नहीं, इस पर फैसला अभी जल्दबाजी होगा
- अगर fast iteration करनी है, तो Rust के उपयुक्त न होने की संभावना अधिक है
- अगर scope ज्ञात है या अधिक initial cost उठाई जा सकती है, तो Rust पर गंभीरता से विचार किया जा सकता है
- WebAssembly का perspective हर महीने मजबूत हो रहा है, जिससे एक बार लिखा गया robust software कई जगह reuse करने की संभावना वास्तविकता के और करीब आ रही है
1 टिप्पणियां
Hacker News की रायें
Rust का काफी इस्तेमाल किया है, लेकिन कई सालों बाद भी यह अब भी कम productivity वाला लगता है
इन दिनों Zig ज्यादा इस्तेमाल करता हूं; उसमें सिर्फ मनचाही coding पर ध्यान दे पाता हूं और कौन-सा tool या library इस्तेमाल करनी है, यह सोचने की जरूरत नहीं पड़ती, इसलिए लगभग 10 गुना ज्यादा productive महसूस होता है
समझता हूं कि Rust memory safety देता है और यह अहम है, लेकिन इसकी usability सच में खराब है। Rust लिखते समय हर बार बंधा हुआ महसूस होता है, और हमेशा library ढूंढनी पड़ती है या काम कैसे करना है यह search करना पड़ता है, इसलिए बस “code type” नहीं कर पाता
type system भी बेकाबू होकर बहुत बड़ा हो सकता है, और कई बार यह जानना मुश्किल होता है कि किसी struct पर असल में कौन-से methods call किए जा सकते हैं। Rust एक शानदार tool है और कई समस्याएं हल करता है, लेकिन मुझे नहीं लगता कि यह एक अच्छा general-purpose language है
करीब 20 साल Python इस्तेमाल करने के नजरिए से कहूं तो, अब मैं Rust में भी Python जितनी तेजी से काम करता हूं
मेरे हिसाब से Rust ने सही balance point पूरी तरह miss कर दिया है। high-level applications लिखने के लिए यह low-level details पर बहुत ज्यादा picky है, और embedded या operating systems लिखने के लिए बहुत जटिल है
पहले मामले में मैं C++, Java, Haskell, OCaml, यहां तक कि Go में थोड़ा C मिलाकर इस्तेमाल करना चुनूंगा; और दूसरे मामले में macro assembly की तरह इस्तेमाल किया जाने वाला C कहीं ज्यादा उपयुक्त है
अब भी लगता है कि Graydon Hoare की मूल परिकल्पना—यानी linear types, garbage collection, stack allocation, green threads, CPS वाला OCaml/SML—कहीं बेहतर language बनती
C में एक छोटी-सी गलती भी अक्सर undefined behavior और headaches में बदल जाती है, लेकिन Rust में ऐसा नहीं है, इसलिए उसने पूरा खेल बदल दिया
क्या आपका मतलब है कि Zig में libraries ढूंढने या यह पता लगाने की जरूरत नहीं पड़ती कि क्या करना है?
Rust आपको पहले से तय करने पर मजबूर करता है कि हर bit और byte कहां जाएगा, किस thread में इस्तेमाल होगा, और किस तरह के mutation के साथ handle होगा। parser या microcontroller level न हो तो यह प्रक्रिया उबाऊ लगती है
मुझे पहले किसी चीज को काम करवाना और फिर सबसे अच्छा API structure तय करना पसंद है, लेकिन Rust इस प्रक्रिया से टकराता है
Rust का type system ज्यादा powerful जरूर है, लेकिन Swift से भी performance का 90% मिल जाता है और flow कहीं ज्यादा natural रहता है
crates.io में namespace न होना शायद सबसे बड़ी आलोचना हो सकती है
कोई भी global generic package name पहले से कब्जा कर सकता है, और crates.io repository से बचने के अलावा ज्यादातर लोगों को इसे स्वीकार करना पड़ता है। लेकिन ऐसे कब्जा किए गए generic नामों वाले कुछ packages वास्तव में इस्तेमाल के लिए सबसे अच्छे packages नहीं हैं
शायद यह Java-style reverse DNS notation के verbose और परेशान करने वाले होने की प्रतिक्रिया रही हो, लेकिन GitHub की तरह package name के आगे user/group namespace जोड़ने का तरीका अच्छा middle ground हो सकता था
वह analysis मैंने crates.io team को भेजा और यह भी बताया कि automation पर प्रतिबंध की policy है, लेकिन जवाब मिला कि यह name squatting का पर्याप्त evidence नहीं है
crates.io की समस्या यह है कि स्पष्ट policy होने पर भी उसे enforce नहीं किया जाता। इसलिए छोटे और याद रखने में आसान crate names पहले ही ले लिए गए हैं, और उन्हें वापस पाने का कोई तरीका नहीं है
NPM, PyPI, RubyGems, Elixir का Hex, Haskell का Cabal आदि—2014~2015 के आसपास जब Rust आया था, Java के अलावा ऐसे package managers के उदाहरण याद नहीं आते जिनमें single global namespace न हो
कुछ ने बाद में इसे ठीक करने की कोशिश की, लेकिन उस समय package managers बस इसी तरह काम करते थे
बाद में आई दूसरी languages के कमजोर dependency management systems ने पिछले उदाहरणों से बहुत कम सीखा
इसका फायदा यह भी है कि language level पर global package database की जरूरत नहीं रहती। example.com/your-thing पर package डालते ही वह तुरंत release हो जाता है
बेशक, चाहें तो cache और search engine अलग से दिए जा सकते हैं
जैसे http-server खराब है, उसे मत इस्तेमाल करो और MuffinTop इस्तेमाल करो—लेकिन यह बात आपको बस पता होनी चाहिए
certified package names की धारणा दिलचस्प है, लेकिन समय के साथ alias के पीछे का code बदल जाए तो असल में confusion पैदा होने की काफी संभावना है
अंत में शायद यह किसी भी ecosystem में domain expert बनने की प्रक्रिया का हिस्सा बना रहेगा
workspace root में
.cargo/config.tomlबनाने पर यह सभी crates पर लागू होता है, इसलिए global Clippy lints set किए जा सकते हैंfile के अंदर
[build]के तहतrustflags = ["-Wclippy::lint_name_to_warn", "-Dclippy::lint_name_to_deny"]जैसा डालना होगाहालांकि
rustflagsadd नहीं करता बल्कि overwrite करता है, इसलिए अगरRUSTFLAGSenvironment variable जैसे किसी दूसरे source से value हो, तो वह इस setting को overwrite कर देगीlib.rsयाmain.rsfile में lints जोड़ने वाली script चलाते हैं। आसान हैRust पेशेवर तौर पर अहम होने वाला है, यह साफ दिख रहा है, इसलिए सीख रहा/रही हूँ। सच में इसे पसंद करना चाहता/चाहती हूँ और इसके फायदे भी दिखते हैं, लेकिन अब तक जिन भाषाओं का इस्तेमाल किया है उनमें यह सबसे अप्रिय श्रेणी में आता है
मैं लगातार उम्मीद करता/करती रहा/रही कि दक्षता बढ़ने पर नापसंदगी खत्म हो जाएगी, लेकिन learning curve चढ़ते जाने के बावजूद इससे खास लगाव नहीं हो रहा
ठीक है। यह शायद अकेली भाषा नहीं होगी जिसे मैं कुशलता से इस्तेमाल करते हुए भी नापसंद करूँ। बस Rust से प्यार करने की बात कहने वाले लोग इतने ज्यादा हैं कि लगा था मैं भी इसे enjoy करूँगा/करूँगी
लगता है Rust compiler भी मान्य मामलों के और बड़े दायरे को स्वीकार करने में बेहतर हो गया है
borrow checker को समझने की कुंजी इसके नीचे मौजूद memory model को समझना था। Rust का memory model, generics जैसी abstractions के लिए extensions को छोड़ दें, तो C जैसा ही है
borrow checker के नियम शुरुआत में मनमाने लगते हैं, लेकिन वे इस memory model से गहराई से जुड़े हैं। असली value तब है जब आप अनजाने में borrow checker से टकराते हैं, क्योंकि वह ध्यान भटकने से बना bug होता है
डरावनी बात यह है कि C या C++ जैसी भाषाएँ ऐसे code को बस स्वीकार करके आगे बढ़ सकती हैं
Rust का strict type system और borrow checker code को सही तरह से structure करने के लिए धीरे से प्रेरित करते हैं, और मुझे यकीन है कि इसने मेरी हर भाषा में code design बेहतर किया है
यह बहुत basic programmer-usability feature है जो ज्यादातर popular languages में मिलता है, और C++ तक में बहुत पहले से default arguments हैं
मैं पूर्व C/C++ programmer हूँ जो 10 साल तक लगभग हर हफ्ते pthread call करता था, और अब async Rust हर जगह इस्तेमाल करता/करती हूँ
समझ नहीं आता async से इतनी नफरत क्यों है। मेरी राय में हर किसी को हर चीज में async इस्तेमाल करना चाहिए। उन “सरल” कामों में भी जो ऊपर से single-threaded लगते हैं
अगर लेखक का use case Wasm होता, तो निश्चित रूप से अलग दृष्टिकोण बनता
बड़े buffers इस्तेमाल करने या reuse करके allocation cost से बचने वाले कामों में अक्सर पुराने ढंग के thread pool का फायदा मिलता है। bump allocator या sharded allocator से इसे कुछ हद तक संभाला जा सकता है, लेकिन vectorizable tight loop में CPU-bound होने पर thread pool बेहतर काम करता है
async अच्छा tool है, लेकिन हर context में optimal नहीं होता
Go, C#, TypeScript में ऐसी बाधा नहीं है
उदाहरण के लिए, Tokio से आने वाले decorator के बिना लगता है
mainfunction के अंदरawaitभी नहीं कर सकतेEngineजैसे कुछ itemsSendनहीं हैं, और मैं उन्हें async closure के अंदर इस्तेमाल करना चाहता/चाहती हूँGPT-4 ने thread के अंदर
tokio Runtimeबनाने औरblock_on()इस्तेमाल करने का सुझाव दिया। कल इसे आज़माने वाला/वाली हूँ। यह मेरा पहला गंभीर Rust project हैयह भी जानना चाहूँगा/चाहूँगी कि “अब async Rust हर जगह इस्तेमाल करता/करती हूँ” का मतलब “Tokio हर जगह इस्तेमाल करता/करती हूँ” है या नहीं
Rust programming सच में किसी abusive relationship जैसी नहीं है। compiler जितना हो सके मदद करने की कोशिश करता है, और खासकर rustc error messages world-class हैं
abusive relationship के ज्यादा करीब Rust compiler नहीं बल्कि operating system है। hardware भी उसी तरह assembly को सही से चलाना चाहता है, तो उस नजरिए से उसे भी abusive relationship कहा जा सकता है
Rust के error messages बेजोड़ हैं, और कोई compiler उसके करीब भी नहीं आता
साथ ही, हाल में LaTeX इस्तेमाल किया और उसके error messages भयानक थे। error को घूरते हुए समझना कि क्या गलत है, एक nightmare था
FutureअबSendऔरSyncनहीं रहा, यह मुझे सच में नापसंद हैपूरा console errors से भर जाता है, और असली syntax error कहीं बीच में दबा होता है
मुख्य शिकायत यह है कि मैं अब भी lifetimes को पूरी तरह नहीं समझता/समझती, और compiler हर बार मदद नहीं कर सकता। समझ आता है, क्योंकि compiler conservative तरीके से判断 करता है
C++ टेस्ट में अक्सर कहा जाता है, “अगर compile हो गया तो ज़्यादातर सही है”
अगर आपको लगता है कि Rust बहुत सारी errors संभाल देता है, इसलिए आम test cases बेकार हो जाते हैं, तो इसे इस बात का संकेत मानता हूं कि दूसरी languages में आपने सही चीज़ test नहीं की थी
test करने की चीज़ language की अपनी समस्याएं नहीं, बल्कि business logic है
test code देखकर अगर लगे कि “JavaScript होता तो test करता, लेकिन Rust में ज़रूरत नहीं”, तो उस test को बस हटा देना चाहिए
“business logic बनाम language problem” जैसा कोई अलगाव नहीं है। क्योंकि language वही आधार है जिस पर business logic रखी जाती है
अगर आप failure modes को test नहीं करते, तो test का मतलब क्या है, समझ नहीं आता
ज़्यादातर परिचित languages के उलट, C++ में IFNDR है, जिसे मज़ाक में “क्या यह C++ program है?” सवाल का false positive कहा जाता है
standard-compliant C++ compiler को कुछ मामलों में, जहां लिखे गए code के बेमतलब होने का शक हो, आपको बताने से मना किया जाता है, और उसे बस आगे बढ़कर कुछ output करना होता है
वह काम करने वाली executable file भी हो सकती है, या ऐसी executable file भी जो हर शुक्रवार तबाही मचाए। पता लगाने का कोई तरीका नहीं
ISO standard ऐसे cases की पहचान तो करता है, लेकिन इतना अस्पष्ट है कि ठीक-ठीक पकड़ना मुश्किल है कि क्या-क्या शामिल है, और मेरा अंदाज़ा है कि आजकल का ज़्यादातर non-trivial C++ software असल में IFNDR होगा। बेहतर है पूरी language को ही reject कर दिया जाए
Rust ने शायद आखिरकार यह सोच तोड़ दी है कि programmer को compiler की हर चीज़ पर पूरी तरह control और awareness होनी चाहिए
सच तो यह है कि दशकों से ऐसा नहीं था, और compilers लगभग magic जैसे थे। Rust ने borrowing के ज़रिए उस प्रवाह को काफी उलट दिया, लोगों को इस बात में सहज बनाया कि compiler उनसे बेहतर जानता है
काश यह और आगे तक सहज हो जाए। algorithmically ज़रूरी न हो तो collections को explicitly शुरुआत से iterate करने की ज़रूरत नहीं होनी चाहिए। कई operations implicit रूप से parallelize होने चाहिए। काश Rust जैसा Bash होता
Rust जो करता है उसमें काफी transparent है, और compiler magic को लेकर बहुत conservative है। language heap allocation नहीं करती, reference counting भी नहीं करती, और implicit numeric type conversion भी नहीं है
जिन types को implicitly copyable घोषित नहीं किया गया है, उन्हें copy नहीं करती, और वह भी सिर्फ उन types के लिए legal है जिन्हें simple shallow
memcpyसे copy किया जा सकता हैRust जगह-जगह zero-cost abstractions इस्तेमाल करता है, इसलिए यह predict किया जा सकता है कि किस code में compile होगा, और आम तौर पर वह simple होता है। standard types का default layout भी अच्छी तरह known है, इसलिए पता होता है कि
Vectraversal pointer increment करने वाले loop में compile होगा, और implicit parallelism नहीं हैborrowing को “compiler programmer से बेहतर जानता है” बताना अजीब है। borrowing type checking जैसी है। किसी type को temporary घोषित करके उसे लंबे समय तक रहने जैसा इस्तेमाल करने पर error आता है
यह वैसा ही है जैसे
Foostruct return करने की घोषणा करने वाले function सेBarreturn करने पर error आना। compiler के “बेहतर जानने” की वजह बस यह है कि आपने bug लिखा हैborrowing भी garbage collection के बिना direct pointer use में compile होती है, और C ABI structs और functions में तो literally C pointer जैसी ही होने की guarantee है। अगर आपको लगता है कि आप compiler से बेहतर जानते हैं, तो
unsafeसे lifetimes को bypass भी कर सकते हैंiter()call का नाम बदलना होता हैहालांकि मैं इस बात से सहमत नहीं कि यह implicit होना चाहिए
कुछ मायनों में Rust programmer को C से ज़्यादा control देता है। उदाहरण के लिए Rust inline assembly को standard तौर पर support करता है, जबकि C की inline assembly vendor-specific extensions पर निर्भर करती है
हालांकि convenient defaults बहुत अलग हैं। Rust में unsafe type casting कई प्रक्रियाएं और सावधानी मांगती है, और C से ज़्यादा rules follow करने पड़ते हैं
खासकर Rust के references लगभग सभी
restrictजैसे behave करते हैं, और raw pointer से safe reference मेंunsafecasting करते समय इसे बिगाड़ना बहुत आसान है। इसलिए अगर विकल्प हो, तो ऐसा code न लिखने की strong incentive बनती हैउल्टा, मैं और explicit control चाहता हूं, और ज़्यादा expressive type system से उस burden को कम करना चाहता हूं। ideally Rust का type system Prolog variant जैसा हो जाए तो अच्छा होगा
कब type constraints में invest करना है और कब नहीं, यह सीखना एक अहम lesson है
यह सिर्फ Rust की समस्या नहीं है, लेकिन इसे express करने का तरीका थोड़ा अलग हो सकता है
मैंने overly typed C++ और बहुत ज़्यादा abstracted और typed Java के साथ काम किया है, और दोनों में same तरह की refactoring problems होती हैं
इसके उलट, type की कमी और documentation की कमी वाला Go भी बहुत देखा है, जहां कुछ values इधर-उधर बिखरकर runtime landmines बन जाती हैं और refactoring सचमुच बहुत मुश्किल हो सकती है
शुरुआती progress का एहसास जल्दी आता है, लेकिन आम तौर पर bugs users तक deploy हो जाते हैं
इस trade-off का कोई magic answer नहीं है। Rust इस axis पर काफी wide range of choices देता है
“Rust दिन भर, हर दिन, उन चीज़ों पर चिल्लाता रहता है जिन्हें आप अपनी पुरानी ज़िंदगी में पूरी तरह सामान्य मानते थे” — यह बात एक अच्छा C compiler भी सभी flags चालू करने पर कुछ हद तक वैसी ही करता है
मुझे ऐसी language और compiler पसंद हैं जो चुनिंदा तौर पर चिल्लाना बंद करने दें और जानबूझकर खराब code लिखने दें। जल्दी लिखा जा सकने वाला working bad code अक्सर उस perfect code से बेहतर होता है जिसे लिखने में हमेशा लग जाए
आप पहले खराब लेकिन काम करने वाला proof of concept बना सकते हैं, फिर उसे कम खराब बना सकते हैं
“नए users को तो अच्छी तरह खींच लाता है, लेकिन libraries या tools में नाटकीय सुधार नहीं होता, और बस खास use cases के लिए one-off forks बनते हैं” — यह उम्र से जुड़ा मुद्दा नहीं है
core developers को आकर्षित करना मुश्किल है, और इसे आकर्षक बनाने के लिए बहुत मेहनत चाहिए। ऊपर से cultural conventions शुरुआती adopters तय करते हैं, और conventions का न होना भी अक्सर खराब conventions जितना ही नुकसानदेह होता है
Python को देखें: development और execution environments को ढीले तरीके से लेने के नतीजे में, Python programs को develop या run करने के करीब 50 competing तरीके बन गए
सबसे ज़्यादा इस्तेमाल होने वाला package repository PyPI सालों तक बेतरतीब रहा; मौजूदा packages पर build करने वाले कम हैं; नाम random word generator जैसे लगते हैं; ecosystem में malicious code बहुत है; और command line से packages search तक नहीं कर सकते
यह language की गलती नहीं है, बल्कि sidelines पर खड़े रहे community और core team की गलती है। Culture, उसके केंद्र की technology से ज़्यादा महत्वपूर्ण है
मेरा मकसद सिर्फ Python को निशाना बनाना नहीं है; बस मैं उस समस्या को बेहतर जानता हूँ। C आधी सदी से मौजूद है, लेकिन उसकी community भी उन solutions के आधे भी ठीक से व्यवस्थित नहीं कर पाई जो अधिक modern languages ने दे रखे हैं
Compiler आपको सुधारने के लिए चिल्लाता है, लेकिन कभी-कभी आप पूरी तरह polish करने से पहले बस idea test करना चाहते हैं