मैकार्थी के एलआईएसपी


39

मैकार्थी के 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सभी भाषाओं में स्ट्रिंग एस पर प्रतिबंध लगाना एक व्यक्तिपरक और फिसलन ढलान होगा। लेकिन मैं इस चुनौती को 'सही' तरीके से करने के लिए लोगों को दंडित नहीं करना चाहता, इसलिए मैं इस चुनौती के लिए दो विजेताओं को अनुमति दे सकता हूं, एक लिस्प जैसी भाषा में और एक गैर-लिस्फी भाषा में, अगर यह समस्या बन जाती है ।


1
आपके पास एक "इसनूल" फ़ंक्शन को परिभाषित करने वाला एक लैम्ब्डा उदाहरण है, लेकिन यह निल रिटर्न नील जैसा दिखता है, जब मुझे ऐसा लगता है कि इसे टी वापस करना चाहिए?
nmjcman101

1
आपके पास अंत में इनपुट ((LAMBDA, (ATOM 1), (EQ, ATOM 1, (QUOTE, NIL))), (QUOTE, NIL)) -> NILकहां है (QUOTE NIL), इसलिए इसे वापस करना चाहिए T?
nmjcman101

1
ठीक है, लेकिन आपने लिखा है-> NIL
nmjcman101

1
आपके लिए आपके विवरण में CONSकहा गया है कि "पहले तर्क को दूसरे तर्क पर लागू करता है और नई बनाई गई सूची को लौटाता है," लेकिन परीक्षण के मामले दूसरे तर्क को पहले से जोड़ते हुए दिखाते हैं। क्या सही है?
जॉर्डन

1
मैं kjetilvalle के लिस्प ट्यूटोरियल पर अपने कार्यान्वयन को आधार बना रहा हूं , और वाक्यविन्यास थोड़ा अलग है। लोअरकेस का उपयोग किया जाता है और कोई अल्पविराम मौजूद नहीं होता है। क्या मैं बस एक लोअरकेस परिवर्तन चला सकता हूं और इनपुट स्ट्रिंग से कॉमा को हटा सकता हूं ताकि यह उपरोक्त दुभाषिया के डिजाइन के अनुरूप हो या कम हो? मैं लिस्प के लिए बहुत नया हूं, लेकिन अपनी भाषा में इस चुनौती का पता लगाना चाहता हूं। अब तक मैंने पार्सर लागू किया है । (मेरी भाषा लिस्प की तरह दिखती है, लेकिन Node.js में कार्यान्वित की जाती है)
एंडरकिस

जवाबों:


17

पायथन 3, 770 बाइट्स

यह stdin / stdout पर एक REPL है। हर पंक्ति को एक पूर्ण कथन या रिक्त होने की अपेक्षा करता है। evalकार्यान्वयन को छोटा करने के लिए उपयोग किया जाता है, लेकिन अन्यथा तर्क के लिए आवश्यक नहीं है।

import re,sys;S=re.sub
P=lambda l:eval(S("([A-Z0-9][A-Z0-9 ]*)",r"' '.join('\1'.strip().split())",S("NIL","()",S("\)",",)",l))))
d={"QUOTE":'(v,L[1])[1]',"EQ":'[(),"T"][E(L[1],v)==E(L[2],v)]',
"CDR":'E(L[1],v)[1:]',"CONS":'(E(L[1],v),)+E(L[2],v)',"CAR":'E(L[1],v)[0]',
"LAMBDA":'("#",)+L[1:]',"LABEL":'[v.update({L[1]:E(L[2],v)}),L[1]][1]'}
def E(L,v):
 if L*0=="":return v[L]
 elif L[0]in d:return eval(d[L[0]])
 elif L[0]=="COND":return next(E(l[1],v)for l in L[1:]if E(l[0],v)=="T")
 elif L[0]=="ATOM":o=E(L[1],v);return[(),"T"][o*0in["",o]]
 else:l=E(L[0],v);n=v.copy();n.update({a:E(p,v)for a,p in zip(l[1],L[1:])});return E(l[2],n)
R=lambda o:o==()and"NIL"or 0*o==()and"(%s)"%", ".join(R(e)for e in o)or o
g={}
for l in sys.stdin:
 if l.strip():print(R(E(P(l),g)))

1
@Harry पहले दो परीक्षण मामलों को एक छोटे बग को ठीक करने के बाद काम करता है जिसे मैंने अंतिम टच में पेश किया था। निष्कासन निर्दोष रूप से काम करता है। लेकिन SUBSTउदाहरण अभी भी (मेरी जानकारी के लिए) एक टेस्टकेस के रूप में टूटा हुआ है। एक CONDखोजने से पहले अंत में से एक तक पहुँचता है T
orlp

1
इसे ठीक करने के लिए धन्यवाद! यह बहुत प्रभावशाली है! यह मेरे लिए अब सभी टेस्टकेस पर काम करता है, EVAL(इतने सुखद आश्चर्य के साथ कि मुझे पहली कोशिश में एक अधिकार मिल गया!) मैं आपको इनाम और स्वीकृत जवाब देने जा रहा हूं।
हैरी

2
इसके अलावा, मैं R(E(P(l)सेटअप से प्यार करता हूं ;-)
हैरी

2
@ हेरी मैं तुम्हें बच्चा नहीं है कि एक दुर्घटना थी! आर = repr, ई = eval, पी = parse, एल = line
orlp

4
बस आपको जानकारी देना चाहता था, मैंने आपके कार्यान्वयन का उल्लेख करते हुए एक लेख लिखा था !
हैरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.