मैकार्थी के 1959 के एलआईएसपी
1959 की शुरुआत में, जॉन मैकार्थी ने एक ग्रैब्रेकिंग पेपर लिखा, जिसमें सिर्फ नौ आदिम कार्यों को परिभाषित किया गया था, जो आज भी सभी LISP जैसी भाषाओं के लिए आधार बनाते हैं। कागज यहाँ डिजीटल उपलब्ध है:
http://www-formal.stanford.edu/jmc/recursive.pdf
यही है, कार्य: अपनी नौकरी पूरी तरह से एक पार्सर और मैककार्थी के लिस्प वास्तव में 1960 पत्र में वर्णित के लिए दुभाषिया लागू करने के लिए है QUOTE
, ATOM
, EQ
, CAR
, CDR
, CONS
, COND
, LAMBDA
, और LABEL
सभी कार्यात्मक होना चाहिए। उत्तर की शुद्धता पर विचार करते समय पेपर इस चुनौती पाठ पर पूर्वता लेगा, लेकिन मैंने नीचे दिए गए नौ कार्यों को संक्षेप में प्रस्तुत करने का प्रयास किया है। ध्यान दें कि भाषा सभी CAPS में होगी और कोई त्रुटि जाँच आवश्यक नहीं है, सभी इनपुट को मान्य माना जाना चाहिए।
प्रकार
- मैकार्थी के LISP में केवल दो प्रकार होते हैं: एक परमाणु और एक लिंक्ड सूची, जिसे पुनरावर्ती रूप से एक सिर के रूप में परिभाषित किया जाता है, जो एक सूची या एक परमाणु हो सकता है, और एक सूची जो सिर से जुड़ी है (पूंछ)।
NIL
एक परमाणु और एक सूची दोनों होने की विशेष संपत्ति है। - कागज के अनुसार, परमाणु नामों में केवल बड़े अक्षरों, संख्याओं और अंतरिक्ष वर्ण शामिल होंगे, हालांकि लगातार रिक्त स्थान के तारों को केवल एक स्थान माना जाना चाहिए और सभी प्रमुख और अनुगामी अंतरिक्ष वर्णों को हटा दिया जाना चाहिए। उदाहरण के बराबर परमाणु नाम (अंतरिक्ष वर्ण के साथ अंडरस्कोर को बदलें)
___ATOM__1__ = ATOM_1
:। उदाहरण परमाणु नाम के समकक्ष नहीं:A_TOM_1 != ATOM_1
- सूची को कोष्ठकों द्वारा निरूपित किया जाता है, और
NIL
प्रत्येक सूची के अंत में एक निहित है। एक सूची में एलीमेंट अल्पविराम के द्वारा अलग किया जाता और न खाली स्थान के सबसे आधुनिक Lisps में अच्छा लगता है। तो सूची(ATOM 1, (ATOM 2))
होगी{[ATOM 1] -> {[ATOM 2] -> NIL} -> NIL}
।
QUOTE
:
- एक तर्क लेता है जो एक परमाणु (एकल तत्व) या एक लिंक्ड सूची हो सकता है। तर्क बिलकुल लौटाता है।
- परीक्षण के मामलों:
(QUOTE, ATOM 1) -> ATOM 1
(QUOTE, (ATOM 1, ATOM 2)) -> (ATOM 1, ATOM 2)
ATOM
:
- एक तर्क लेता है जो एक परमाणु (एकल तत्व) या एक लिंक्ड सूची हो सकता है।
T
यदि तर्क परमाणु नहीं है, तो रिटर्न (सत्य) यदि तर्क परमाणु है, याNIL
(असत्य)। - परीक्षण के मामलों:
(ATOM, (QUOTE, ATOM 1)) -> T
(ATOM, (QUOTE, (ATOM 1, ATOM 2))) -> NIL
EQ
:
- दो तर्क लेता है जो परमाणु होना चाहिए (यदि कोई तर्क परमाणु नहीं हैं तो व्यवहार अपरिभाषित है)। रिटर्न
T
(सच) यदि दो परमाणु समान हैं, याNIL
(झूठे) यदि वे नहीं हैं। - परीक्षण के मामलों:
(EQ, (QUOTE, ATOM 1), (QUOTE, ATOM 1)) -> T
(EQ, (QUOTE, ATOM 1), (QUOTE, ATOM 2)) -> NIL
CAR
:
- एक तर्क लेता है जो एक सूची होनी चाहिए (यदि यह सूची नहीं है तो व्यवहार अपरिभाषित है)। उस सूची का पहला परमाणु (सिर) लौटाता है।
- परीक्षण के मामलों:
(CAR, (QUOTE, (ATOM 1, ATOM 2))) -> ATOM 1
CDR
:
- एक तर्क लेता है जो एक सूची होनी चाहिए (यदि यह सूची नहीं है तो व्यवहार अपरिभाषित है)। हर परमाणु लौटाता है लेकिन सूची का पहला परमाणु, यानी पूंछ। ध्यान दें कि प्रत्येक सूची एक निहित में समाप्त होती है
NIL
, इसलिएCDR
केवल एक तत्व के लिए दिखाई देने वाली सूची पर चल रहा हैNIL
। - परीक्षण के मामलों:
(CDR, (QUOTE, (ATOM 1, ATOM 2))) -> (ATOM 2)
(CDR, (QUOTE, (ATOM 1))) -> NIL
CONS
:
- दो तर्क देता है। पहला एक परमाणु या एक सूची हो सकता है लेकिन दूसरा एक सूची या होना चाहिए
NIL
। दूसरे तर्क के लिए पहले तर्क को प्रस्तुत करता है और नई बनाई गई सूची लौटाता है। - परीक्षण के मामलों:
(CONS, (QUOTE, ATOM 1), (QUOTE, NIL)) -> (ATOM 1)
(CONS, (QUOTE, ATOM 1), (CONS, (QUOTE, ATOM 2), (QUOTE, NIL))) -> (ATOM 1, ATOM 2)
COND
:
- यह LISP का "if-else" कथन है। तर्कों की एक चर-लंबाई राशि लेता है, जिनमें से प्रत्येक की लंबाई की एक सूची होनी चाहिए। 2. प्रत्येक तर्क सूची के लिए पहले कार्यकाल का मूल्यांकन करें और यदि यह सत्य है (T), तो संबंधित दूसरे पद को वापस करें और फ़ंक्शन से बाहर निकलें । यदि पहला शब्द सत्य नहीं है, तो अगले तर्क पर जाएं और उसकी स्थिति का परीक्षण करें, और तब तक जब तक कि पहली सच्ची स्थिति न पहुंच जाए। कम से कम एक तर्क की स्थिति को सच माना जा सकता है - यदि वे सभी झूठे हैं, तो यह अपरिभाषित व्यवहार है। इस फ़ंक्शन के व्यवहार का एक अच्छा उदाहरण के लिए पृष्ठ 4 देखें।
- परीक्षण के मामलों:
(COND, ((ATOM, (QUOTE, ATOM 1)), (QUOTE, 1)), ((ATOM, (QUOTE, (ATOM 1, ATOM 2))), (QUOTE, 2))) -> 1
(COND, ((ATOM, (QUOTE, (ATOM 1, ATOM 2))), (QUOTE, 2)), ((ATOM, (QUOTE, ATOM 1)), (QUOTE, 1))) -> 1
LAMBDA
:
- एक अनाम फ़ंक्शन को परिभाषित करता है। दो तर्कों को लेता है, पहला परमाणुओं की एक सूची है जो फ़ंक्शन के तर्कों का प्रतिनिधित्व करता है और दूसरा किसी भी एस-अभिव्यक्ति (फ़ंक्शन निकाय) का है, जो आमतौर पर तर्कों का उपयोग करेगा।
- परीक्षण के मामलों:
- एक अनाम "Null" फ़ंक्शन को परिभाषित और उपयोग करना:
((LAMBDA, (ATOM 1), (EQ, ATOM 1, (QUOTE, NIL))), (QUOTE, NIL)) -> T
((LAMBDA, (ATOM 1), (EQ, ATOM 1, (QUOTE, NIL))), (QUOTE, ATOM 1)) -> NIL
LABEL
:
- एक अनाम
LAMBDA
फ़ंक्शन को एक नाम देता है , जो उस फ़ंक्शन को शरीर में पुनरावर्ती रूप से कॉल करने की अनुमति देता हैLAMBDA
। दो तर्कों को लेता है, पहला एक लेबल है और दूसरा वहLAMBDA
फ़ंक्शन है जिसके लिए लेबल को बाध्य किया जाना चाहिए। दिया गया नाम वापस करता है। सभीLABEL
नामों का दायरा वैश्विक है, और एकLABEL
अपरिभाषित व्यवहार को फिर से परिभाषित करना है। - मजेदार तथ्य,
LABEL
वास्तव में पुनरावर्ती कार्यों को बनाने के लिए आवश्यक नहीं है क्योंकि अब हम जानते हैं कि इस कार्य को पूरा करने के लिएLAMBDA
एक 'Y-Combinator' के साथ उपयोग किया जा सकता है , लेकिन मूल पेपर लिखते समय मैकार्थी को इस विधि के बारे में पता नहीं था। यह वैसे भी प्रोग्राम लिखने के लिए बहुत आसान बनाता है। - परीक्षण के मामलों:
(LABEL, SUBST, (LAMBDA, (X, Y, Z), (COND, ((ATOM, Z), (COND, ((EQ, Y, Z), X), ((QUOTE, T), Z))), ((QUOTE, T), (CONS, (SUBST, X, Y, (CAR, Z)), (SUBST, X, Y, (CDR, Z))))))) -> SUBST
- (उपरोक्त चलाने के बाद)
(SUBST, (QUOTE, A), (QUOTE, B), (QUOTE, (A, B, C))) -> (A, A, C)
SUBST
उपरोक्त फ़ंक्शन की कल्पना करने में मदद करने के लिए , इसे इस पायथन-जैसे स्यूडोकोड के रूप में दर्शाया जा सकता है:
def substitute(x, y, z): # substitute all instances of y (an atom) with x (any sexp) in z
if isAtom(z):
if y == z:
return x
elif True:
return z
elif True:
return substitute(x,y,z[0]) + substitute(x,y,z[1:])
अंतिम परीक्षण मामले:
अगर मैंने इसे सही तरीके से ट्रांसफ़र किया है, तो आपके दुभाषिये को EVAL
इस कोड के साथ व्याख्या करने में सक्षम होना चाहिए :
(LABEL, CAAR, (LAMBDA, (X), (CAR, (CAR, X))))
(LABEL, CDDR, (LAMBDA, (X), (CDR, (CDR, X))))
(LABEL, CADR, (LAMBDA, (X), (CAR, (CDR, X))))
(LABEL, CDAR, (LAMBDA, (X), (CDR, (CAR, X))))
(LABEL, CADAR, (LAMBDA, (X), (CAR, (CDR, (CAR, X)))))
(LABEL, CADDR, (LAMBDA, (X), (CAR, (CDR, (CDR, X)))))
(LABEL, CADDAR, (LAMBDA, (X), (CAR, (CDR, (CDR, (CAR, X))))))
(LABEL, ASSOC, (LAMBDA, (X, Y), (COND, ((EQ, (CAAR, Y), X), (CADAR, Y)), ((QUOTE, T), (ASSOC, X, (CDR, Y))))))
(LABEL, AND, (LAMBDA, (X, Y), (COND, (X, (COND, (Y, (QUOTE, T)), ((QUOTE, T), (QUOTE, NIL)))), ((QUOTE, T), (QUOTE, NIL)))))
(LABEL, NOT, (LAMBDA, (X), (COND, (X, (QUOTE, NIL)), ((QUOTE, T), (QUOTE, T)))))
(LABEL, NULL, (LAMBDA, (X), (AND, (ATOM, X), (EQ, X, (QUOTE, NIL)))))
(LABEL, APPEND, (LAMBDA, (X, Y), (COND, ((NULL, X), Y), ((QUOTE, T), (CONS, (CAR, X), (APPEND, (CDR, X), Y))))))
(LABEL, LIST, (LAMBDA, (X, Y), (CONS, X, (CONS, Y, (QUOTE, NIL)))))
(LABEL, PAIR, (LAMBDA, (X, Y), (COND, ((AND, (NULL, X), (NULL, Y)), (QUOTE, NIL)), ((AND, (NOT, (ATOM, X)), (NOT, (ATOM, Y))), (CONS, (LIST, (CAR, X), (CAR, Y)), (PAIR, (CDR, X), (CDR, Y)))))))
(LABEL, EVAL, (LAMBDA, (E, A), (COND, ((ATOM, E), (ASSOC, E, A)), ((ATOM, (CAR, E)), (COND, ((EQ, (CAR, E), (QUOTE, QUOTE)), (CADR, E)), ((EQ, (CAR, E), (QUOTE, ATOM)), (ATOM, (EVAL, ((CADR, E), A)))), ((EQ, (CAR, E), (QUOTE, EQ)), (EQ, (EVAL, (CADR, E, A)), (EVAL, (CADDR, E, A)))), ((EQ, (CAR, E), (QUOTE, COND)), (EVCON, (CDR, E), A)), ((EQ, (CAR, E), (QUOTE, CAR)), (CAR, (EVAL, (CADR, E), A))), ((EQ, (CAR, E), (QUOTE, CDR)), (CDR, (EVAL, (CADR, E), A))), ((EQ, (CAR, E), (QUOTE, CONS)), (CONS, (EVAL, (CADR, E), A), (EVAL, (CADDR, E), A))), ((QUOTE, T), (EVAL, (CONS, (ASSOC, (CAR, E), A), (EVLIS, (CDR, E), A)), A)))), ((EQ, (CAAR, E), (QUOTE, LABEL)), (EVAL, (CONS, (CADDAR, E), (CDR, E)), (CONS, (CONS, (CADAR, E), (CONS, (CAR, E), (CONS, A, (QUOTE, NIL))))))), ((EQ, (CAAR, E), (QUOTE, LAMBDA)), (EVAL, (CADDAR, E), (APPEND, (PAIR, (CADAR, E), (EVLIS, (CDR, E), A)), A))))))
(LABEL, EVCON, (LAMBDA, (C, A), (COND, ((EVAL, (CAAR, C), A), (EVAL, (CADAR, C), A)), ((QUOTE, T), (EVCON, (CDR, C), A)))))
(LABEL, EVLIS, (LAMBDA, (M, A), (COND, ((NULL, M), (QUOTE, NIL)), ((QUOTE, T), (CONS, (EVAL, (CAR, M), A), (EVLIS, (CDR, M), A))))))
उस मधुमक्खी को चलाने के बाद, यह रेखा वापस आनी चाहिए (A, B, C)
:
(EVAL, (QUOTE, (CONS, X, (QUOTE, (B, C)))), (QUOTE, ((X, A), (Y, B))))
हालाँकि, जॉन मैकार्थी को खुद को 16 पेज पर उद्धृत करने के लिए, ऐसा लगता है जैसे वह अपने कंप्यूटर पर पात्रों से बाहर चल रहा था:
यदि कंप्यूटर पर अधिक वर्ण उपलब्ध थे, तो इसे काफी सुधार किया जा सकता है ...
इसलिए, इस चुनौती को कोड-गोल्फ टैग किया गया है और पात्रों में सबसे छोटा उत्तर विजेता होगा। मानक खामियां लागू होती हैं। सौभाग्य!
स्ट्रिंग ईवल्स पर ध्यान दें : मैं समझता हूं कि कुछ को लगता है कि लिस्प का उपयोग करके और मेजबान भाषा को फिट करने के लिए सिंटैक्स को संशोधित करके और फिर एक स्ट्रिंग का उपयोग करके इस चुनौती को जीतना संभव हो सकता है (eval)
। मैं विशेष रूप से आश्वस्त नहीं हूं कि यह दृष्टिकोण विशेष रूप से पहचानकर्ता नामकरण नियमों के साथ विशेष रूप से जीत जाएगा, और यहां तक कि अगर मुझे लगता है कि eval
सभी भाषाओं में स्ट्रिंग एस पर प्रतिबंध लगाना एक व्यक्तिपरक और फिसलन ढलान होगा। लेकिन मैं इस चुनौती को 'सही' तरीके से करने के लिए लोगों को दंडित नहीं करना चाहता, इसलिए मैं इस चुनौती के लिए दो विजेताओं को अनुमति दे सकता हूं, एक लिस्प जैसी भाषा में और एक गैर-लिस्फी भाषा में, अगर यह समस्या बन जाती है ।
((LAMBDA, (ATOM 1), (EQ, ATOM 1, (QUOTE, NIL))), (QUOTE, NIL)) -> NIL
कहां है (QUOTE NIL)
, इसलिए इसे वापस करना चाहिए T
?
-> NIL
CONS
कहा गया है कि "पहले तर्क को दूसरे तर्क पर लागू करता है और नई बनाई गई सूची को लौटाता है," लेकिन परीक्षण के मामले दूसरे तर्क को पहले से जोड़ते हुए दिखाते हैं। क्या सही है?