Зворотний зв'язок

Функції виводу

Функції виводу передають результат в поточний поток виводу (COS - Current Output Stream).

1. (PRIN1 obj). Передає символьне представлення об’єкту в COS і повертає об’єкт. Функція друкує символи використовуючи їх P-імена. Друк відбувається згідно з поточною системою числення. Змінна *PRINT-POINT* контролює максимальну кількість десяткових цифр для зображення на екрані дисплею.

2. (PRINC obj). Працює як і PRIN1, але P-імена виводяться з контрольними символами. Значення контрольної змінної *PRINT-ESCAPE* при виклику PRINC стає рівним T.

(DEFUN PRINC (obj *PRINT-ESCAPE*)

(SETQ *PRINT-ESCAPE* T)

(PRIN1 obj) )

3. (WRITE-BYTE n). Якщо n — ціле число від 0 до 255, то функція виводить в COS символ, ASCII-код якого дорівнює n, і повертає n.

4. (TERPRI n). Якщо n — невід’ємне ціле число, то в COS передається n символів ASCII нового рядка. Якщо функція викликана без аргументів, n вважається рівним 1. Сама функція повертає NIL.

(DEFUN TERPRI (n)

((AND (INTEGERP n) (>= n 0))

(LOOP

((ZEROP n) NIL)

(WRITE-BYTE 13)

(WRITE-BYTE 10)

(DECQ n) ) )

5. (PRINT obj) Для виводу виразів можна використовувати функцію PRINT. Вона має один аргумент. При виклику цей аргумент обчислюється, а потім виводиться його значення. Перед виводом аргумента відбувається перехід на новий рядок, а після виводу аргумента друкується проміжок. Значенням функції є значення аргумента. Побочним ефектом функції PRINT є друк повертаємого знчення. Функцію PRINT можна визначити так:

(DEFUN PRINT (x)

(TERPRI) (PRIN1 x) (PRINC “ “) )

6. (SPACES n). Передає n порожніх ASCII - символів (проміжків) в COS. Повертає кількість переданих символів після того як буде переданий останній новий рядок.

7. (FRESH-LINE). Якщо ми знаходимося на початку рядка, функція просто повертає NIL. Інакше вона передає в COS новий рядок і повертає Т.

8. (WRITE-STRING символ), (WRITE-LINE символ). В COS виводиться P-ім’я символа. Якщо аргумент не є символом, обидві функції повертають NIL. Функція WRITE-LINE після виводу символа в COS автоматично виконує перехід на новий рядок командою (TERPRI).

9. (SET-CURSOR рядок колонка). Текстовий режим для Ліспа має розмір 80*25. Ця функція встановлює курсор у відповідну позицію.

10. (ROW), (COLUMN). Відповідно повертають поточний рядок (стовпчик) поточного положення курсора.

11. (CLEAR-SCREEN). Стирає екран, встановлює курсор в (0, 0) та повертає T.

4.5. Обчислювані функції

Обчислення виразів та звернення до функцій відбувається автоматично інтерпретатором muLisp. Обчислювані функції необхідні в тих випадках коли необхідно безпосередньо обчислити вираз або звернутися до функцій. Визначенням функції є список, який складається з трьох частин: імені типу функції, формальних параметрів та тіла функції.

CAR-елементом визначення функції є ім’я типу фукції — LAMBDA, NLAMBDA чи MACRO. Тип функції дає інтерпретаторові інформацію про те, як використовувати дану функцію.

Визначення функцій та їх обчислення в Ліспі основано на лямбда-численні Чорча. Лямбда вираз, який взято з лямбда числення, є важливим механізмом у програмуванні. В лямбда численні Чорча функція записується у вигляді:

lambda (x1, x2, ..., xn) . f

В Ліспі лямбда вираз має вигляд:

(LAMBDA (x1 x2 ... xn) f)

Символ LAMBDA говорить нам про визначення функції. Символи xi – це формальні параметри, f – тіло функції. Тілом функції може бути довільна форма, значення якої може обчислити інтерпретатор Ліспа. Функцію, яка обчислює суму квадратів двох чисел, можна визначити так:

(LAMBDA (x y) (+ (* x x) (* y y)) )

Формальність параметрів вказує на те, що ми можемо замінити їх на інші символи, але від цього не зміниться сутність обчислення функції.

Лямбда вираз – це визначення обчислення та параметрів функції в чистому вигляді без фактичних параметрів або аргументів. Для застосування такої функції до певних аргументів, необхідно поставити лямбда вираз на місце імені функції:

(лямбда-вираз a1 a2 ... an)

Тут ai – форми, що задають фактичні параметри.

Наприклад, множення (* 3 4) можна записати з використанням лямбда виклику:

$ ((LAMBDA (x y) (* x y)) 3 4)

12

Наступний виклик будує список з двох аргументів:

$ ((LAMBDA (x y) (CONS x (CONS y NIL))) ‘dog ‘cat)

(dog cat)

Таку форму виклику називають лямбда викликом. Обчислення лямбда виклику відбувається в два етапи. Спочатку обчислюються значення фактичних параметрів та відповідні формальні параметри зв’язуються з отриманими значеннями. На другому етапі обчислюється форма, яка є тілом лямбда виразу. Отримане значення повертається в якості значення лямбда виклику. По завершенню обчислення формальним параметрам повертаються зв’язки , які існували до лямбда виклику. Весь цей процес називається лямбда перетворенням.Пам’ятайте, що лямбда вираз без фактичних параметрів є лише визначення, а не форма, яку можна обчислити. Сам по собі лямбда вираз інтерпретатором не сприймається. Якщо ви введете: (LAMBDA (x y) (CONS x (CONS y NIL))), то інтерпретатор Ліспу видасть повідомлення про помилку.

Лямбда вираз є як чисто абстрактним механізмом для визначення та опису обчислення, так і механізмом для зв’язування формальних та фактичних параметрів під час виконання обчислення. Лямбда вираз є функцією без імені.

Ми вже говорили про те, як визначити нову функцію – це можна здійснити за допомогою функції DEFUN. Визначення функції викликається так:

(DEFUN <і’мя> <лямбда вираз>)

Для спрощення опустимо зовнішні дужки у лямбда виразі та сам атом LAMBDA. Тоді ми отримаємо знайоме нам визначення функції. Наступні визначення еквівалентні:

(DEFUN list2 (LAMBDA (x y) (CONS x (CONS y NIL))))

та

(DEFUN list2 (x y) (CONS x (CONS y NIL)))

Функція DEFUN з‘єднує символ з лямбда виразом, після чого символ починає іменувати обчислення, яке визначається лямбда виразом. Значенням функції DEFUN є ім’я нової функції.

За допомогою структури LET, яка визначена в common.lsp, можна утворити локальний звя’зок. Значення змінним форми LET присвоюються одночасно. Ця структура має наступний вигляд:

(LET ((m1 a1) (m2 a2) ... (mN aN)) <форма1> <форма2> ... <формаN>),

яка в дійсності є лямбда викликом, де формальні та фактичні параметри знаходяться разом на початку структури:

((LAMBDA (m1 m2 ... mN) <форма1> <форма2> ... <формаN>) a1 a2 ... aN)

Наступні виклики еквівалентні:

$ (LET ((x 4)(y 2))(+ x y))$ ((LAMBDA (x y) (+ x y)) 4 2)

66

Функція типу NLAMBDA називається необчислюваною. Якщо викликається необчислювана функція, то їй аргументи передаються без обчислення — так, як вони стоять в рядку виклику. Пояснимо це на прикладі. Визначимо дві функції f1 та f2, які на перший погляд однакові:

(DEFUN f1 (LAMBDA (x y)(DEFUN f2 (NLAMBDA (x y)

(+ x y)) )(+ x y)) )

Якщо викликати (f1 5 6) або (f2 5 6), то результат буде однаковим – 11.

Нехай змінним k та l присвоєні деякі значення: (SETQ k 5 l 6). Тоді

$ (f1 k l)$ (f2 k l)

11 помилка: (+ k l) / а не (+ 5 6), оскільки передані

аргументи не обчислені /

Функція типу MACRO називається макро-функцією. Макроси є потужним робочим інструментом програмування. Синтаксис визначення макроса виглядає таким же чином як синтаксис визначення функції форми DEFUN:

(DEFMACRO <ім’я> <лямбда список> <тіло>)

Виклик макроса співпадає за формою з викликом функцї, але його обчислення відрізняється від обчислення виклику функції. В макросі не обчислюються аргументи. Обчислення виклику макроса складається з двох послідовних етапів. Спочатку відбувається обчислення тіла з аргументами (як і для функції). Цей етап називається розширенням або розкриттям макроса. На другому етапі обчислюється розкрита форма, значення якої повертається в якості значення всього макровиклику. Визначимо макрос PUSH1, який працює як відома нам функція PUSH (в дійсності PUSH є вмонтованим в середовище Лісп макросом).

$ (DEFMACRO PUSH1 (x y)$ (SETQ ‘a ‘(1 2 3)) (PUSH1 6 ‘a)

(LIST 'SETQ y (LIST 'CONS x y)))після чого a = (6 1 2 3)

