Jump to content

Լիսպ

Վիքիպեդիայից՝ ազատ հանրագիտարանից
Լիսպ
Изображение логотипа
Տեսակբազմահարացուցային ծրագրավորման լեզու, ֆունկցիոնալ ծրագրավորման լեզու, ծրագրավորման պրոցեդուրային լեզու, պծրագրավորման ռեֆլեքսիվ լեզու, metaprogramming language? և ծրագրավորման ինտերպրետացվող լեզու
Սեմանտիկաֆունկցիոնալ
Կատարման ձևինտերպրետացիա և կոմպիլյացիա
Առաջացել է1958 թ․
ՍտեղծողՋոն ՄակՔարթի
ՆախագծողՋոն Մաքքարթին (համակարգչային գիտություն)
Տիպիզացիադինամիկ
Ներշնչվել էInformation Processing Language?
Ներշնչել էCommon Lisp, Scheme
ՀմայագիրThe Lisp alien?
 Lisp (programming language) Վիքիպահեստում

Լիսպը (LISP, անգլ. LISt Processing – «ցուցակների մշակման լեզու») ծրագրավորման լեզուների ընտանիք է, որում տվյալներն ու ծրագրերը ներկայացվում է գծային ցուցակների միջոցով[1]։ Լիսպի հիմնադիր Ջոն ՄակՔարտին[2] զբաղվում էր արհեստական ինտելեկտի հետազոտություններով և նրա կողմից ստեղծված լեզուն հանդիսանում է արհեստական ինտելեկտի մոդելավորման հիմնական միջոցներից մեկը։

Ավանդական լիսպում օգտագործվում է տիպերի դինամիկ համակարգը։ Լեզուն համարվում է ֆունկցիոնալ, սակայն ունի սիմվոլների մշակման լիարժեք համակարգ, որը թույլ է տալիս իրականացնել օբեկտ-կողմնորոշվածություն, որի օրինակ է CLOS պլատֆորման։

Ճարտարապետություն և շարահյուսություն

[խմբագրել | խմբագրել կոդը]

Լեզվի հիմնական տարրերը

[խմբագրել | խմբագրել կոդը]

Լեզվի հիմնական տարրեր են հանդիսանում սիմվոլները, ատոմները և դրանցից կառուցված ցուցակները՝ S-արտահայտությունները։

Լիսպում սիմվոլը օբեկտ է մեքենայական հիշողության մեջ, որը հանդիսանում է սլոթերի ամբողջականություն և պահում է հղումներ։ Սլոթերի մի մասն ունի լեզվի կողմից նախապես որոշված նշանակություն.

  • անուն – նիշերի տող, ըստ որի ծրագիրը կարող է հղվել տվյալ սիմվոլի վրա։
  • Ֆունկցիոնալ սլոթ – սիմվոլի հետ կապակցված լամբդա արտահայտություն։ Երբ ծրագրում սիմվոլին դիմելու հնարավորությունը շարահյուսորեն համապատասխանում է ֆունկցիայի կանչի, հաշվարկվում է սիմվոլի հետ կապված լամբդա արտահայտություն։
  • արժեք – օբեկտ մեքենայական հիշողության մեջ, որը կարելի է մեկնաբանել ինչպես տվյալները։ Երբ ծրագիրը սիմվոլին դիմում է որպես փոփոխականի, ստանում է տվյալ սլոթի արժեքը։

Սլոթերի հավաքածուն դինամիկ ընդլայնվող է և կարող է օգտագործվել որպես սիմվոլի անկախ հատկությունների ցուցակ։

Ատոմները սիմվոլներն են և թվերը։ Թվերը չեն հանդիսանում լիսպի սիմվոլներ, քանի որ կարող են ընդունել միայն սեփական թվային արժեքը։ Բայց միաժամանակ թվերը կարող են սլոթերին հավասար ընդգրկվել ցուցակների մեջ։ Դրանով ել պայմանավորված է դրանց միավորումը միասնական կատեգորիայի մեջ։

