छह दशक बाद भी Lisp क्यों मायने रखती है
Lisp 65 साल से ज़्यादा पुरानी है, फिर भी आधुनिक भाषा-डिज़ाइन को प्रभावित कर रही है। जानिए यह क्यों टिकी है और आज के developers इससे क्या सीख सकते हैं।

हर कुछ साल में कोई न कोई 'Lisp मर चुकी है' वाला निबंध लिख देता है, और हर कुछ साल में कोई और याद दिला देता है कि आपकी पसंदीदा आधुनिक भाषा के आधे फीचर Lisp से ही चुराए गए थे। Garbage collection, first-class functions, closures, dynamic typing, homoiconicity, REPL-driven development, macros — ये सब आज के ज़्यादातर developers के पैदा होने से पहले Lisp में ईजाद या लोकप्रिय हो चुके थे। Lisp वह प्रोजेक्ट है जिसे पूरी तरह समझने में दशकों लगते हैं।
फिर भी। किसी कामकाजी developer से पूछिए कि क्या उसने कभी Lisp इस्तेमाल किया है, तो ज़्यादातर का जवाब 'नहीं' होगा। पूछिए कि क्या वे Lisp में production प्रोजेक्ट शुरू करेंगे, तो ज़्यादातर आपको अजीब नज़रों से देखेंगे। यहाँ एक विरोधाभास है: Lisp के विचारों ने प्रोग्रामिंग की दुनिया पर कब्ज़ा कर लिया, लेकिन Lisp खुद आज भी एक niche भाषा बनी हुई है। यह समझना उन 'Lisp अच्छी है, बाकी भाषाएँ बेकार हैं' वाली बातों से कहीं ज़्यादा दिलचस्प है जो अक्सर Lisp के प्रचार में सुनने को मिलती हैं।
Lisp ने वास्तव में क्या सही किया
Lisp को John McCarthy ने 1958 में बनाया था। संदर्भ के लिए, FORTRAN उस समय सिर्फ़ एक साल पुरानी थी। COBOL तब अस्तित्व में ही नहीं था। PDP-1 मिनीकंप्यूटर को अभी दो साल और लगने थे। Lisp पहले कागज़ पर डिज़ाइन हुई और फिर IBM 704 पर लागू की गई — एक ऐसी मशीन जो पूरा कमरा घेरती थी और जिसके शब्द 36-bit के थे।
इसके बावजूद, McCarthy ने ऐसे डिज़ाइन फ़ैसले लिए जो छह दशक बाद भी प्रासंगिक हैं। सबसे बड़े फ़ैसले ये हैं:
कोड के रूप में डेटा (Homoiconicity)
ज़्यादातर भाषाओं में code और data मूल रूप से अलग चीज़ें होती हैं। आप एक syntax में code लिखते हैं, और वह data structures को manipulate करता है। Lisp में code ही data है। एक Lisp प्रोग्राम lists से बना होता है। (+ 1 2) एक साथ दो चीज़ें है: 1 और 2 को जोड़ने वाली function call, और तीन elements वाली एक list — symbol +, संख्या 1 और संख्या 2। आप उस list को बदल सकते हैं — उसके elements को पुनर्व्यवस्थित करें, नए जोड़ें, रूपांतरित करें — और फिर परिणाम को execute कर सकते हैं।
;; This is a function call
(+ 1 2) ; => 3
;; This is a list containing the same elements
'(+ 1 2) ; => (+ 1 2)
;; You can build code as data and then evaluate it
(def my-expr '(+ 1 2))
(eval my-expr) ; => 3
;; Or transform it
(def doubled (list '* 2 my-expr))
;; doubled is now (* 2 (+ 1 2))
(eval doubled) ; => 6
यह एक जिज्ञासा जैसा लगता है, जब तक आप यह नहीं समझते कि यह क्या संभव बनाता है: ऐसे प्रोग्राम जो दूसरे प्रोग्राम लिखते हैं। Lisp macros, C preprocessor macros की तरह सिर्फ़ text substitution नहीं करते। वे असली प्रोग्राम की structure को एक data structure के रूप में पाते हैं, भाषा की पूरी ताकत से उसे बदलते हैं, और नई program structure लौटाते हैं। यह compile time पर code generation है, जहाँ compiler खुद आपका API बन जाता है।
REPL बतौर Development Environment
Lisp ने Read-Eval-Print Loop को लोकप्रिय बनाया — यह विचार कि आप कोई expression टाइप करें, तुरंत evaluate हो और परिणाम दिखे। आज जब हर भाषा में REPL है, यह सुनने में साधारण लगता है, लेकिन Lisp का REPL ज़्यादातर से आगे जाता है।
Common Lisp या Clojure में आप REPL में सिर्फ़ अलग-थलग expressions टेस्ट नहीं करते। आप पूरे system को interactively develop करते हैं। आप एक function define करते हैं, टेस्ट करते हैं, फिर redefine करते हैं, यह सब प्रोग्राम चलते हुए। आप चल रही state को देख और बदल सकते हैं। आप application को रीस्टार्ट किए बिना एक ही function को recompile कर सकते हैं। Development cycle write-compile-run-debug नहीं है — यह एक ज़िंदा system के साथ लगातार बातचीत है।
खासकर Clojure developers अक्सर इसी तरह काम करते हैं: वे अपने editor को एक चल रहे REPL से जोड़ते हैं, editor में code लिखते हैं, एक keystroke से अलग-अलग expressions evaluate करते हैं और नतीजे तुरंत देखते हैं। Feedback loop मिनटों में नहीं, मिलीसेकंड में मापा जाता है। एक बार इस तरह काम करने के बाद, पारंपरिक edit-compile-restart चक्र डाक से चिट्ठियाँ भेजने जैसा लगने लगता है।
न्यूनतम Syntax, अधिकतम लचीलापन
Lisp का syntax — या उसकी कमी — उसकी सबसे विवादास्पद विशेषता है। if statements, for loops या class definitions के लिए कोई special forms नहीं हैं। सब कुछ एक list है जिसमें operator सबसे पहले आता है: (if condition then-expr else-expr), (defn name [args] body), (for [x (range 10)] (* x x))। जिन कोष्ठकों से नए लोग दूर भागते हैं, वे अब तक डिज़ाइन की गई सबसे नियमित syntax वाली भाषा की कीमत हैं।
इस नियमितता का व्यावहारिक फ़ायदा है: tooling। जब हर construct एक ही (operator operands...) पैटर्न का पालन करता है, तो editors भरोसे के साथ indent, refactor और code में structurally navigate कर सकते हैं। 'enclosing expression चुनो' Lisp में बिल्कुल साफ़ है — वह हमेशा मिलते हुए कोष्ठक ही होता है। जिन भाषाओं में syntax विविध है, वहाँ structural editing अभी भी एक अनसुलझी समस्या है। Lisp में यह 1960 के दशक से हल हो चुकी है।
Lisp जीती क्यों नहीं
अगर Lisp इतनी अच्छी है, तो हर कोई इसका इस्तेमाल क्यों नहीं करता? Lisp के standard समर्थक का जवाब होता है 'इंडस्ट्री गलत है', जो न तो मददगार है और न ही ज़्यादातर सच। Lisp को मुख्यधारा में जगह न मिलने के पीछे असली, गैर-मामूली कारण हैं।
- Ecosystem की कमी। ज़्यादातर व्यावहारिक काम के लिए libraries, भाषा के फीचरों से ज़्यादा मायने रखती हैं। Python इसलिए लोकप्रिय नहीं है कि उसका syntax सुंदर है — बल्कि इसलिए कि
pip installसे data science, web development, machine learning और बाकी हर चीज़ के लिए हज़ारों अच्छी तरह मेंटेन की गई packages तुरंत मिल जाती हैं। Lisp के ecosystems (Common Lisp, Scheme, Clojure) ठोस हैं, लेकिन छोटे हैं। आप चीज़ें शून्य से लिखने में, या कम मेंटेन की गई libraries को अपनाने में ज़्यादा समय लगाएँगे। - सीखने की कठिनाई शुरू में ही आती है। Lisp का कोष्ठकों वाला syntax एक बार समझ आने पर बेहद सरल है, लेकिन नए लोगों के लिए यह एक असली बाधा है। इससे भी ज़्यादा, idiomatic Lisp लिखने के लिए ऐसे सोचना पड़ता है जो procedural या object-oriented भाषाओं से आए लोगों के लिए अनजाना है। इसका फ़ायदा बाद में मिलता है, लेकिन कई developers वहाँ तक पहुँचने से पहले ही छोड़ देते हैं।
- बिखराव। 'Lisp' कोई एक भाषा नहीं, बल्कि एक परिवार है। Common Lisp, Scheme, Racket, Clojure, Emacs Lisp, Hy, Janet — हर एक की अलग ताकत, अलग ecosystem और अलग community है। यह बिखराव उस प्रयास के केंद्रीकरण को रोकता है जिससे ecosystems बढ़ते हैं।
- कॉर्पोरेट समर्थन मायने रखता है। Java के पीछे Sun था। C# के पीछे Microsoft। Go के पीछे Google। Python के पीछे Google और एक विशाल data science community। Lisp परिवार की production में सबसे सफल भाषा, Clojure, को गति आंशिक रूप से इसलिए मिली क्योंकि Rich Hickey एक असाधारण स्पष्ट विचारक और communicator हैं — फिर भी उसमें वह संस्थागत धक्का नहीं है जो मुख्यधारा अपनाने को चलाता है।
Clojure: वह Lisp जिसने इतिहास से सीखा
Clojure पर विशेष ध्यान देना ज़रूरी है, क्योंकि यह दिखाती है कि Lisp की ताकत को आधुनिक software development के लिए व्यावहारिक कैसे बनाया जाए। Rich Hickey ने 2007 में Clojure डिज़ाइन की, इस साफ़ समझ के साथ कि पिछली Lisps मुख्यधारा में क्यों नहीं पहुँचीं, और उन्होंने सोच-समझकर समझौते किए।
- JVM पर चलती है। शून्य से एक अलग ecosystem बनाने के बजाय, Clojure Java Virtual Machine पर चलती है और किसी भी Java library को सीधे इस्तेमाल कर सकती है। Database driver चाहिए? Java वाला इस्तेमाल करें। HTTP client चाहिए? Java वाला इस्तेमाल करें। इस एक फ़ैसले ने Clojure को पहले ही दिन से हज़ारों परखी हुई libraries तक पहुँच दे दी।
- डिफ़ॉल्ट रूप से Immutability। Clojure के core data structures — lists, vectors, maps, sets — immutable हैं। आप map को modify नहीं करते, बल्कि अपने बदलावों के साथ नया map बनाते हैं। इससे concurrency bugs की पूरी श्रेणियाँ खत्म हो जाती हैं और प्रोग्राम को समझना आसान होता है। भीतर के persistent data structures इसे कुशल बनाने के लिए structure साझा करते हैं।
- व्यावहारिक concurrency primitives। Atoms, refs, agents — Clojure कई concurrency models देती है, जो अलग-अलग patterns के लिए उपयुक्त हैं। यह केवल सैद्धांतिक खूबसूरती नहीं थी; यह production Java applications में shared mutable state के दर्द का Hickey का सीधा अनुभव था।
- ClojureScript। Clojure JavaScript में compile होती है, जिससे उसे browser और Node.js ecosystems मिलते हैं। Backend Clojure में लिखें, frontend ClojureScript में, और दोनों के बीच code साझा करें। यह वही वादा है जो TypeScript या Kotlin Multiplatform करते हैं, लेकिन यह पहले आ गया।
आधुनिक भाषाओं ने क्या उधार लिया
भले ही आपने Lisp की एक भी लाइन न लिखी हो, आप रोज़ उसके विचारों का इस्तेमाल कर रहे हैं। इसका प्रभाव इतना व्यापक है कि उसे ट्रैक करना यह देखने का अभ्यास बन जाता है कि यह कितनी गहराई तक गया है।
JavaScript के map, filter और reduce Lisp के list-processing functions के सीधे वंशज हैं — भाषा का नाम ही उनसे पड़ा है (LISt Processing)। Python की list comprehensions उन्हीं operations का syntactic sugar हैं। Rust की pattern matching ML के रास्ते Lisp के cond expressions तक जाती है। Swift के closures, Kotlin का lambda syntax, Java का streams API — ये सब अलग कपड़ों में पहनी हुई Lisp की अवधारणाएँ हैं।
Rust (macro_rules! और procedural macros), Elixir, Nim और Julia के macro systems सीधे Lisp macros से प्रेरित हैं — हालाँकि इनमें से कोई भी ठीक वैसी सहजता नहीं पाता, क्योंकि इन भाषाओं में homoiconic syntax नहीं है। जब आपका code data है, तो macros सरल होते हैं। जब code का syntax जटिल हो, तो macros को उस syntax को parse और generate करना पड़ता है, जिससे घर्षण बढ़ता है।
REPL-driven development data science में आदर्श बन चुका है (Jupyter notebooks असल में persistence वाले REPL ही हैं), और Figwheel तथा shadow-cljs जैसे टूल्स ने frontend development में hot-reloading लाए — यह विचार सीधे उस Lisp परंपरा से आया है जिसमें एक चल रहे system के खिलाफ़ develop किया जाता है।
क्या आपको Lisp सीखनी चाहिए?
ईमानदार जवाब इस पर निर्भर करता है कि आप इससे क्या पाना चाहते हैं।
अगर आप code के बारे में सोचने का तरीका बढ़ाकर बेहतर programmer बनना चाहते हैं: हाँ, बिल्कुल। Lisp सीखना — खासकर data transformation, recursive structures और code-as-data के रूप में सोचना — आपके किसी भी भाषा में problems हल करने के तरीके को बदल देगा। यह functional programming सीखने जैसा है: भले ही आप production में Haskell कभी न लिखें, इसकी अवधारणाएँ आपको बेहतर Python और JavaScript लिखने में मदद करती हैं।
अगर आप Lisp के साथ production software बनाना चाहते हैं: Clojure व्यावहारिक विकल्प है। इसका असली ecosystem है, एक पेशेवर community है, और कंपनियाँ (Nubank, Walmart, CircleCI) इसे बड़े पैमाने पर चलाती हैं। Common Lisp व्यवहार्य है लेकिन niche है — आप अपनी असली समस्या की बजाय infrastructure पर ज़्यादा समय लगाएँगे। Scheme और Racket शिक्षा और भाषा अनुसंधान के लिए उत्कृष्ट हैं, लेकिन सामान्य-उद्देश्य development के लिए कम व्यावहारिक।
अगर आप जिज्ञासु हैं लेकिन अभी प्रतिबद्ध होने के लिए तैयार नहीं, तो कुछ Clojure code पढ़िए। Tutorials नहीं — असली production code। देखिए कि Clojure developers छोटे functions को कैसे compose करते हैं, data pipelines बनाने के लिए threading macros (-> और ->>>) का कैसे उपयोग करते हैं, और classes की जगह सादे maps से domains को कैसे model करते हैं। आपको प्रोग्रामिंग की एक ऐसी शैली दिखेगी जो मुख्यधारा की OOP codebases में मिलने वाली शैली से अधिक संक्षिप्त, अधिक composable और data flow पर अधिक केंद्रित है।
Lisp का टिके रहना नॉस्टैल्जिया नहीं है। यह कुछ बुनियादी बातों को इतना सही करने का नतीजा है कि छह दशकों की language design भी उनमें सुधार नहीं कर पाई। कोष्ठक अजीब हैं। Ecosystem जितना चाहेंगे उतना बड़ा नहीं है। लेकिन इसके विचार कालातीत हैं, और अगर आप इनके साथ समय बिताएँगे, तो पाएँगे कि जिस भी भाषा में आप रोज़ काम करते हैं, उसमें आप बेहतर code लिख रहे हैं।


