Lisp पर Hofstadter की टिप्पणी (1983)
(gist.github.com/jackrusher)- Douglas Hofstadter का 1983 का लेख AI शोध में व्यापक रूप से इस्तेमाल होने वाली Lisp को एक छोटे mathematical kernel पर बनी हुई सुरुचिपूर्ण और लचीली भाषा के रूप में परिचित कराता है
- Lisp की interactivity read-eval-print loop में दिखती है, जहाँ उपयोगकर्ता expression दर्ज करता है, interpreter उसे पढ़ता है, evaluate करता है, print करता है, और फिर अगले input का इंतज़ार करता है
- Lisp objects मुख्यतः atom और list से बनते हैं, और nil एक अपवादस्वरूप स्थिति रखता है क्योंकि वह empty list भी है और atom भी
quote,eval,car,cdr,cons,setq,set,lambda,def,condcode और data को एक ही list structure में संभालने देते हैं, जिससे नए functions को धीरे-धीरे बनाया जा सकता है- function composition, conditional expressions, side effects और applicative style, तथा recursive thinking उदाहरणों के साथ जुड़े हैं, और अंत का
powerfunction तथा “porpuquine” रूपक Lisp-शैली recursion की ओर संकेत करते हैं
AI शोध और Lisp की भूमिका
- 1983 के समय AI एक ऐसा शोध क्षेत्र था जो flexibility, common sense, insight, creativity, self-awareness, और humor जैसे व्यवहारों को computers में लागू करने की कोशिश कर रहा था
- अमेरिका में लगभग 2,000 लोग AI में पेशेवर रूप से जुड़े थे, और विदेशों में भी लगभग इसी पैमाने के शोधकर्ता थे
- AI शोधकर्ता AI तक पहुँचने के सर्वोत्तम रास्ते पर काफ़ी बँटे हुए थे, लेकिन programming language के चयन में वे लगभग समान रूप से Lisp का उपयोग करते थे
- Lisp नाम “list processing” से आया है, और यह कोई पूर्ण acronym नहीं है
- Lisp का आकर्षण इस बात में है कि यह एक “crisp” और “elegant” भाषा है
- जहाँ कई भाषाएँ बहुत-सी मनमानी सुविधाएँ समेटे रहती हैं, वहीं Lisp और Algol जैसी कुछ भाषाएँ गणित की किसी शाखा की तरह एक स्वाभाविक kernel के इर्द-गिर्द बनी होती हैं
- Lisp के kernel में “crystalline purity” है, और यह purity सिर्फ़ aesthetic sense ही नहीं बल्कि flexibility में भी योगदान देती है
Mathematical logic से list processing language तक
- Lisp की गहरी जड़ें mathematical logic में हैं
- 1920–1930 के दशक में Thoralf Skolem, Kurt Godel, और Alonzo Church ने logic में जो विचार दिए, वे बाद में Lisp में शामिल हुए
- वास्तविक computer programming की शुरुआत 1940 के दशक में हुई, और Lisp जैसी high-level languages 1950 के दशक में सामने आईं
- पहली list processing language Lisp नहीं बल्कि IPL (Information Processing Language) थी
- IPL को 1950 के दशक के मध्य में Herbert Simon, Allen Newell, और J. C. Shaw ने विकसित किया था
- John McCarthy ने 1956–1958 के बीच पहले से मौजूद विचारों के आधार पर Lisp नाम की algebraic list processing language बनाई
- Lisp जल्दी ही MIT Artificial Intelligence Project के आसपास के युवा शोधकर्ताओं में फैल गई
- इसे IBM 704 पर implement किया गया और फिर दूसरे AI groups तक पहुँची
- इसके कई dialects बने, लेकिन उनका elegant central kernel साझा रहा
Interactive Lisp और REPL
- कई दूसरी high-level languages के विपरीत, Lisp को interactive language के रूप में प्रस्तुत किया गया
- उपयोगकर्ता terminal पर Lisp चलाता है, prompt देखता है, और expression दर्ज करता है
- उदाहरण:
(plus 2 2)दर्ज करने पर4print होता है और नया prompt दिखाई देता है
- उदाहरण:
- Lisp interpreter की मुख्य कार्यप्रणाली read-eval-print loop है
- expression पढ़ना
- expression को evaluate करना
- उपयुक्त value print करना
- यह संकेत देना कि अगला expression पढ़ने के लिए तैयार है
- इस संरचना की वजह से उपयोगकर्ता एक-एक करके अपनी “इच्छाएँ” दर्ज कर सकता है और तुरंत परिणाम देख सकता है
- कई non-interactive languages में पहले पूरा program लिखना और फिर उसे चलाना पड़ता है, इसलिए कई चरणों का पूरी तरह मेल खाना ज़रूरी होता है और errors ठीक करना भी अप्रत्यक्ष तथा महँगा हो सकता है
- Lisp एक समय में एक expression चलाने के तरीके से incremental development और debugging को संभव बनाती है
Polish notation और parentheses
- Lisp के arithmetic expressions में Polish notation का उपयोग होता है, जिसमें operator operands से पहले आता है
- उदाहरण:
(times (plus 6 3) (difference 6 3))का मूल्य 27 होता है
- उदाहरण:
- यह notation Polish logician Jan Lukasiewicz ने computers के आने से पहले बनाई थी
- Lisp expressions में parentheses बहुत दिखाई देते हैं
- लंबे expressions का कई closing parentheses के साथ समाप्त होना भी आम बात है
- शुरू में यह भारी लग सकता है, लेकिन आदत पड़ने पर logical structure सहज रूप से दिखने लगता है
- उदाहरणों को structure स्पष्ट करने वाली indentation के साथ pretty printing रूप में दिखाया गया है
atom, list, nil
- Lisp का केंद्र manipulable structure है, और सारे programs structures को बनाने, बदलने और नष्ट करने के तरीके से काम करते हैं
- structure दो प्रकार के होते हैं
- atom: मूल object जिसे आगे विभाजित नहीं किया जा सकता
- list: एक निश्चित क्रम में रखे गए कई elements की संरचना
- हर Lisp object या तो atom होता है या list, और केवल एक अपवाद nil है
- nil एक atom भी है और list भी
- nil empty list को दर्शाता है
()औरnilका अर्थ एक ही है, लेकिनnilअधिक प्रचलित है
- list के elements atom भी हो सकते हैं और list भी
- उदाहरण:
(zonk blee strill (croak flonk))चार elements वाली list है, और इसका अंतिम element स्वयं दो elements वाली list है
- उदाहरण:
- Lisp sentence स्वयं भी list होती है
(plus 2 2)भी एक list है- Lisp interpreter lists और atoms को manipulate करके नए “commands” बना और evaluate कर सकता है
value, quote, eval
- atoms के पास values हो सकती हैं
- numeric atoms की स्थायी value वही स्वयं होती है
- nil की value nil है
- t भी एक विशेष atom है जिसकी स्थायी value वही स्वयं है
setqatom को value assign करता है(setq pie 4)सेpieकी value 4 हो जाती है(setq pie (plus 2 2))से भीpieकी value 4 हो जाती है
- atom की value सिर्फ़ संख्या नहीं, कोई भी Lisp object हो सकती है
- atom भी और list भी
- quote evaluation को रोकता है और list या atom को ज्यों का त्यों data की तरह मानने देता है
(setq pie (plus 2 2))अंदर के expression को evaluate करकेpieमें 4 store करता है(setq pi '(plus 2 2))list(plus 2 2)को स्वयंpiमें store करता है
evalvalue के रूप में store किए गए expression को फिर evaluate करता है- यदि
piकी value(plus 2 2)है, तो(eval pi)4 लौटाता है - interpreter आम तौर पर केवल एक चरण evaluate करता है, लेकिन
evalसे अतिरिक्त evaluation माँगी जा सकती है
- यदि
car, cdr, cons
- nil को छोड़कर हर list में कम-से-कम एक element होता है, और पहले element को car कहा जाता है
(eval pi)का carevalहै(plus 2 2)का carplusहै
- car का function name होना आवश्यक नहीं है
((1)(2 2) (3 3 3))का car(1)है
- car को हटाने पर जो list बचती है, वह cdr है
(a b c d)का cdr(b c d)है- फिर क्रमशः
(c d),(d), और nil तक पहुँचा जा सकता है
- nil का न तो car होता है न cdr, और उस पर car या cdr लेने की कोशिश error देनी चाहिए
consकिसी मौजूदा list के आगे नया car जोड़कर नई list बनाता है- यदि
xका मान(cake cookie)है, तो(cons 'pie x)से(pie cake cookie)बनता है - इस दौरान मौजूदा
xनहीं बदलता
- यदि
- quote हो या न हो, इससे परिणाम बदलता है
- यदि
pieकी value 4 है, तो(cons pie x)(4 cake cookie)लौटाएगा (cons 'pie x)atom namepieको स्वयं आगे जोड़ देगा
- यदि
setq और set का अंतर
- Lisp interpreter हमेशा arguments को evaluate नहीं करता, और
setqइसका प्रमुख अपवाद है setqका पहला argument evaluate नहीं होता, बल्कि सीधे variable name माना जाता हैsetqमें q का मतलब quote है, यानी पहला argument quoted की तरह treat होता है
setsetqजैसा है, लेकिन उसका पहला argument भी evaluate होता है- यदि x की value k है, तो
(set x 7)x को नहीं बदलता बल्कि k की value 7 कर देता है
- यदि x की value k है, तो
- उदाहरण के लिए यह क्रम दिया गया है
(setq a 'b)(setq b 'c)(setq c 'a)(set a c)(set c b)
- इसे चलाने के बाद a, b, और c तीनों की values
aहो जाती हैं setआम तौर पर ज़्यादा इस्तेमाल नहीं होता, और इस तरह की उलझन भी बहुत सामान्य नहीं है
function definition और lambda
- programming की बड़ी शक्ति इस क्षमता में है कि मौजूदा operations से नए compound operations परिभाषित किए जाएँ और फिर इस प्रक्रिया को दोहराकर अधिक जटिल operations का repertoire तैयार किया जाए
- Lisp में नए functions पहले से ज्ञात functions के माध्यम से define किए जाते हैं
racऐसा example function है जो list का आख़िरी element लौटाता है- आख़िरी element पाने के लिए list को reverse करके car लिया जा सकता है
- परिभाषा:
(def rac (lambda (lyst) (car (reverse lyst))))
lambdaके बाद आने वाला(lyst)function का parameter, यानी dummy variable, दर्शाता हैdefसे define करने के बादracऐसा function बन जाता है जिसेcarकी तरह इस्तेमाल किया जा सकता है(rac '(your brains))brainsलौटाता है
readers-digest-condensed-versionनाम का function लंबी list से सिर्फ़ पहला और आख़िरी element लेकर एक छोटी list बनाता है- यदि James Joyce की Finnegans Wake को शब्दों की list माना जाए, तो इसका परिणाम
(riverrun the)होगा
- यदि James Joyce की Finnegans Wake को शब्दों की list माना जाए, तो इसका परिणाम
rejoyceनाम का उलटा operation एक कल्पित function है जो दो शब्दों से शुरू और अंत तय होने वाला उपन्यास बना दे, और इसे पाठक के अभ्यास के लिए छोड़ा गया है
return values, side effects, applicative style
- कुछ लोग मानते हैं कि Lisp और संबंधित languages में दो लक्ष्य वांछनीय और संभव हैं
- हर sentence एक value लौटाए
- sentence का प्रभाव केवल उसकी return value के माध्यम से हो
- लेख में चर्चा की गई Lisp dialects पहला लक्ष्य पूरा करती हैं, लेकिन दूसरा लक्ष्य अनिवार्य रूप से नहीं
(reverse x)स्वयं x को नहीं बदलता, बल्कि x जैसी लेकिन उल्टे क्रम वाली नई list बनाकर लौटाता है- ठीक वैसे ही जैसे
(plus 2 2)संख्या 2 की value नहीं बदलता
- ठीक वैसे ही जैसे
consभी मौजूदा list को बदले बिना नई list लौटाता है- दूसरी ओर,
setqऐसा command है जो variable binding बदलने जैसा side effect छोड़ता है- side effects में variable binding बदलने के अलावा input/output भी शामिल हो सकते हैं
- applicative programming के समर्थक केवल उसी शैली को पसंद करते हैं जिसमें functions बिना side effects के values की गणना करके आगे बढ़ाएँ
- इस शैली में स्वीकार्य binding केवल function call के दौरान अस्थायी रूप से बनने वाली lambda binding है
- function की computation समाप्त होते ही dummy variable की binding समाप्त हो जाती है
- लेख का वक्ता applicative style को elegant मानता है, लेकिन बड़े AI-शैली programs बनाने में उसे व्यावहारिक नहीं समझता
- सख़्त applicative programming में
defभी एक चरम उदाहरण बन जाता है, क्योंकि वह permanent function definition को memory में store करता है, इसलिए उसे भी स्वीकार नहीं किया जाएगा
conditional expression cond और निर्णय
- Lisp को अधिक रोचक काम करने हों, तो उसे मध्यवर्ती प्रक्रिया में होने वाली घटनाओं के अनुसार निर्णय लेने आना चाहिए, और इसके लिए conditional expressions ज़रूरी हैं
- उदाहरण:
(cond ((eq x 1) 'land) ((eq x 2) 'sea))- यदि x, 1 है तो
land - यदि x, 2 है तो
sea - अन्यथा nil लौटता है
- यदि x, 1 है तो
eqLisp का function है जो दोनों arguments की values समान होने परtऔर अलग होने परnilलौटाता हैcondsentencecondनाम से शुरू होता है और उसमें कई clauses होते हैं- हर clause condition और result से बनी 2-element list होती है
- conditions को क्रम से जाँचा जाता है, और जो पहली condition nil के अलावा कोई value लौटाए, उसका result evaluate होकर पूरे
condकी value बन जाता है - उसके बाद के clauses नहीं जाँचे जाते
- अंत में condition के रूप में
tवाला catch-all clause जोड़ देने पर nil की जगह default result लौटाया जा सकता है- उदाहरण में ऐसा
condदिया गया है जो land और sea दोनों असफल होने परairलौटाता है
- उदाहरण में ऐसा
power और recursive structure
- लेख के अंत में स्पष्ट pattern वाले function definitions आते हैं
square=k * kcube=k * square(k)4th-power=k * cube(k)- और यही क्रम आगे चलता है
- सवाल उठाया गया है कि क्या इस पूरे pattern को एक साथ समेटने वाला दो-parameter function
powerdefine किया जा सकता है(power 9 3)को 729 लौटाना चाहिए(power 7 4)को 2,401 लौटाना चाहिए
- इसके लिए ज़रूरी सारे tools मुख्य लेख में पहले ही दिए जा चुके हैं, और अब पाठक की सूझ-बूझ की परीक्षा है
- अंत की Glazunkian porpuquine कहानी recursive structure को एक रूपक की तरह पेश करती है
- porpuquine के काँटे स्वयं छोटे porpuquine हैं
- Outer Glazunkia में हमेशा 9 काँटे होते हैं, और Inner Glazunkia में हमेशा 7 काँटे
- 0-inch porpuquine के पास कोई काँटा नहीं होता, इसलिए infinite regress वहीं रुक जाता है
- इस जीव की “buying power” या “power” उसके भीतर शामिल छोटे 0-inch porpuquine noses की संख्या से जुड़ती है, और इसी रूपक के साथ पहले वाले
powerप्रश्न पर लेख समाप्त होता है
मूल पुनर्प्रकाशन का संदर्भ
- Gist की शुरुआत बताती है कि यह लेख 1980 के दशक के मध्य की Scientific American की पुरानी प्रतियों में मिला Douglas Hofstadter का Lisp परिचय है
- examples अब भी Emacs में कुछ aliases सेट करके चलाए जा सकते हैं
plus→+quotient→/times→*difference→-
- अंत में कहा गया है कि यदि आपको Hofstadter की यह अनोखी Lisp-मार्गदर्शिका पसंद आई हो, तो उनकी किताब Metamagical Themas में इसी तरह के और लेख मिल सकते हैं
1 टिप्पणियां
Hacker News टिप्पणियाँ
उदाहरण में
"oval"और"snot"फ़ंक्शन नामों से मैं उलझ गया था, लेकिन कुछ सेकंड बाद समझ आया कि ये क्रमशः"eval"और"snoc"की टाइपो हैंअसली कोड को
(cond ((eq (eval pi) pie) (eval (snoc pie pi))) (t (eval (snoc (rac pi) pi))))की तरह पढ़ा जाना चाहिएhttps://www.jstor.org/stable/24968822 से मूल Scientific American लेख डाउनलोड करके जाँचा, और सचमुच
oval/snotदरअसलeval/snocकी टाइपो निकले"oval"और"snot"सच में"eval"और"snoc"की टाइपो हैंऔर
snoc, उल्टा लिखाconsलगता है, जबकिrac, उल्टा लिखाcarयह लेख फिर दिखाता है कि Lisp की लोकप्रियता सीमित रहने का एक बड़ा कारण Lisp को समझाने का तरीका था
ऐसे Lisp लेखों ने बचपन में मुझे कुछ भी ऐसा नहीं सिखाया जिसे मैं सच में काम में ला सकूँ, और न ही यह दिखाया कि assembly/C/Pascal वगैरह के मुकाबले कोई काम X कितना आसान हो जाता है
आज मैं होता तो यह दिखाता: “assembly में 7 महीने लेने वाला स्पेल-चेकर? बैंक-switched memory वाले microcomputer पर Lisp में यह लगभग मामूली काम है, और garbage collection भी कमजोर CPU पर निर्णायक साबित हो सकता है”
अनगिनत Lisp लेख और पाठ्यपुस्तकें सिर्फ lists, recursion और AI की बातें दोहराती रहीं, लेकिन उपयोगी काम करना नहीं दिखाया, इसलिए लगता है जैसे मैंने चिमटी, चावल के दाने और गोंद से प्रोग्रामिंग सीखने में अपना समय बर्बाद किया
बचपन में मैंने Byte मैगज़ीन में पहली बार symbolic differentiation और algebraic simplification को Lisp में लिखे कोड के रूप में देखा था; उसका पीछा करना मुश्किल था, लेकिन उसमें कुछ आकर्षक ज़रूर था
Basic में वह आसान होता, ऐसा नहीं लगता; बाद में समझ आया कि वह कोड बहुत शानदार भी नहीं था, लेकिन 80 के दशक के आख़िर में PC पर XLisp और SICP मिलने के बाद ही मैं सच में Lisp का मुरीद बना
मुझे Hofstadter की लेखन शैली बहुत पसंद है। उन्होंने Lisp को खोजते समय की भावना को बहुत अच्छी तरह पकड़ा है
मैं 80 के दशक में प्रोग्रामिंग सीखने वाला एक बच्चा था, और हाई स्कूल व कॉलेज के शुरुआती दिनों तक BASIC, Fortran, Pascal, COBOL थोड़ा-बहुत कर चुका था; उनमें फ़र्क थे, लेकिन बुनियादी तौर पर वे एक जैसे ही लगते थे
फिर UC Berkeley की पहली computer science क्लास Lisp की एक बोली Scheme में हुई, और वह पूरी तरह झकझोर देने वाला अनुभव था
Hofstadter की तरह मुझे भी वह गणित के सबसे क़रीब लगी, उसने गणित के सिद्धांत वाले कोर्सों की बहुत याद दिलाई, और वह पहली भाषा थी जो मुझे सच में सुंदर लगी
यह उद्धरण मुझे ख़ास तौर पर पसंद आया: “Lisp और Algol गणित की किसी शाखा की तरह एक स्वाभाविक कोर के आसपास बनाए गए थे। Lisp के केंद्र में एक स्फटिक जैसी शुद्धता है, जो सिर्फ़ सौंदर्यबोध को आकर्षित नहीं करती, बल्कि उसे अधिकांश भाषाओं से कहीं अधिक लचीला भी बनाती है”
एक ऐसे व्यक्ति के नज़रिए से भी जो algebraic topology का शोधकर्ता बनना चाहता था, Scheme दरअसल उस प्रोग्रामिंग शैली की सुघड़ और न्यूनतम अभिव्यक्ति के अधिक क़रीब है जो dynamic typing और garbage collection वाली भाषाओं में व्यापक है
यह इस अर्थ में “theory” जैसा लगता है कि यह बहुत पूर्ण दिखता है, और Scheme में समस्या-समाधान का तरीका सोच लेने के बाद आप उसे दूसरी dynamic typed भाषाओं में भी ले जाकर सुरुचिपूर्ण हल तक पहुँच सकते हैं
Scheme उस दौर के पारंपरिक Lisp की तुलना में lexical scope, functions और variables के लिए एकल namespace जैसी बातों में अधिक सरल और व्यवस्थित भाषा थी
1983 तक इस क्षेत्र की शुरुआत को लगभग 20 साल हो चुके थे, फिर भी इसमें ऐसे AI की बात हो रही है जो “लचीलापन, सामान्य समझ, अंतर्दृष्टि, रचनात्मकता, आत्म-जागरूकता, हास्य” रखे
मज़ेदार बात यह है कि यह सूची उन चीज़ों की सूची जैसी लगती है जिनमें LLM वास्तव में कमज़ोर हैं
फिर भी कम से कम उस दिशा में शून्य से अधिक प्रगति तो हुई है
शायद उससे भी ज़्यादा दिखाया है, लेकिन ऐसा कहने पर मुझे ख़ुद भी थोड़ा अजीब लगता है
भले ही बहुत सी चीज़ें अब तक ठोस नतीजों में नहीं बदलीं, फिर भी उन्हें पढ़ना दिलचस्प है
इस लेख के साथ जिन दो साथी लेखों का ज़िक्र हुआ है, वे Hofstadter की किताब Metamagical Themas के अध्याय 17~19 में हैं, और Scientific American की उसी शृंखला के दूसरे लेख भी उसमें शामिल हैं
[0]: https://www.goodreads.com/book/show/181239.Metamagical_Thema...
किताब का शीर्षक Martin Gardner के Scientific American में लिखे “Mathematical Games” का anagram है, और Hofstadter ने वही शृंखला आगे संभाली थी
लेख में कहा गया है कि
nilपरcarयाcdrलागू करने से 0 से भाग देने जैसी त्रुटि आनी चाहिए, लेकिन आधुनिक Lisp में अक्सर अब ऐसा नहीं होता।John McCarthy द्वारा परिभाषित मूल Lisp में
CARऔरCDR,NILके लिए परिभाषित नहीं थे: <https://dl.acm.org/doi/pdf/10.1145/367177.367199>लेकिन Common Lisp और Emacs Lisp
(car nil)और(cdr nil)कोnilके रूप में परिभाषित करते हैं: <https://www.lispworks.com/documentation/HyperSpec/Body/f_car...>, <https://www.gnu.org/software/emacs/manual/html_node/elisp/Li...>LISP 2156में(status lispversion)ने/2156लौटाया, और(car nil)तथा(cdr nil)दोनों नेNILलौटाया।carऔरcdrजैसे बेहद ठोस implementation details इतने केंद्रीय थे।“List Processor” के सबसे बुनियादी और सबसे प्रसिद्ध operators वास्तव में list पर नहीं, बल्कि cons पर काम करने के लिए बनाए गए थे, जो वह खास machine representation element है जिससे Lisp data structure बनाता है।
cons को हमेशा list के रूप में नहीं समझा जाता, और list-recursive functions का बेहद महत्वपूर्ण base case भी cons से व्यक्त नहीं होता।
60 साल बाद भी ज़्यादातर Lisp programs cons operations से भरे हुए हैं, और शायद इसका ज़्यादा सटीक नाम “Cons Processor” होता।
यह याद दिलाता है कि Lisp उस दौर में पैदा हुआ था जब language और implementation को एक-दूसरे में गुँथा होना पड़ता था, और इसी वजह से computer language को mathematical logic पर आधारित करने की उपलब्धि और भी अधिक चौंकाने वाली लगती है।
nilकाCARयाCDRलेने पर त्रुटि मिलती है।nilकाcar/cdrत्रुटि देता है, इसलिए मेरे जैसे शुरुआती व्यक्ति के लिए code काफ़ी unergonomic लगता है।फिर भी Common Lisp की तुलना में मैं Guile Scheme को ज़्यादा पसंद करता हूँ, इसलिए थोड़ा अफ़सोस है।
nilपर कुछ लागू करने पर त्रुटि दिए बिना फिर सेnilलौटाया जाता है।SQL याद आता है, और व्यक्तिगत रूप से मुझे यह अच्छा विकल्प नहीं लगता, इसलिए अगर इसका कोई और नाम नहीं है तो मैं इसे “bleeding nils/NULLs” कहना चाहूँगा।
खासकर अगर boolean comparison में
nil,falseके बराबर भी न हो, तो यह और खराब हो जाता है।Ruby और Elixir में
nilकोfalseकी तरह माना जाता है, और Elixir शुद्ध boolean ही लेने वालेandतथाnilकोfalseमानने वाले&&को अलग-अलग प्रदान करता है।ऐसा डिज़ाइन शुरू में code को साफ़-सुथरा बना सकता है, लेकिन असल त्रुटि वाले गलत तरीके से संभाले गए
nilकई call stacks बाद बिलकुल किसी और जगह सामने आ सकते हैं, जिससे debugging बहुत कठिन हो जाती है।इस लेख की Lisp संबंधी जानकारी मुझे पहले से पता थी, फिर भी इसे पढ़ना मज़ेदार लगा। Hofstadter की भाषा में सचमुच एक आकर्षण है।
खासकर यह मज़ाक बहुत अच्छा लगा कि उसने
readers-digest-condensed-versionकी inverse operation के रूप मेंrejoyceबनाया, ताकि(rejoyce 'Stately 'Yes)चलाने पर कोई Lisp परी James Joyce द्वारा लिखी गई हो सकती Ulysses की पूरी किताब शुरू से पैदा कर दे।इसमें थोड़ा समय लगा, लेकिन हम आखिरकार उस बिंदु तक पहुँच ही गए; और भले ही 2024 का AI, 1983 में उसकी कल्पना से पूरी तरह एक जैसा नहीं है, छोटे seed से text को फिर से उत्पन्न करना आज के AI के लिए काफ़ी उपयुक्त काम है।
Lisp को अब भी ऐसी प्रमुख language में माना जाता है जो Hofstadter द्वारा चर्चा किए गए strange loop की अवधारणा को समेट सकती है
केवल Lisp ही homoiconic language नहीं है, लेकिन जिन languages का लोग वास्तव में उपयोग करना जानते हैं, उनमें यह उस बड़े वर्ग का हिस्सा है जहाँ
evalको parse करने के लिए string नहीं लेनी पड़तीयह बात खटकती है कि लोग अक्सर Lisp को पूरे functional programming का पर्याय मान लेते हैं
functional programming से कोई आपत्ति नहीं है, लेकिन Lisp का symbolic character कहीं अधिक दिलचस्प है, और
(go tag)सेक्शन से चलने वाला code बनाकर GOTO-शैली का programming भी बहुत आसानी से किया जा सकता है — यह अंतहीन रूप से मज़ेदार हैXSLT और XML का उपयोग करके repetitive code सीधे लिखने के बजाय XSLT generate करने वाली metaprogramming क्षमता काफ़ी व्यापक रूप से इस्तेमाल हुई
हालाँकि, इसकी syntax Lisp की syntax से भी बड़ी समस्या थी
ऐसी language बनाना आसान नहीं है जिसकी syntax रोज़मर्रा के उपयोग के लिए अच्छी हो और साथ ही abstract syntax tree के रूप में संभालना भी बहुत कठिन न हो, और Lisp इस मामले में अपेक्षाकृत सफल बहुत कम उदाहरणों में से एक है
functoolsसे सहज रूप में नहीं मिलता: https://docs.python.org/3/library/functools.htmlमैं Lisp के बिना symbolic AGI बना रहा हूँ, इसलिए experts से कुछ संकेत सुनना चाहता हूँ
मेरी समझ में Python पक्ष की सुविधाएँ
filter(),map(),reduce()जैसी वे functions हैं जो iterable objects पर दूसरी functions लागू करती हैं;@singledispatchजैसे wrappers जो call को route करते हैं;@cacheऔरpartial()जैसी functions जो flow control या performance convenience देती हैं; औरwraps()जैसी functionality जो मनमाने ढंग से functions को wrap करती हैइनमें से ज़्यादातर चीज़ें functions को असामान्य तरीक़े से call करने की convenience जैसी लगती हैं, और Lisp की उस प्रशंसा के स्तर तक पहुँचती नहीं दिखतीं जहाँ “आत्म-चिंतन” को first-class concern की तरह लिया जाता है
मैं जानना चाहता हूँ कि ऊपर की सुविधाओं से परे Lisp वास्तव में क्या देता है
वे Lisp का उपयोग concepts समझाने के साधन के रूप में करते हैं, और वे concepts प्रायः functional recursion के इर्द-गिर्द घूमते हैं
Scheme और उसके आसपास की culture भी इसमें भूमिका निभाती है
Scheme केवल functional language नहीं है, लेकिन यह पहले की Lisp family की तुलना में pure programming पर अधिक ज़ोर देती है, base language में looping constructs के बजाय tail recursion structure देती है, और implementations से tail call optimization की अपेक्षा करती है
Common Lisp में भी
defaliasको macro के रूप में define किया जाए तो इसे Emacs केdefaliasकी तरह इस्तेमाल किया जा सकता है: https://stackoverflow.com/questions/24252539/defining-aliase...Metamagical Themas में छपे Hofstadter के Lisp लेख मुझे पसंद आए थे, और उस series के आख़िरी लेख के code को मैंने workplace study group के लिए Clojure के अनुरूप रूपांतरित करके व्यवस्थित किया था
[1] http://johnj.com/posts/oodles/