Լիսպում տվյալների հիմնական կառուցվածքը ատոմների դինամիկ ցուցակն է, որը ռեկուրսիվ սահմանվում է որպես “գլուխ”-օբեկտ և նրան ամրացված ցուցակ-“պոչ”: Քանի որ գլուխն իր հերթին կարող է լինել ցուցակ, ցուցակը փաստացի հանդիսանում է ծառի մոդել ( վերին մակարդակի ցուցակ – արմատ, դրա մեջ մտնող ենթացուցակներ – ճյուղեր, ատոմներ – տերևներ )։ Ատոմների և ցուցակների համար լեզուն օգտագործում է պարզ, փակագծերով շարահյուսություն. սիմվոլը ներկայացվում է անունով, թիվը՝ իր արժեքով, իսկ ցուցակը՝ կլոր փակագծերում գրված ատոմների և ցուցակների հաջորդականությամբ։

Ցուցակում կարող են ընդգրկված լինել ցանկացած տիպի էլեմենտներ՝ այդ թվում նաև ցուցակներ։ Օրինակ.

(1 3/7 'foo #'+)

ցուցակը բաղկացած է ամբողջ թվից, կոտորակից, foo սիմվոլից և գումարման ֆունկցիայի վրա ցուցչից։

Արտահայտություններն իրենցից ներկայացնում են պրեֆիքս գրառմամբ ցուցակներ. Առաջին էլեմենտը պետք է լինի ֆունկցիա, օպերատոր կամ մակրոս։

Թվաբանական արտահայտությունները նույնպես գրառվում են այդ սկզբունքով, օրինակ

 (+ 4 (* 2 3))

արտահայտությունը վերադարձնում է 10 ( ինֆիքս գրառումն է 2 * 3 + 4 )։

s_expression ::= atomic_symbol | "(" s_expression "." s_expression ")" | list 
list ::= "(" s_expression { s_expression } ")" 
atomic_symbol ::= letter atom_part 
atom_part ::= empty | letter atom_part | number atom_part 
letter ::= "a" | "b" | " ..." | "z" 
number ::= "1" | "2" | " ..." | "9" 
empty ::= " "

Լիսպով գրված ծրագրի առանձնահատկությունն այն է, որ տվյալները և ցանկացած բարդության կոդ բնութագրվում է վերը նշված պարզ քերականությամբ։

Բազային սիմվոլներ, օպերատորներ և ֆունկցիաներ

[խմբագրել | խմբագրել կոդը]

Լիսպի վերջին իրագործումներն ունեն բազմաթիվ ֆունկցիաներ, մակրոսներ և օպերատորներ։ Այստեղ ներկայացված են նրանք, որոնք կազմում են ցուցակների հետ աշխատելու և լիսպով ֆունկցիոնալ ծրագրեր ստեղծելու հիմնական բազիսը։

Լիսպի ներկառուցված սիմվոլ – հաստատուններ, որոնք ցույց են տալիս տրամաբանական արտահայտության ճշմարիտ կամ կեղծ լինելը համապատասխանաբար։

NIL սիմվոլն ունի ևս մեկ կիրառում – այն նաև կարող է նշանակել դատարկ ցուցակ։

Հետևյալ ֆունկցիան վերադարձնում է իր արգումենտների ցուցակը.

(list 1 3/7 'foo) ==>> (1 3/7 'foo)

(այստեղ, նաև հաջորդ օրինակներում «==>>» նշանակումը ցույց է տալիս որ ձախ մասի հաշվարկի արդյունքում վերադարձվում է աջ մասում գրվածը)։ Եթե արգումենտ չկա, վերադարձվում է դատարկ ցուցակ.

 (list) ; ==>> NIL

Եթե որևէ արգումենտ իրենից ներկայացնում է արտահայտություն, ապա սկզբում հաշվարկվում է դրա արժեքը.

(list 1 2 (list 1 2))  ; ==>> (1 2 (1 2))

Լիսպի ինտերպրետատորը, մուտքում ստանալով ցուցակ կամ սիմվոլ, փորձում է այն հաշվել։ Եթե անհրաժեշտ է, որ ինտերպրետատորը չհաշվարկի արժեք, այլ վերցնի սիմվոլը կամ ցուցակն այնպես, ինչպես կա, պետք է կիրառել QUOTE.

(list 1 2 (quote (list 1 2)))  ; ==>> (1 2 (LIST 1 2))
(quote (list 1 2 (list 1 2))) ; ==>> (LIST 1 2 (LIST 1 2))

QUOTE–ի լրիվ կանչի ձևի փոխարեն կարելի է արտահայտությունից առաջ ուղղակի ապաթարց դնել.

