ПАРАДИГМА ФУНКЦІОНАЛЬНОГО ПРОГРАМУВАННЯ 3 страница
г) 3/5 – тип ratio, звичайний дріб.
д) 279 – тип integer.
е) 16777215 – fixnum, максимальне ціле.
є) -16777216 – fixnum, мінімальне ціле.
ж) 16777216111222333 – тип bignum, ціле більше ніж fixnum.
з) #\P – pyfr H? nbg character/
и) “lisp” – тип рядок.
і) (2 3 4 5)- тип список.
ї) ‘(A . N) - тип cons.
к) #(2 4 3 1) - тип vector.
л) #*101 - тип bit-vector.
м) #S(student :fam Petrenko : Микола) - структура
У Common Lisp прості типи даних (simple) не подаються об’єктами.
Для подавання змінних та імен інших об’єктів(ідентифікаторів) застосовують тип символ. Символ має зовнішнє і внутрішнє подавання.
Зовнішнє подавання – це набір будь-яких знаків (латинських та кириличних букв, цифр, спеціальних знаків без обмежень). Довжина зовнішнього подавання практично необмежена.
Для застосування цифри або спеціального знаку в Print-імені, щоб відрізнити їх від макрознаків чи чисел застосовують перед одиночним таким символом „\”. Наприклад, подамо символ цифрами \53.
CL-USER> (setq \53 25)
CL-USER> \53
Якщо Print- ім’я повинно містити декілька спеціальних знаків, то зручно його обмежувати парними знаками “|”.
CL-USER> (Setq | | 14e-1)
1.4
У прикладі символ містить 3 пропуски.
При вводі програми символи, що необмежені розділовими знаками автоматично переводяться у верхній регістр.
Наприклад:
CL-USER> (setq n 12.3)
12.3
CL-USER>N
12.3
Одержати ім’я символу можна функцією SYMBOL-NAME:
CL-USER> (symbol-name 'R)
“R"
Мову LISP розробили для спілкування експертної системи з користувачем природною мовою та створення бази знань на основі мови.
Мова повинна була дозволяти будувати інформаційні одиниці знань будь-якої складної структури та легко оброблювати їх. Причому, структура даних невідома була попередньо і тому описати її було неможливо. Звідси виникла властивість мови автоматичного створення символів у середовищі при завантаженні програми або під час роботи програми.
Щоб утворити у середовищі символ достатньо просто завантажити програму з файлу на вхід інтерпретатору і відкомпілювати її або ввести вираз з клавіатури. У середовищі символ буде створено автоматично, якщо його не було. Для будь-якого символу створюється рядок – Print – ім’я символу.
Мова Common Lisp дозволяє генерувати унікальний символ під час роботи програми. Для цього застосовується функція Gentemp.
CL-USER> (Gentemp “N”)
|N2|
CL-USER> (Gentemp “N”)
|N3|
У середовищі Common Lisp символ – це об’єкт, що розпізнається і складається з 4-х покажчиків.
Рисунок 5.2 – Внутрішнє подавання символу
Якщо символ ім’я змінної, то перший покажчик вказує на значення змінної. Другий покажчик вказує на список властивостей символу. Третій застосовується, якщо символ ім’я функції, він вказує на код функції. Четвертий покажчик вказує на зовнішнє подавання символу: Print-ім’я.
Перевірити, чи є об’єкт символом, можна функцією Symbolp.
Наприклад:
CL-USER> (Symbolp ‘a)
T
CL-USER> (Symbolp “a”)
NIL
Можливості мови Лісп ідеально пристосовано до роботи із знаннями. Знання подаються в поняттях. Поняття - зміст слова. Слово – ідентифікатор поняття.
Кожне поняття – передається групою тверджень. Кожне твердження вказує на певні властивості об’єкту, який відповідає слову.
У середовищі слово подається символом, а для вказівки змісту слова існують властивості символу. Властивості символу подаються списком, а символ містить покажчик на цей список.
Внутрішнє подавання символів дозволяє краще розуміти роботу функцій з ними.
Символи можуть об’єднуватися у пакети. Пакети дозволяють мати у середовищі символи з однаковими іменами, що застосовуються різними програмами, кожен зі своїм значенням. З іншого боку ці символи не локальні, можуть застосовуватись всіма функціями однієї програми.
З пакетами зручно працювати, якщо користувач бажає застосовувати певні бібліотеки. У програмі користувача і у бібліотеці можуть бути робочі символи з однаковими іменами. Щоб уникнути помилок символи бібліотеки і символи програми користувача розміщують у іменовані пакети. Для спілкування з бібліотекою частина її символів повинна бути доступною користувачу такі символи називають зовнішніми.
Пакет може наслідувати символи іншого пакету; експортувати свої символи в інший пакет та імпортувати символи у свій пакет.
Утворити пакет можна функцією MAKE-PACKAGE.
(make-package “Ім’я символу” :nicknames cgbcjr1 :use cgbcjr2)
Наприклад:
CL USER>(make-package "B" :nicknames '("b"))
#<package b>
CL USER>(make-package “A” :nicknames ‘(“a”) :use ‘(“b” “c”))
#<package a>
Опція :nicknames дозволяє давати скорочені імена пакетам, або зменшувати можливість помилок. Опція :use вказує на список імен пакетів, зовнішні символи яких доступні цьому пакету.
Символ інтернують у пакет функцією INTERN:
(INTERN "рядок" 'ім’я пакету)
CL USER>(INTERN "s" 'A)
A::|s|
NIL
Працювати з символом інтернованим у пакет можна за складним ім’ям <Ім’я пакету::символ>.
CL USER>(setq A::|s| 5/9)
5/9
Функцію INTERN можна застосовувати для створення за рядком символу.
Середовище містить 3 стандартних пакети: Common-Lisp, Common-Lisp-User, Keyword. При вході в Common-Lisp поточним пакетом є пакет Common-Lisp-User.
Пакет Common-Lisp-User застосовує символи пакету Common-Lisp. Користувачу недозволено інтернувати символи у пакет Common-Lisp. Пакет Common-Lisp-User є робочим пакетом. Користувач може інтернувати символи в цей пакет через інтерпретатор. Стандартні символи наслідуються всіма пакетами.
Пакет Keyword дозволяє обмежити ключові слова, відкинути суперечливі ситуації у різних реалізаціях Common-Lisp.
5.2.2 Базові типи даних
Базовими типами є атом і список.
АТОМИ
Атомами називають прості типи даних. З атомів будуються інші типи даних. До атомів відносяться символи, знаки, числа, логічні константи T і NIL.
Типи даних, що є підтипами вказаних типів також є атомами. Наприклад, потік є символом і тому теж атом.
Перевірити, чи є об’єкт атомом, можна функцією ATOM:
CL-USER> (ATOM 26)
T
ЛОГІЧНІ КОНСТАНТИ
Логічна константа Т служить для подавання значення «істина». Логічна константа NIL використовується в мові Лісп для подавання значення «лжа» і для подавання порожнього списку ( ).
У мові LISP всі значення, що не NIL вважаються істинними.
Нижче, подається приклад, що ілюструє твердження.
CL-USER> (NULL (Setq P 34 ) )
NIL
Функція NULL перевіряє істинність свого аргументу. Якщо аргумент не істинний, то функція повертає Т, інакше NIL:
Функція Setq повертає 34, число вважається істинним значенням. Число 34 аргумент функції NULL, тому функція повертає NIL.
Вказаний підхід дозволяє використовувати результат будь-якої функції, константу, значення змінної, як умову.
CL-USER> (IF (NULL (Setq P 34 ) ) (PRINT “Істина”) )
NIL
Перший раз слово друкує функція PRINT. Другий раз слово повертає функція IF, як останню виконану дію.
КОНСИ
Тип даного конс має наступне зовнішнє подавання:
(елемент1 . елемент2).
Конс складається з пари елементів, що пов’язані точкою і розміщені у круглих дужках. Щоб відрізняти конс від дійсного числа, коли елементи числа, між елементами пари і точкою ставляться пропуски.
Наприклад,
CL-USER> (setq K ‘(3 . 4))
(3 . 4)
Основний принцип мови Лісп: „Всі виразу автоматично обчислюються, якщо обчислення не заперечене”.
Заперечити обчислення можна функцією QUOTE(‘).
Якщо не заперечити обчислення консу у прикладі, то інтерпретатор буде шукати функцію з ім’ям 3, бо у дужках подаються виклики функцій.
У середовищі конс – об’єкт, що розпізнається. Він має два покажчики, які вказують на елементи консу:
Рисунок 5.3-Внутрішнє подавання консу
Перевірити, чи є об’єкт консом, можна функцією CONSP:
CL-USER> (CONSP ‘(X . 30) )
T
Конс створюється функцією Cons:
CL-USER> (CONS ‘X 30)
(X . 30)
Перший елемент консу прийнято називати CAR – елементом, а другий елемент називають CDR – елементом за іменами базових функцій Ліспу, що працюють з елементами консу.
Функції CAR і CDR вибирають лівий і правий елементи консу відповідно.
CL-USER> (CAR ‘(X . 30))
X
CL-USER> (CDR ‘(X . 30))
СПИСКИ
Зовнішнє подавання списку ми вже розглядали у розділі „Принципи побудови та функціонування мови LISP”.
У середовищі список – це об’єкт, що розпізнається, і будується на основі консів. Car-елемент кожного консу списку вказує на елемент списку. Cdr - елемент консу вказує на наступний конс. У останньому консу правий елемент має значення NIL, тобто покажчик відсутній.
Розглянемо, як у середовищі з консів подається список.
Рисунок 5.4-Внутрішнє подавання списку
Функції CAR і CDR працюють із першим консом списку. Застосовуючи знання про роботу функцій CAR і CDR з консами, можна зрозуміти, що повертають функції при роботі із списками.
CL-USER> (CAR ‘(1 2 3) )
CL-USER> (CDR ‘(1 2 3) )
(2 3)
Зверніть увагу, що у першого конса правий покажчик вказує на другий конс, а він пов’язаний з третім консом і. т. д. до кінця списку. Таким чином, функція CDR бере хвіст списку (список без першого елементу).
Запис списку можна трактувати, як запис із консів, тобто бінарним деревом: (1 2 3) (1 . (2 . (3 . NIL) ) ).
Внутрішнє подавання консів і списків допомагає краще розуміти роботу з ними функцій. Конс тотожній списку з одним елементом.
Запис списку із консів можна подати графічно у вигляді бінарного дерева. Розглянемо подавання списку (1 2 3) консами.
Рисунок 5.5-Графічне подавання списку консами
5.2.3 Поняття S - виразу
Для узагальнення типів даних вводиться тип S - вираз. Атоми і списки є базовими типами для всіх типів даних.
Тому кажуть, що S - вираз є узагальненням типів атом і список.
Дамо конструктивне означення S - виразу. Під конструктивним означенням розуміють процес одержання об’єкту.
Надамо лічильнику дужок значення 0. Будемо називати об’єкт S - виразом, якщо для кожної відкритої круглої дужки до вмісту лічильника буде добавлятися 1. А для кожної закритої круглої дужки із лічильника буде відніматися 1. І при цьому, всередині виразу значення буде весь час більше 0, а в кінці виразу значення лічильник дорівнює нулю.
Під це означення підходить атом і список. У атома немає дужок і тому лічильник дорівнює 0. У списку парні дужки.
Розглянемо приклад вірного S – виразу:
(* (+ a b) (- c d))
Значення лічильника: 0,1,2,1,2,1,0.
Для невірного S- виразу (* (+ a b) (- c d)
Значення лічильника: 0,1,2,1,2,1.
Якщо інтерпретатор, зустрічає такий вираз, то чекає вводу закритої дужки.
5.3 Інтерпретатор Common Lisp
5.3.1 Процесори інтерпретатора Common Lisp
На вхід інтерпретатору подаються вирази.
Інтерпретатор Common Lisp має два процесора мови:
- процедуру читання;
- процедуру обчислення.
Процедура читання має лексичний аналізатор і синтаксичний аналізатор.
Лексичний аналізатор процедури читання: читає потік знаків, виділяє в ньому S – вираз, будує об’єкт, що відповідає S - виразу і передає синтаксичному аналізатору.
Синтаксичний аналізатор процедури читання:будує з S - виразів синтаксичні дерева і передає їх синтаксичному аналізатору процедури обчислення.
Синтаксичний аналізатор процедури обчислення: розглядає синтаксичні дерева і виявляє в них форми Ліспу. Під формами у Common Lisp розуміють вирази, що можуть обчислюватися.
Процедура обчислення, одержує форму, генерує її код, ініціює його виконання і повертає результат.
Кажуть, що інтерпретатор працює у циклі(LOOP), виконуючи тріаду READ-EVAL-PRINT. Меню роботи з інтерпретатором COMMON LISP називають REPL за першими буквами функцій.
5.3.2 Обчислення форм інтерпретатором
Форми COMMON LISP розподіляють на дві групи символи і інші форми.
Символ, який обчислюється, розуміється інтерпретатором як змінна. Після обчислення символу повертається його значення.
CL-USER> (setq R 199)
Привласнюється змінній R 199.
CL-USER> (setq М R)
Обчислюється значення R і привласнюється змінній М.
CL-USER> R
CL-USER> M
Обчислюються також іменовані константи. До таких констант відносять PI. По замовчанню для типу LONG-FLOAT виводиться 19 цифр після точки.
CL-USER> PI
3.1415926535897932385L0
Кажуть, що константи обчислюються самі. Інтерпретатор повертає те значення, що введено.
CL-USER> “asd”
“asd”
Якщо символ, що подає змінну, заборонено обчислювати, то змінній привласнюється ім’я символу. Таке привласнювання називають автоматичним посиланням.
CL-USER> ‘a
A
При вводі символу всі знаки символу, якщо вони не обмежені розділовими знаками, переводяться у верхній регістр.
CL-USER> '\a
|a|
CL-USER> '|a|
|a|
Символи, які є ключами, і імена яких починаються з “:”, інтерпретатор оброблює автоматично процедурою читання. Процедура знаходить відповідні їм іменовані константи і повертає імена цих констант.
Якщо на вхід інтерпретатора подається список, і обчислення його елементів заборонено, то список дане.
CL-USER> ‘(+ 2 3)
(+ 2 3)
На вхід інтерпретатору може подаватися список, який є викликом функції, спец. форми, макросу. Процедура обчислення виявляє чи є перший елемент списку ім’ям функції. Обчислення виклику функції починається з обчислення фактичних параметрів. Обчислення параметрів виконується зліва направо. Результати обчислення передаються функції. Кожен аргумент повинен бути формою.
CL-USER> (* (CAR ‘(5 2 7) ) 10)
При компіляції функції може виникнути ситуація, коли функція містить виклик іншої функції, яка ще не існує. Тоді по замовчанню перший елемент виклику приймається ім’ям функції.
На вхід інтерпретатору може подаватися список, який є викликом спеціальної форми. Виклик спеціальної форми неможливо подати, як виклик функції.
Покажемо на прикладі обчислення спеціальної форми:
(IF X (PRINT “Plus”) (PRINT “Minus”) ).
Якщо обчислювати IF, як функцію, то спочатку буде обчислене значення змінної Х. Потім виведеться Plus і Minus. Після чого почне виконуватись функція, що вже непотрібно.
Спеціальні форми не обчислюють свої аргументи і використовують свої аргументи по різному. Компіляція спеціальної форми виконується спеціальною формою DEFMACRO.
Розглянемо приклади спеціальних форм:
CL-USER> (setq X -4)
-4
CL-USER> (IF ( Plusp X) (PRINC “Plus”) (PRINC “Minus”) )
Minus
“Minus”
Функція PRINC виводить рядок без лапок.
У COMMON LISP існує 25 спеціальних форм. Більшість з них застосовується у інших конструкціях і сховані від користувача у цих конструкціях. Спеціальні форми обмежені синтаксисом стандарту.
Розширити стандарт можна макросами. Процедура обчислення виявляє чим є перший елемент списку ім’ям макросу(макрокоманди). Макрос викликає макровизначення. Макровизначення виконується в два етапи. Спочатку фактичні параметри без обчислення передаються в макровизначення і формується макророзширення в операціях нижнього рівня, що підставляється на місце макровизначення. Потім макророзширення обчислюється.
Наприклад:
CL-USER> (setf A 25)
Макрос оцінює місце змінної Х і заносить у вічко пам’яті , що відповідає їй число 25.
Компіляція макровизначення виконується спеціальною формою DEFMACRO.
На вхід інтерпретатору може подаватися список, який є означенням функції (спеціальною формою, макровизначенням) користувача. Процедура обчислення виявляє чим є перший елемент списку ім’ям функції компіляції. Компіляція функції виконується спеціальною формою DEFUN. Якщо компіляція функції виконана вірно, то інтерпретатор повертає ім’я функції.
Наприклад:
CL-USER> (defun sum (Y) (* (CAR Y) (+ (CAR Y) 1) ) )
SUM
ТЕМА 6: БАЗОВІ ФУНКЦІЇ
6.1 Формальні та фактичні параметри
6.1.1 Обов’язкові параметри
Звичайно визначення функції може мати певне число формальних параметрів. Виклик функції повинен мати стільки ж фактичних параметрів, інакше видається повідомлення про помилку. Такий тип параметрів називають обов’язковими параметрами. У поданому нижче визначенні функції обов’язковими формальними параметрами являються: a b c.
CL-USER> (defun L ( a b c) (List a b c))
L
CL-USER>(L 2 4 6)
(2 4 6)
6.1.2 Необов’язкові ключові параметри
Функція може мати необов’язкові параметри, які застосовуються тільки при певних умовах. У визначенні функції такі формальні параметри розміщуються після обов’язкових формальних параметрів і починаються з ключа–параметра &Optional.
При виклику функції спочатку пов’язуються обов’язкові формальні і фактичні параметри, потім пов’язуються необов’язкові параметри і якщо необов’язкових формальних параметрів більше ніж фактичних, то їм привласнюється NIL.
Розглянемо приклад. Нехай потрібно із введено списку чисел зробити новий список без нулів.
При виклику такої функції треба вказати вихідний список і порожній список, в який будуть перенесені всі числа крім нулів. Вказуючи необов’язковий формальний параметр для нового списку, ми можемо не задавати відповідний йому фактичний параметр. Така функція вимагає роботи з циклами, яку ми розглянемо пізніше. Тому ми напишемо лише початок функції, щоб показати як застосовується необов’язковий параметр.
(defun sp (L1 &optional L2)(print L2))
SP
CL-USER> (sp '(2 4 6))
NIL
NIL
Перша константа NIL виводить значення змінної L2. Print спочатку виводить BK, ПС, після виводу NIL пропуск.
6.1.3 Іменовані ключові параметри
Функція може мати змінну кількість аргументів, але не більше вказаної у формальних параметрах. Для цього на початку формальних параметрів розміщують ключ-параметр &key. У виклику функції вказують тільки необхідні параметри. Формальним параметрам, що не мають значення по замовчанню привласнюється NIL.
Приклад 1:
(defun L (&key a b c) (List a b c))
L
CL-USER> (L)
(NIL NIL NIL)
CL-USER> (L :a 5 :b 6 :c 7)
(5 6 7)
CL-USER> (L :с 5 :a 7)
(7 NIL 5)
CL-USER> (L :a 5 )
(5 NIL NIL)
CL-USER> (L :b 5 )
( NIL 5 NIL)
Параметри не є позиційними, їх можна задавати не в тому порядку, як вони записані у формальних параметрах. Такий вид параметрів називають іменованими параметрами.
У функції можна подавати замовчення для значень формальних параметрів. Для цього формальні параметри подають у дужках разом із значенням по замовчанню.
Приклад 2:
(defun L (&key (a 10) (b 20) (c 30 )) (list a b c ))
L
CL-USER> (L)
(10 20 30)
Часто треба задати значенням фактичного параметру NIL. Щоб розрізняти NIL по замовчанню і фактичний параметр NIL, для формального параметра вводиться додатковий параметр(символ), який буде містити Т, якщо значення NIL було фактичним параметром.
CL-USER> (defun L (&key (a 10) (b 20 s) (c 30 )) (list a b s c ))
L
CL-USER> (L :a 1 :b NIL :c 3)
(1 NIL T 3)
В нашому прикладі параметр b контролюється.
CL-USER> (L :a 1 :b 2 :c 3)
(1 2 T 3)
6.1.4 Остаточні ключові параметри
Застосування у визначенні функції ключа–параметра &REST дозволяє застосовувати у виклику функції будь-яку кількість фактичних параметрів.
Серед фактичних параметрів є обов’язкові, яким відповідають формальні параметри. Обов’язкові фактичні параметри при виклику пов’язуються з формальними параметрами. Якщо за обов’язковими фактичними параметрами є параметр &REST, то фактичні параметри збираються у список і привласнюються змінній, що йде за параметром &REST.
У прикладі показано, як формується з фактичних параметрів список.
CL-USER> (defun Sum (&rest L)(Print L))
SUM
CL-USER> (sum 1 2 3)
(1 2 3)
(1 2 3)
Всі типи ключів-параметрів одночасно вживають рідко, бо між ними можуть бути конфліктні ситуації. Записуються параметри у такій послідовності: обов’язкові, необов’язкові, іменовані, остаточні.
6.2 Базові функції і їх параметри
До базових функцій мови відносять функції, які існують у будь-яких сучасних діалектах мови LISP.
ФУНКЦІЯ LOAD
(LOAD “Шлях до файлу Ім’я файлу”)
Функція застосовується для завантаження вмісту файлу у середовище COMMON LISP. По замовчанню вживається каталог з LISP.BOX.
Приклад 1:
CL-USER> (load "d:\\Common Lisp\\s.txt")
;; Loading file D:\Common Lisp\s.txt; початок завантаження
;; Loaded file D:\Common Lisp\s.txt; кінець завантаження
ФУНКЦІЯ CAR
(CAR Об’єкт)
Якщо об’єкт список, функція одержує перший елемент списку і повертає його. Перший елемент списку називають головою списку. Якщо об’єкт конс, функція одержує і повертає лівий елемент консу.
CL-USER> (CAR '(4 2 3))
CL-USER> (CAR '(3 . 2))
ФУНКЦІЯ CDR
(CDR Об’єкт)
Якщо об’єкт список, функція повертає список без першого елементу. Список без першого елементу називають хвостом списку. Якщо об’єкт конс, функція повертає правий елемент консу.
CL-USER> (CDR '(4 2 3))
(2 3)
CL-USER> (CDR '(3 . 2))
СКЛАДЕНІ ФУНКЦІЇ
Часто потрібно застосовувати до списків комбінацію функцій CAR і CDR.
Приклад 1:
CL-USER> (SETQ L (CAR (CDR ‘(5 3 1) ) ) )
Функція CDR одержує від списку (5 3 1) його хвіст (3 1). Функція CAR одержує від хвоста списку його голову 3.
LISP дозволяє коротко записати таку комбінацію функцій CAR і CDR одною складною функцією:
CL-USER> (SETQ L (CADR‘(5 3 1)))
Приклад2:
CL-USER> (CAR (СAR ‘( (21 15 14 26) (18) (13 14) )))
Внутрішня функція CAR одержує список (21 15 14 26), а зовнішня функція CAR одержує число 21.
Ті ж дії виконує складна функція:
CL-USER> (CAAR '( (21 15 14 26) (18) (13 14) ))
Взагалі між буквами С і R можна вставляти до 4-х символів «А» і / або «D».
Приклад 3:
CL-USER> (CAADDR '( (1 2) (3 4) ( 5 6) ) )
<------
Внутрішня функція CDR від списку ( (1 2) (3 4) ( 5 6) ) повертає його хвіст ( (3 4) (5 6) ). Зовнішня функція CDR повертає від одержаного хвоста хвіст ( ( 5 6) ). Внутрішня функція CAR одержує від списку ( ( 5 6) ) його голову (5 6). Зовнішня функція CAR одержує число 5. Послідовність виконання функцій вказана стрілкою.
ФУНКЦІЯ CONS
Функція будує пару точок(конс):
(CONS Объект1 Объект2),
де об’єктами можуть бути будь-які об’єкти Lisp: список, символ, змінна, число, тощо.
Функція CONS будує список з його CAR і CDR елементів.
Приклад 1:
CL-USER>(CONS (CAR ‘(1 2 3) ) (CDR ‘(1 2 3)))
(1 2 3)
Якщо об’єкт2 список, то функція додає на початок списку объект1 і повертає поповнений список.
Приклад 2:
CL-USER> (cons 2 '(1 5 3))
(2 1 5 3)
Приклад 3:
CL-USER> (cons '(1 2) '(5 6 7))
((1 2) 5 6 7)
Якщо другий об’єкт не список, то функція повертає конс.
Приклад 4:
CL-USER> (cons "vaga" 65)
("vaga" . 65)
Приклад 4:
CL-USER> (cons 'bin-vector #*1111)
(Bin-VECTOR . #*1111)
ФУНКЦІЯ SET
Функція (SET Символ Об’єкт) – обчислює значення аргументів і привласнює значенню 1-го аргументу значення 2-го аргументу. Функція повертає значення, яке привласнює значенню першого аргументу. Якщо після обчислення аргументів перший аргумент не символ, то фіксується помилка «Не символьний аргумент».
Приклад 1:
CL-USER> (setq b 21)
CL-USER> (setq k 'с)
С
CL-USER> (set k b)
CL-USER> K
С
CL-USER> С
Привласнимо символу В 21, а символу К ‘С. Функція set обчислює обидва свої аргументи. Тому символ К має значення С, а символ В 21. В результаті символу С привласнюється 21.
Приклад 2:
CL-USER> (SETQ K 2)
CL-USER> (SETQ M 3)
CL-USER> (SET K M)
Помилка, видається повідомлення „Не символічний аргумент”.
СПЕЦІАЛЬНА ФОРМА SETQ
Робота спеціальної форми SETQ базується на функції SET.
SETQ застосовує остаточний параметр &REST. Спеціальна форма SETQ обчислює свої аргументи не перед викликом, а під час роботи і виконує групове привласнювання значень символам.
(Setq Символ1 Значение1 Символ2 Значение2 … Символ N ЗначенняN)
SETQ – може мати скільки завгодно аргументів. Аргументи діляться на пари: 1–ий елемент пари – символ, що не обчислюється; 2-ий аргумент – форма.
Спеціальна форма SETQ поступово розглядає пари зліва направо. Для кожної форми виконуються дії: обчислюється форма, привласнюється символу значення форми. Якщо кількість аргументів непарна, то символу привласнюється NIL.
Функція повертає останнє значення форми.
Наприклад:
CL-USER> (SETQ M 3 K (* M 4) N (- K 2) P)
NIL
CL-USER> K
CL-USER> N
CL-USER> P
NIL
Значення змінної K залежить від того, яке значення було привласнено символу M, а значення символу N залежить від того, яке значення було привласнено K. Для символу Р немає форми.
Запис (SETQ M 3) тотожній запису (SET (QUOTE M) 30 )
У COMMON LISP є функція SETQQ, яка забороняє обчислення обох аргументів.
МАКРОС РSETQ
МАКРОСPSETQ застосовує остаточний параметр &REST. Аргументи його діляться на пари, як у SETQ, проте обчислення значень виконується по-іншому.
PSETQ працює так: спочатку обчислюється 2-і аргументи кожної пари, після чого зліва направо виконується привласнювання символам значень. Макрос завжди повертає NIL.
Приклад 1:
CL-USER> (SETQ M 3 C 10)
CL-USER> (PSETQ C 4 M (+ 5 M) P (* C M M) )
4 8 90
NIL
CL-USER> M
CL-USER> P
Порівняємо результати обчислень тих же виразів функцією SETQ.
CL-USER>(SETQ M 3 C 10)
CL-USER> (SETQ C 4 M (+ 5 M) P (* C M M) )
4 8 256
ФУНКЦІЯ LIST
Функція може мати скільки завгодно фактичних параметрів. Вона застосовує остаточні параметри &reast. Функція обчислює значення своїх об’єктів, будує з них список і повертає побудований список.
(LIST об’єкт1 об’єкт2 … об’єкт K)
Покажемо перевагу створення списку функцією LIST перед іншими способами створення списку.
Нехай символам привласнюванні значення:
CL-USER> (SETQ A 13 B 14 C 15 D 16)
Створимо список з використанням дужок.
CL-USER> (SETQ L (A B C D))
Виводиться повідомлення „Невідома функція А”.
Заборонимо обчислення списку функцією QUOTE, щоб інтерпретатор не розглядав список, як виклик функції:
CL-USER>(SETQ L ‘(A B C D))
(A B C D)
Але функція QUOTE не дозволяє обчислювати значення змінних.
Функція LIST дозволяє обчислювати значення змінних при побудові списку. Перший елемент списку функція LIST.
CL-USER> (SETQ L (LIST A B C D))
(13 14 15 16)
ТЕМА 7: УЗАГАЛЬНЕННЯ ПОНЯТТЯ „ЗМІННА”
7.1 Застосування форми у якості місця
У мовах нижнього рівня змінна - це вічко з іменем(адресою) або група вічок з іменем, яким привласнюються значення. Такий підхід не дозволяє одній змінній привласнювати дані різних типів, бо дані різних типів займають різну кількість байтів і мають різну організацію. У алгоритмічних мовах вищого рівня, що не мали абстрактних типів цей підхід зберігався.
Дата добавления: 2016-09-20; просмотров: 566;