Լիսպ (Lisp)

| Սեպտեմբեր 14, 2012 | Մեկնաբանված չէ |

Երբ ես սկսում եմ ոգևորված պատմել Lisp-ի մասին, բերելով նրա առավելություններից այս կամ այն օրինակը, լսողների մեջ անպայման գտնվում է մեկը, որ հարցնում է, թե ո՞ւմ է այն պետք, կամ որտե՞ղ է այն օգտագործվում: Իհարկե, Lisp-ը չունի Java-ի կամ C-ի տարածվածությունը  (տես. TIOBE Programming Community Index), բայց Lisp-ը, իմ կարծիքով, ոչ միայն ծրագրավորման լեզու է, այն ոչ միայն գործիք է ծրագրավորողի ձեռքին, այլ նաև այն մտածելակերպ է, փիլիսոփայական նոր մոտեցում: 

Ես չեմ կարծում, որ երբևէ առիթ կունենամ Lisp-ն օգտագործել որևէ կոմերցիոն նախագծում: Բայց Lisp-ի ուսումնասիրության արդյունքում իմ աշխատանքը (C, Java, Tcl, C++, Bash լեզուներով) դարձավ ավելի հասկանալի, ավելի պարզ, ավելի հուսալի: Թերևս հենց սրա համար արժե իմանալ (կամ գոնե ծանոթ լինել) Lisp լեզուն:

Ֆունկցիայի սահմանում – defun

Ֆունկցիաները սահմանվում են defun հատուկ մակրոսի միջոցով: Այն ստանում է սահմանվելիք ֆունկցիայի անունը, պարամետրերի ցուցակը և մարմինը: Մարմինը կարող է բաղկացած լինել մեկ կամ մի քանի արտահայտություններից: Օրինակ, հետևյալ ֆունկցիան մի տողում արտածում է 0-ից n թվերը, իսկ հաջորդ տողում արտածում է այդ նույն թվերի քառակուսիները.

(defun f (n)
  (dotimes (i n)
    (format t "~d " i))
  (terpri)
  (dotimes (i n)
    (format t "~d " (* i i)))
  (terpri))
Ֆունկցիայի անունն է f, արգումենտների ցուցակը պարունակում է միայ n անունը, իսկ ֆունկցիայի մարմինը բաղկացած է չորս արտահայտություններից:
Եթե f ֆունկցիան կանչենք 10 արգումենտով, ապա կստանանք հետևյալ պատկերը.
(f 10)
0 1 2 3 4 5 6 7 8 9 
0 1 4 9 16 25 36 49 64 81 
NIL

Վերջին NIL-ը f ֆունկցիայի վերադարձրած արժեքն է. քանի որ Lisp ֆունկցիաները որպես արժեք վերադարձնում են իրենց մարմնում վերջին հաշվարկված արտահայտության արժեքը, այս դեպքում դա terpri ֆունկցիայի արժեքն է:

Ցուցակներ – list, nth, car, cdr …

Lisp լեզվի ցուցակներկ կառուցվում են list հրամանով, որին հետևում է ցուցակի տարրերի թվարկումը: Օրինակ (list 2 (* 2 2) (+ 2 3)) արտահայտության կատարումը վերադարձնում է (2 4 5) ցուցակը: Ցուցակի տարրերին կարելի է դիմել nth ֆունկցիանի միջոցով, այն ստանում է տարրի համարը և ցուցակը, ապա վերադարձնում է պահանջված տարրը: Օրինակ, (nth 2 ‘(0 1 2 3 4)) արտահայտության արժեքն է 2 թիվը: Ցուցակների հետ աշխատելիս շատ հաճախ է պետք լինում ստանալ ցուցակի առաջին տարրը կամ առաջին տարրին հաջորդող տարրերի ցուցակը: Այդ նպատակին են ծառայում համապատասխանաբար car և cdr ֆունկցիաները: Օրինակ,
(car ‘(a b c d e f))
A
(cdr ‘(a b c d e f))
(B C D E F)

Գրենք մի ֆունկցիա, որ ստանում է թվերից բաղկացած ցուցակ և տպում է ցուցակի տարրերի գումարը:

(defun sumof (x)
  (if (null x)
    0
    (+ (car x) (sumof (cdr x)))))
if-ը մի հատուկ կառուցվածք է, որը կանչի ժամանակ ստանում է երեք արտահայտություն: Եթե առաջին արտահայտության արժեքը տարբեր է nil-ից ապա հաշվարկում և վերադարձնում է երկրորդ արտահայտության արժեքը, կակառակ դեպքում՝ երրորդինը: (if (> 2 1) 'a 'b) արտահայտության արժեքը A է, իսկ (if (not (> 2 1)) 'a 'b) արտահայտությանը՝ B: null պրեդիկատը ստուգում է ցուցակի զրոյական լինելը:
Մեկ այլ օրինակ. կազմենք մի ֆունկցիա, որը տրված n (n>=2) թվի համար կառուցում է Ֆիբոնաչիի առաջին n թվերի ցուցակը:
(defun fib-list (n)
  (if (= n 2)
    (list 1 1)
    (let* ((r (fib-list (1- n))) (m (length r)))
      (append r (list (+ (nth (- m 1) r) (nth (- m 2) r)))))))

let և let* կառուցվածքները ստեղծում են լեքսիկական (լոկալ) կապեր փոփոխականների համար: let-ի դեպքում այդ կապերը ստեղծվում են զուգահեռ, իսկ let*-ի դեպքում՝ ըստ թվարկման հաջորդականության: Բերված օրինակում օգտագործված է let* ձևը, քանի որ m փոփոխականին պետք է կապել r ցուցակի երկարությունը, իսկ let-ի դեպքում դա հնարավոր չէր լինի, որովհետև r և m անունները պետք է արժեք ստանային զուգահեռաբար:

append ֆունկցիան իր արգումենտում թվարկված ցուցակներից կառուցում է նոր ցուցակ՝ դրանք կցելով իրար:

Ֆայլեր – open, with-open-file …

ֆայլային հոսք ստեղծելու համար Lisp-ում նախատեսված է open ֆունկցիան, որ բացում է տրված անունով ֆայլը և վերադարձնում է նրա հետ կապված ֆայլային օբյեկտը: Օրինակ, հետևյալ ֆունկցիան ստեղծում է մի ֆայլ, որի ամեն մի տողում գրված է “Line i of text” (0 <= i < 10):

(defun text-file ()
  (let ((fout (open "abcd.txt" :direction :output)))
    (dotimes (i 10)
      (format fout "Line ~d of text~%" i))))
Նույն այդ ֆայլի պարունակությունը կարդալու և տերմինալին արտածելու համար արդեն ֆայլը պետք է բացել կարդալու համար՝ (open “abcd.txt” :direction :input):

Շարունակելի…

ՍկզբնԱղբյուր

Լիսպ (Lisp), 10.0 out of 10 based on 2 ratings

Նշագրեր: ,

Բաժին: Lisp և Common Lisp

Կիսվել , տարածել , պահպանել

VN:F [1.9.20_1166]
Rating: 10.0/10 (2 votes cast)

Մեկնաբանեք

Կհաստատվեն միայն մեսրոպատառ հայերենով գրած մեկնաբանությունները

188