Визначимо деяку функцію P, тілом якої є макрос PUSH1:

(DEFUN p (x y)

(PUSH1 x y))

Тепер за допомогою команди (GETD p) можна побачити, який вигляд має функця p:

$ (GETD p)

(LAMBDA (X Y) (SETQ Y (CONS X Y)))

При програмуванні розкритого макроса явно не видно, тому для їх тестування існує спеціальна функція – MACROEXPAND, яка здійснює тільки розкриття макроса. Повертається макророзширення виклику, яке можна вивчати.

$ (MACROEXPAND '(PUSH1 6 s))

(SETQ S (CONS 6 S))

CADR-елементом визначення функції є або список формальних аргументів, або ім’я формального аргументу. Функція, яка визначена за допомогою списку формальних аргументів, в тому числі і порожнього, називається розгорнутою. При виклику такої функції фактичні аргументи прив’язуються відповідно до формальних аргументів.

Функція, яка визначена за допомогою імені формального аргумента, називається нерозгорнутою. Якщо викликається така функція, список фактичних аргументів пов’язується з іменем формального аргумента. Отже нерозгорнуті функції допускають будь-які імена фактичних аргументів.

CDDR-елементом визначення функції є список форм, який називається тілом функції. Після того як формальні аргументи функції були прив’язані з її фактичними, починає працювати неявна функція PROGN, яка обчислює тіло функції. Після обчислення тіла функції формальні аргументи знову приймають свої вихідні значення, а результат обчислення тіла функції видається як значення функції.

1. FUNCALL (<функція> ... )Виконуються дії функції <функція> над аргументами та повертається результат. <Функція> повинна бути або іменем обчислюваної функції, або тілом LAMBDA. Якщо <функція> — це ім’я макро або невизначеної функції, виникає переривання по помилці <невизначена функція>.

$ (FUNCALL ‘CONS ‘a ‘(b c d))

(a b c d)

$ (FUNCALL ‘(LAMBDA (n) (* n n)) 5)

25

2. EVAL <об’єкт>

Інтерпретатор Ліспа називається EVAL, його можна як і інші функції викликати з програми. У звичайній роботі інтерпретатор викликати не має потреби, оскільки його виклик має місце неявно. Зайвий виклик інтерпретатора може зняти ефект блокування (QUOTE), або дозволить знайти значення виразу. EVAL – це універсальна функція Ліспа, яка може обчислити довільний правильно побудований лісповський вираз.

Якщо об’єкт — атом, функція повертає зміст комірки значення об’єкту.

Якщо CAR-елемент об’єкта є іменем обчислюваної функції або LAMBDA, функція обчислює кожний елемент CDR-частини об’єкта і додає CAR-елемент об’єкта до списку результатів.

Якщо CAR-елемент об’єкта є іменем необчислюваної функції, EVAL додає CAR-елемент об’єкта до CDR-елемента об’єкта без обчислення останнього.

Якщо CAR-елемент об’єкта є макрофункцією, EVAL рекурсивно обчислює результат додавання CAR-елемента об’єкта до його CDR-елемента.

Якщо CAR-елемент об’єкта не є функцією, EVAL повертає помилку “невизначена функція” та генерує переривання по помилці.

$ (SETQ a ‘b b ‘c)$ (EVAL ‘(CONS ‘A ‘(B C)))

$ (EVAL a)(A B C)

c

$ (EVAL ‘(PRIN1 ‘(a b c)))

(a b c) (a b c)

$ (DEFUN a (n)$ (EVAL ‘(a 3))

(+ n 2) )5

$ (EVAL (LAMBDA (n) (* n n)) 7)

49

Діалог з інтерпретатором Ліспа на верхньому (командному) рівні можна описати простим циклом:

(SETQ e (READ))введення виразу

(SETQ v (EVAL e))обчислення виразу

(PRINT v)друк результата

При виконанні тіла необчислювальної функції ми можемо використати функцію EVAL для обчислення аргументів.

(DEFUIN f3 (NLAMBDA (x y)(SETQ k 5 l 6)(f3 k l)

(+ (EVAL x) (EVAL y))) )11

3. CONSTANTP <об’єкт>

Об’єкт є константою тоді і тільки тоді, коли (EVAL <об’єкт>) повертає <об’єкт>. Символ NIL, числа та списки, в яких CAR-елемент є символ QUOTE, в muLisp є константами. Якщо <об’єкт> — константа, функція CONSTANTP повертає Т, інакше — NIL.

(DEFUN CONSTANTP (obj)

((NULL obj))

((NUMBERP obj))

((ATOM obj) NIL)

(EQ (CAR obj) ‘QUOTE) )

$ (CONSTANTP ())$ (CONSTANTP 23.543)

T T

$ (CONSTANTP ‘v)$ (CONSTANTP ‘(a b c))

NILNIL

$ (CONSTANTP ‘(QUOTE (a b c)))

T

4. APPLY <функція> <арг1> <арг2> ... <арг-список>

Застосовує функцію до списку аргументів. (APPLY f x1 x2 ... xN) еквівалентно (f x1 x2 ... xN). Використання функції APPLY є більщ гнучким у порівнянні з прямим викликом функції. Діє як і функція FUNCALL, тільки аргументи функції приймає не окремо, а списком.

Якщо функція — ім’я визначеної користувачем функції або тіло LAMBDA, APPLY пов’язує формальні аргументи функції з фактичними аргументами, обчислює тіло функції, відтворює вихідні значення формальних аргументів і повертає значення обчислення тіла функції.

Якщо функція — не ім’я функції і не тіло LAMBDA, APPLY генерує переривання по помилці “невизначена функція”.

$ (APPLY ‘CONS ‘(a (b c d)))$ (SETQ z ‘(LAMBDA (n) (* n n)))

(a b c d)$ (APPLY z ‘(4))

16

5. UNDEFINED <символ> <форма1> ... <формаN>

Ця функція ініціює преривання по помилці “Невизначена функція”. Ця функція керування помилками використовується тоді, коли намагаються обчислити форму, CAR-елемент якої є символом, який не має визначення функції.


Реферати!

У нас ви зможете знайти і ознайомитися з рефератами на будь-яку тему.







Не знайшли потрібний реферат ?

Замовте написання реферату на потрібну Вам тему

Замовити реферат