Go बनाम Rust बनाम Zig पर विचार
(sinclairtarget.com)- तीनों भाषाओं की दर्शन और मूल्य-प्रणाली के अंतर पर केंद्रित होकर, यह तुलना करती है कि हर भाषा किस समस्या को हल करना चाहती है
- Go को ऐसी भाषा के रूप में समझाया गया है जो सरलता और स्थिरता को महत्व देती है, और फीचर्स को न्यूनतम रखकर सहयोग और maintenance को आसान बनाती है
- Rust सुरक्षा और performance दोनों को साथ लेकर चलती है, और जटिल type system तथा trait संरचना के जरिए memory safety सुनिश्चित करती है
- Zig को manual memory management और data-oriented design के माध्यम से डेवलपर को पूर्ण नियंत्रण देने वाली एक प्रयोगधर्मी भाषा के रूप में वर्णित किया गया है
- तीनों भाषाओं के परस्पर विपरीत दृष्टिकोण यह दिखाते हैं कि programming language किन मूल्यों को लागू करती है, और डेवलपर किस दर्शन से सहमत है, यही चयन का आधार बनता है
भाषाओं की तुलना का दृष्टिकोण
- लेखक अपने काम में इस्तेमाल होने वाली भाषा नहीं, बल्कि नई भाषाओं के प्रयोग के जरिए हर भाषा की मूल्य-प्रणाली को समझना चाहता है
- केवल फीचर सूची की तुलना करने के बजाय, भाषा ने कौन-से trade-off चुने हैं, यह अधिक महत्वपूर्ण बताया गया है
- Go, Rust, और Zig में कार्यात्मक रूप से काफी समानताएँ हैं, लेकिन डिज़ाइनर किन मूल्यों को प्राथमिकता देते हैं, यह अलग है
- हर भाषा के दर्शन को समझकर यह आंका जा सकता है कि वह किस तरह के वातावरण और उद्देश्य के लिए उपयुक्त है
Go — सरलता और सहयोग पर केंद्रित भाषा
- Go अपनी minimalism के कारण अलग दिखती है, और इसकी एक खासियत है कि “पूरी भाषा को दिमाग में रखा जा सकता है”
- generics 12 साल बाद जोड़े गए, और tagged unions या error handling syntax sugar जैसे फीचर आज भी नहीं हैं
- नए फीचर जोड़ने में बहुत सावधानी बरती जाती है, इसलिए boilerplate code अधिक है, लेकिन भाषा की स्थिरता और readability ऊँची रहती है
- Go की slice, Rust के
Vec<T>या Zig केArrayListजैसी क्षमताओं को समेटती है, और memory location को runtime अपने-आप manage करता है - इसका डिज़ाइन C++ की जटिलता और compile delay को लेकर असंतोष से शुरू हुआ, और लक्ष्य था सरल और तेज compilation
- यह enterprise वातावरण में सहयोग की दक्षता को महत्व देती है, और जटिल फीचर्स से अधिक स्पष्ट code और consistency को प्राथमिकता देती है
Rust — जटिल लेकिन शक्तिशाली सुरक्षा और performance
- Rust “zero-cost abstractions” का दावा करती है, और कई तरह की अवधारणाओं को समेटने वाली maximalist language है
- इसे सीखना कठिन इसलिए है क्योंकि इसकी concept density अधिक है, और इसमें जटिल type system तथा trait संरचना मौजूद है
- Rust का मुख्य लक्ष्य performance और memory safety दोनों को साथ पाना है
- UB(Undefined Behavior) को रोकने के लिए compile time पर सत्यापन किया जाता है
- गलत pointer reference या double free जैसी स्थितियों से पैदा होने वाले अनुमान से बाहर behavior को रोका जाता है
- ताकि compiler code के runtime behavior को समझ सके, डेवलपर को types और traits को स्पष्ट रूप से परिभाषित करना पड़ता है
- इसी संरचना की वजह से दूसरों के code पर भरोसेमंदी बढ़ती है और library ecosystem सक्रिय बना रहता है
Zig — पूर्ण नियंत्रण और data-oriented design
- Zig इन तीनों में सबसे नई भाषा है, अभी version 0.14 पर है, और standard library documentation लगभग नहीं के बराबर है
- यह manual memory management अपनाती है, इसलिए डेवलपर को खुद
alloc()कॉल करना होता है और allocator चुनना पड़ता है - Rust या Go के विपरीत, इसमें global variables बनाना आसान है, और runtime पर “illegal behavior” पकड़े जाने पर प्रोग्राम रोक दिया जाता है
- build के समय चुने जा सकने वाले 4 release modes के जरिए performance और stability के बीच संतुलन किया जा सकता है
- इसमें object-oriented programming(OOP) फीचर्स को जानबूझकर शामिल नहीं किया गया है
- private fields या dynamic dispatch नहीं हैं, और
std.mem.Allocatorभी interface के रूप में implement नहीं किया गया है - इसके बजाय यह data-oriented design को लक्ष्य बनाती है
- private fields या dynamic dispatch नहीं हैं, और
- memory management में भी RAII शैली की सूक्ष्म object-level management के बजाय, बड़े memory blocks को समय-समय पर allocate और free करने वाली संरचना को प्रोत्साहित किया जाता है
- Zig को स्वतंत्र और anti-establishment प्रवृत्ति वाली भाषा के रूप में चित्रित किया गया है, जो OOP सोच को हटाकर डेवलपर-नियंत्रित control को अधिकतम करती है
- फिलहाल टीम सभी dependencies को फिर से लिखने के काम पर केंद्रित है, और stable version(1.0) अभी तय नहीं है
निष्कर्ष — भाषाएँ जिन मूल्यों को उजागर करती हैं
- Go के केंद्र में सहयोग और सरलता, Rust के केंद्र में सुरक्षा और performance, और Zig के केंद्र में स्वतंत्रता और नियंत्रण हैं
- तीनों भाषाओं का अंतर केवल फीचर्स का नहीं, बल्कि software development के प्रति दार्शनिक चयन का प्रतिबिंब है
- डेवलपर अंततः इस आधार पर भाषा चुनता है कि वह किन मूल्यों से सहमत है
1 टिप्पणियां
Hacker News राय
Rust में mutable global variable बनाना मुश्किल नहीं है
बस
unsafeया synchronization देने वाले smart pointers का इस्तेमाल करना पड़ता हैऐसा इसलिए है क्योंकि Rust डिफ़ॉल्ट रूप से re-entrant है और compile time पर thread safety की गारंटी देता है
अगर आपको static thread safety की परवाह नहीं है, तो इसे Zig या C की तरह आसानी से बनाया जा सकता है
फ़र्क यह है कि Rust कोड के runtime behavior के बारे में ज़्यादा guarantee tools देता है
दूसरी भाषाओं में लौटकर लोगों को इसे बेझिझक इस्तेमाल करते देखना safety के नज़रिए से पागलपन जैसा लगता है
लेकिन इस तरह की “छोटी-छोटी” चीज़ें जुड़ते-जुड़ते बिल्कुल भी आसान नहीं रहतीं
Rust इस सीमा को पहले ही पार कर चुका है, और अब यह बिल्कुल trivial नहीं है
अगर ऐसा है, तो यह C की तुलना में काफ़ी आकर्षक लगता है
यह भी जानना चाहूँगा कि जब दो variables को हमेशा साथ में lock करना पड़े, तब इसे कैसे handle किया जाता है
debugging में आख़िरकार समस्या की जड़ वही निकलती है
Rust की conceptual density की आलोचना करने वाली बात पर, मेरा मानना है कि वास्तव में उसके सिर्फ 5% concepts जानकर भी आप productive रह सकते हैं
12 साल से ज़्यादा समय से Rust इस्तेमाल कर रहा हूँ, लेकिन
#[fundamental]जैसी चीज़ का मुझे कभी उपयोग नहीं पड़ाRust में arena allocation भी किया जा सकता है, और allocator का concept भी मौजूद है
एक default allocator होता है, और आमतौर पर
Box::newजैसी explicit heap allocation का उपयोग होता हैmutable global को
static FOO: Mutex<T> = Mutex::new(...)की तरह बनाया जा सकता है, और memory safety के लिए mutex ज़रूरी हैRust का type system सिर्फ memory safety ही नहीं, बल्कि code की semantic safety सुनिश्चित करने के लिए भी डिज़ाइन किया गया है
C में इस तरह की complexity कम है
complexity आख़िरकार एक महत्वपूर्ण मुद्दा है
बात सिर्फ यह नहीं है कि कुछ संभव है या नहीं, बल्कि programming style के बुनियादी अंतर की है
Zig Software Foundation ने Asahi Lina के Rust संबंधी बयान को ग़लत quote करने का उदाहरण भी दिया गया
Zig का दूसरी languages को नीचा दिखाने वाला marketing attitude ज़्यादा पसंद नहीं आता
Zig पसंद आने का कारण यह है कि यह memory exhaustion को elegantly handle करने वाली language है
इसमें माना जाता है कि हर allocation fail हो सकता है, और उसे explicitly handle करना पड़ता है
stack space को भी जादुई चीज़ की तरह नहीं माना जाता, बल्कि compiler call graph का analysis करके maximum size infer करता है
embedded environment में ऐसी resource-oriented design अनिवार्य है
इसे language level handling से हल नहीं किया जा सकता
आख़िरकार दोनों manual memory management की समस्या से ही जूझ रहे हैं
ऐसे में मुझे लगता है कि GC language इस्तेमाल करना ज़्यादा बेहतर है
बस Rust standard library OOM पर panic करती है, इसलिए no-std environment में embedded development को सपोर्ट करने वाला अलग ecosystem मौजूद है
Go का slice Rust के
Vec<T>जैसा नहीं हैappend()एक नया slice लौटाता है, जो पुरानी memory share भी कर सकता है और नहीं भीmemory कम करने का कोई तरीका नहीं है, और अगर सिर्फ
append(s, ...)लिखें तो नया slice नज़रअंदाज़ हो जाता हैGo का रवैया है “मैंने जैसा कहा वैसा करो”, जबकि Rust का रवैया है “जाँचो कि जो कहा गया था वही हुआ या नहीं”
यानी Go simplicity के लिए mistakes को allow करता है, और Rust complexity बढ़ने पर भी mistakes कम करने की दिशा चुनता है
साथ ही सिर्फ
append(s, ...)लिखने पर compile error आता है, इसलिए मूल टिप्पणी थोड़ी inaccurate हैGo features जोड़ते समय complexity बढ़ने को लेकर काफ़ी सावधान रहने वाली language है
शायद इसलिए कि growable list को सीधे पास करने की ज़रूरत अक्सर नहीं पड़ती
अक्सर लोग docs नहीं पढ़ते और फिर हैरान होते हैं
C/C++ के UB(Undefined Behavior) को runtime checks से पकड़ना व्यवहारिक रूप से कठिन लगता है
Android ने भी हर commit पर sanitizer लगाया, लेकिन Rust पर जाने के बाद ही exploits कम हुए
यह language comparison लेख अच्छा लगा क्योंकि इसमें हर language की strengths और weaknesses ईमानदारी से रखी गई थीं
बस Raku का ज़िक्र न होना थोड़ा खला
मेरी नज़र में अगर C–Zig–C++–Rust–Go low-level languages का एक continuum हैं, तो high-level तरफ Julia–R–Python–Lua–JS–PHP–Raku–WL जैसी कड़ी बनती है
language level पर grammar definition support होने से DSL या log parsing आसान हो जाती है
VM आधारित होने से performance कम है, लेकिन problem structure को सीधे व्यक्त करने के लिए यह उपयुक्त है
Perl के उत्तराधिकारी के रूप में यह flexible और consistent language बनने की दिशा में है
यह मानना ग़लत है कि Rust में function अगर pointer लौटाता है तो heap allocation अपने-आप हो जाती है
local variables stack पर होते हैं और return के समय नष्ट हो जाते हैं, इसलिए pointer invalid हो जाता है
Rust में safe mode में pointer dereference नहीं किया जा सकता, और unsafe mode में validity की गारंटी देने की ज़िम्मेदारी developer की होती है
शायद
Box::newको “implicit allocation” समझने की ग़लती हुई हैयह या तो concept की ग़लत समझ है, या जानबूझकर mislead करने जैसा लगता है
Go की सबसे बड़ी ताकत उसका सरल concurrency model है
goroutine की वजह से parallel code आसानी से लिखा जा सकता है
interface implementations ढूँढना मुश्किल हो सकता है, लेकिन readability अच्छी होने से team collaboration में फ़ायदा मिलता है
इसमें colored function नहीं हैं, और channel-based communication इतना सरल है कि सही concurrency code जल्दी लिखा जा सकता है
संबंधित लेख: Structured Concurrency or Go Statement Considered Harmful
std.Iointerface, Go के concurrency model से मिलता-जुलता हैgokeyword का समकक्षstd.Io.async, channels काstd.Io.Queue, औरselectकाstd.Io.selectहैमुझे ऐसी language चाहिए जो Go की simplicity को Rust के result/error/enum handling और बेहतर generics के साथ जोड़े
OCaml, D, Swift, Nim, Crystal जैसी भाषाएँ देखी हैं, लेकिन अभी तक किसी ने बाज़ार पर कब्ज़ा नहीं किया है
इसकी जगह Gleam को देखना बेहतर हो सकता है
उम्मीद है कि इससे इस तरह की बार-बार आने वाली समस्याओं का हल निकलेगा
generics अभी भी कठिन चुनौती बने रहेंगे
लेख का समग्र tone अच्छा लगा क्योंकि उसमें एक नए developer का उत्साह और जिज्ञासा महसूस होती है
मेरा मानना है कि Go में generics की कमी सिर्फ minimalism नहीं थी, बल्कि trade-off पर गंभीर विचार का नतीजा थी
Rust के lifetime बहुत से लोगों के लिए सबसे कठिन हिस्सा रहे, और language innovation अक्सर पुराने concepts के संयोजन से आती है
Zig का manual memory management, OOP को हटाने से ज़्यादा Data-Oriented Design(DOD) दर्शन पर आधारित है
संबंधित talk: Andrew का DOD प्रस्तुतीकरण
असली सवाल था: “धीमा programmer, धीमा compiler, या धीमा execution — क्या चुनोगे?”
लगता है Go team ने अंततः इसका एक संतोषजनक compromise खोज लिया