Երբ ես սկսում եմ ոգևորված պատմել Lisp-ի մասին, բերելով նրա առավելություններից այս կամ այն օրինակը, լսողների մեջ անպայման գտնվում է մեկը, որ հարցնում է, թե ո՞ւմ է այն պետք, կամ որտե՞ղ է այն օգտագործվում: Իհարկե, Lisp-ը չունի Java-ի կամ C-ի տարածվածությունը (տես. TIOBE Programming Community Index), բայց 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 10)0 1 2 3 4 5 6 7 8 90 1 4 9 16 25 36 49 64 81NIL
Վերջին NIL-ը f ֆունկցիայի վերադարձրած արժեքն է. քանի որ Lisp ֆունկցիաները որպես արժեք վերադարձնում են իրենց մարմնում վերջին հաշվարկված արտահայտության արժեքը, այս դեպքում դա terpri ֆունկցիայի արժեքն է:
Ցուցակներ – list, nth, 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 պրեդիկատը ստուգում է ցուցակի զրոյական լինելը:
(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 անունները պետք է արժեք ստանային զուգահեռաբար:
Ֆայլեր – 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))))
Շարունակելի…
Comments: no replies