(list 1 2 '(list 1 2))  ; ==>> (1 2 (LIST 1 2))

Այս ֆունկցիան հենց լիսպի ինտերպրետատորն է։ Այն QUOTE֊ի հակադիրն է և հաշվում է իր արգումենտի արժեքը։ Օրինակ.

(eval '(list 1 2 '(list 1 2)))         ; ==>> (1 2 (LIST 1 2))
(eval '(list 1 2 (eval '(list 1 2))))  ; ==>> (1 2 (1 2))

Վերադարձնում է ցուցակի գլուխը՝ առաջին տարրը.

(car '(A B C D))     ; ==>> A
(car '((A B)(C D)))  ; ==>> (A B)

Բացառություն.

 (car NIL) ==>> NIL

Ֆունկցիոնալ ծրագրավորման մեջ դատարկ ցուցակի գագաթի արժեքն անորոշություն է, բայց լիսպում ընդունված է, որ դատարկ ցուցակի և՛ գլուխը, և՛ պոչը հավասար են NIL։

Վերադարձնում է ցուցակի պոչը։ Օրինակ.

(CDR '(A B C D)) ==>> (B C D)
(CDR '((A B)(C D))) ==>> ((C D))
(CDR NIL) ==>> NIL

Այստեղ ?-ի փոխարեն կարող է լինել 2 – ից 4 “A” և “D” տառ՝ ցանկացած կոմբինացիայով։ Այսինքն հնարավոր են CDDDDR, CADAR, CADDR և այլն։ Այդպիսի ֆունկցիայի կանչին համապատասխանում է CAR և CDR ֆունկցիաների ներդրված կանչին, օրինակ (CADAR '((A B C) D E F)) –ին համապատասխանում է

(car (cdr (car '((A B C) D E F))))  ; ==>> վերադարձնում է B–ի արժեքը։

Որպես արգումենտ ընդունում է գլուխ և պոչ և դրանցից կառուցում է ցուցակ կամ կետային զույգ, եթե արգումենտներն ատոմներ են։

(cons 'A '(B C D))      ; ==>> (A B C D) - միացնում է ատոմը ցուցակին
(cons '(A B) '((C D)))  ; ==>> ((A B) (C D)) - միացնում է մի ցուցակը մյուսի գագաթից
(cons 'A 'B)            ; ==>> (A . B) - ստեղծում է կետային զույգ 2 ատոմներից

Պայմանի ընդհանրացված կառուցվածք։ Ունի հետևյալ տեսքը.

(cond ((պայման1) (արտահայտություն1)) ((պայման2) (արտահայտություն2))  )

Հաջորդաբար հաշվարկվում են պայման1, պայման2, և այլն, այնքան, մինչև N – րդ պայմանը ճշմարիտ լինի։ Ապա հաշվարկվում է արտահայտությունN–ը և դրա արժեքը վերադարձվում է որպես cond-ի կանչի արդյունք։ Եթե ճշմարիտ պայման չկա վերադարձվում է NIL։ Սովորաբար որպես երջին պայման կիրառում են T–ն, որն ապահովում է, որ եթե ոչ մի պայման ճշմարիտ չէ, ապա կկատարվի վերջին արտահայտությունը։ Դա համապատասխանում է իմպերատիվ ծրագրավորման լեզուներում ELSE – օպերատորին։

Կառուցվածք է, որը թույլ է տալիս սահմանել ֆունկցիա և ունի հետևյալ ընդհանրացված տեսքը.

(defun անուն (պարամետր1  պարամետր2 ) արտահայտություն  արտահայտություն  )
  • Անուն – ֆունկցիայի անուն։
  • Պարամետր1, և այլն, հաջորդականությունը – ֆունկցիայի ֆորմալ պարամետրեր։

Արտահայտություն1, և այլն, հաջորդականությունը – հաշվարկվող արտահայտություններ, որոնցում կարող են օգտագործվել ֆորմալ պարամետրերը և գլոբալ փոփոխականները։ Ֆունկցիայի կանչի ժամանակ արտահայտությունները հաշվարկվում են հաջորդաբար և որպես ֆունկցիայի վերադարձվող արժեք ծառայում է վերջին արտահայտության հաշվարկից ստացված արդյունքը։

Վիքիպահեստն ունի նյութեր, որոնք վերաբերում են «Լիսպ» հոդվածին։