
- •2. Абстрактное программирование. Функционалы и их применение в вычислительной математике Цель работы
- •Содержание работы
- •Введение в абстрактное программирование
- •Основные типы функционалов и их применения Применяющие функционалы
- •Отображающие функционалы
- •Порядок выполнения работы Основные приемы программирования функционалов
- •Индивидуальные задания
- •Время проведения работы
- •Содержание отчета
2. Абстрактное программирование. Функционалы и их применение в вычислительной математике Цель работы
Изучение основных приемов абстрактного подхода к написанию функциональных программ.
Изучение основ функционального стиля программирования.
Изучение способов программирования с помощью функций.
Изучение способов представления и интерпретации функциональных программ.
Знакомство с особенностями программирования на языке Лисп.
Освоение инструментальных средств разработки функциональных программ.
Содержание работы
Программирование определений функционалов по условию задачи с необходимыми комментариями.
Организация дружественного диалога с предполагаемым пользователем программы. Тестирование определений. Документирование программы.
Введение в абстрактное программирование
Порядок рекурсии функций считается от 0.
Функционал = функция, имеющая функциональный аргумент (функция >1 порядка).
Применяющие функционалы:
(SETQ plus ‘+).
(APPLY plus ‘(2 3)) -> 5.
$ (FUNCALL plus 2 3)) -> 5.
Отображающие функционалы:
(MAPCAR ‘(lambda (x y) (list x y)) ‘(a b c) ‘(1 2 3)) -> ((a 1) (b 2) (c 3)).
(MAPLIST ‘(lambda (y) y) ‘(a b c)) -> ((a b c) (b c) (c)).
(defun mapcar (f l)((null l) nil)(cons(funcall fn (car l))(mapcar fn (cdr l)))).
Автоаппликативный вариант факториала:
(defun ! (n) (fact ‘fact n)).
(defun fact (f n) ((zerop n) 1) (* n (funcall f f (- n 1))))).
Основные типы функционалов и их применения Применяющие функционалы
(APPLY <функциональный аргумент> <список аргументов> )
(<функциональный аргумент> ‘<аргумент-1> ... ‘<аргумент-N>)
где
<функциональный аргумент> ::= <имя функции> |
<лямбда–выражение>
<список аргументов> ::= (<аргумент-1> ... <аргумент-N>)
Пример нахождения суммы элементов списка:
(APPLY ‘+ ‘(1 2 3 4 5)) (+ 1 2 3 4 5) -> 14
Пример нахождения произведения элементов списка:
(APPLY ‘* ‘(1 2 3 4 5)) (* 1 2 3 4 5) -> 120
(FUNCALL <функциональный аргумент>
<аргумент-1> ... ‘<аргумент-N>)
(<функциональный аргумент> <аргумент-1> ... <аргумент-N>)
В AutoLISP функционал FUNCALL в явной форме отсутствует, поскольку разрешается использование синонимов или функциональных аргументов непосредственно:
(SETQ plus +)
((LAMDBA (f x y) (f x y)) plus 2 3)
(plus 2 3) (+ 2 3) -> 5
Необходимо отметить, что в качестве фактического аргумента для f передается синоним имени примитива + а не символ ‘+.
Отображающие функционалы
Пример нахождения суммы квадратов элементов списка:
(MAPCAR ‘(LAMDBA (x y) (+ x y)) ‘(1 2 3 4 5)) (+ 1 2 3 4 5) -> 14
Порядок выполнения работы Основные приемы программирования функционалов
; 1. Применяющие функционалы.
; EVAL
; (eval '(+ 2 3 4 5))
; Лямбда- функции и функциональные аргументы
; (apply '+ '(2 3 4 5))
; (apply '(lambda (x y) (* x y)) '(2 3))
; В AutoLISP имеется встроенная функция MAPCAR с числом аргументов-списков
; в соответствии с арностью функции
; в качестве первого аргумента MAPCAR требует символьное выражение,
; представляющее собой либо имя функции или заблокированное с помощью
; QUOTE или FUNCTION лямбда- выражение.
; Пример. Произведение элементов 2-х списков
(defun ПроизведениеСписков (список1 список2)
(MAPCAR '* список1 список2)
)
;Пример. (ПроизведениеСписков '(1 2 3) '(4 5 6))
;Результат: (4 10 18)
; Пример. Сумма квадратов элементов списка
(defun КвадратыЭлементовСписка (список)
(MAPCAR '* список список)
)
;Пример. (КвадратыЭлементовСписка '(1 2 3))
;Результат: (1 4 9)
; Применение функции из списокФункций к соответствующему элементу из списокДанных
(defun APL-APPLY (списокФункций списокДанных)
(MAPCAR '(lambda (функция элемент) ((EVAL функция) элемент)) списокФункций списокДанных)
)
;Пример. (APL-APPLY '(cdr reverse) '((1 2 3) (4 5 6)))
;Результат: ((2 3) (6 5 4))
; 2.
; Одно из приблизительных описаний MAPCAR может быть следующим.
;Заметим, что, в отличие от MAPCAR в качестве первого аргумента передается
; не символ или заблокированное вычисление а сама функция.
; для случая арности функции 1
(defun Map-Car-1 (функция список)
(if (null список) nil
(cons (функция (car список)) (Map-Car-1 функция (cdr список)))
)
)
; для случая арности функции 2
(defun Map-Car-2 (функция список1 список2)
(if (null список1) nil
(cons (функция (car список1) (car список2)) (Map-Car-2 функция (cdr список1) (cdr список2)))
)
)
;Применение функции последовательно к каждому элементу списка
;Пример. Обращение внутренних подсписков списка:
; (Map-Car-1 reverse '((1 2 3 4 5) (2 3 4 5) (6 7 8)))
;Результат: ((5 4 3 2 1) (5 4 3 2) (8 7 6))
;Пример. Возведение элементов списка в квадрат:
; (Map-Car-1 (lambda (x) (* x x)) '(1 2 3 4 5))
;Результат: (1 4 9 16 25)
;Пример. Поэлементное произведение двух списков:
; (Map-Car-2 (lambda (x y)(* x y)) '(1 2 3) '(5 4 3))
;Результат: (5 8 9 8 5)
(defun КвадратыЭлементовСписка-1 (список)
(Map-Car-1 (lambda (элемент) (* элемент элемент)) список)
)
;или
(defun КвадратыЭлементовСписка-2 (список)
(Map-Car-2 * список список)
)
;Пример. (КвадратыЭлементовСписка-1 '(1 2 3 4 5))
; или (КвадратыЭлементовСписка-2 '(1 2 3 4 5))
;Результат: (1 4 9 16 25)
; 3.
; На практике возникает необходимость в определении большого количества
; различных функционалов. Учитывая однотипность операций обработки списков
; удобно определить одну универсальную параметризованную функцию высших порядков,
; в которой в абстрактной форме реализуются большинство необходимых операций над списками.
; Ниже приводится примерный вариант такого функционала.
(defun Map-Def (проверкаЗавершенияОбработкиСписка
объединениеРезультатов
выборОбрабатываемойЧастиСписка
выборОстальнойЧастиСписка
ПрименяемаяФункцияПользователя
списокПользователя)
(if (проверкаЗавершенияОбработкиСписка списокПользователя) nil
(объединениеРезультатов
(ПрименяемаяФункцияПользователя
(выборОбрабатываемойЧастиСписка списокПользователя)
)
(Map-Def проверкаЗавершенияОбработкиСписка
объединениеРезультатов
выборОбрабатываемойЧастиСписка
выборОстальнойЧастиСписка
ПрименяемаяФункцияПользователя
(выборОстальнойЧастиСписка списокПользователя)
)
)
)
)
; Используя Map-Def можно написать другой вариант функции Map-Сar-1,
; который и будет нами использоваться в дальнейшем.
(defun Map-Car (ФункцияПользователя списокПользователя)
(Map-Def null ; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
car ; выборОбрабатываемойЧастиСписка
cdr ; выборОстальнойЧастиСписка
ФункцияПользователя списокПользователя)
)
;Табулирование функций: получение списка пар значений элементов списка и функций от них. )
(defun ТабулированиеФункции(функция список)
( Map-Car (lambda (элемент) (list элемент (функция элемент))) список)
)
;Пример. Получение списка координат вида (x y) для функции вида y=x^2
;(ТабулированиеФункции (lambda (x)(* x x)) '(1 2 3 4))
;Результат: ((1 1) (2 4) (3 9) (4 16))
; Полезной функцией для дальнейших определений является copy.
; сopy - функция, возвращающая полученное в качестве аргумента значение
(defun copy (элемент) элемент)
; Map-List : Последовательное применение функции к списку и
;последовательно к его подспискам без первого элемента
(defun Map-List (функция список)
(Map-Def null ; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
copy ; выборОбрабатываемойЧастиСписка
cdr ; выборОстальнойЧастиСписка
функция список)
)
;Пример.
;(Map-List copy (1 2 3 4 5))
;Результат: ((1 2 3 4 5) (2 3 4 5) (3 4 5) (4 5) (5))
;Пример. Обращение полученных подсписков
;(Map-List reverse '(1 2 3 4 5))
;Результат: ((5 4 3 2 1) (5 4 3 2) (5 4 3) (5 4) (5))
;Пример. Вычисление произведения полученных подсписков
;(Map-List (lambda (x) (apply '* x)) '(1 2 3 4 5))
;Результат: (120 120 60 20 5)
; Map-Can, Map-Con : аналоги MAPCAR, MAPLIST, но объединяют
; результаты (подсписки) в один список
(defun Map-Can (функция список)
(Map-Def null append car cdr функция список)
)
(defun Map-Con (функция список)
(Map-Def null append copy cdr функция список)
)
;Пример. Вывести только положительные элементы списка:
;(Map-Can (lambda (x) (if (> x 0) (list x) nil)) '(-1 -2 1 2 0 -3 -4 3 4))
;Результат: (1 2 3 4)
;Пример. (Map-Con copy '(1 2 3 4 5))
;Результат: (1 2 3 4 5 2 3 4 5 3 4 5 4 5 5)
;Пример. (Map-Con reverse '(1 2 3 4 5))
;Результат: (5 4 3 2 1 5 4 3 2 5 4 3 5 4 5)
; Map-C, Map-L : аналоги Map-Car, Map-List, но не собирают и необъединяют результаты, а
; возвращают исходный список
(defun Map-C (функция список)
(PROGN (Map-Car функция список) список)
)
(defun Map-L (функция список)
(PROGN (Map-List функция список) список)
)
;Пример. (Map-C (lambda (x) (* x x)) '(1 2 3 4))
;Результат: (1 2 3 4)
;Пример. (Map-L reverse '(1 2 3 4))
;Результат: (1 2 3 4)
;Пример. Вывести элементы списка на экран и вернуть исходный список без изменений
; (Map-C print '(1 2 3 4 5))
;Результат: 1
; 2
; 3
; 4
; 5 (1 2 3 4 5)
;Пример. Функция возвращает исходный список, при этом выводятся на экран все
;хвостовые части исходного списка, начиная с исходного
; (Map-L print '(1 2 3 4 5))
;Результат: (1 2 3 4 5)
; (2 3 4 5)
; (3 4 5)
; (4 5)
; (5) (1 2 3 4 5)
; Вычисление декартова произведения 2-х списков
(defun ДекартовоПроизведение (список1 список2)
(Map-Can (lambda (элемент1) (Map-Car (lambda (элемент2) (list элемент1 элемент2)) список2)) список1)
)
;Пример. (ДекартовоПроизведение '(a b c) '(1 2 3))
;Результат: ((A 1) (A 2) (A 3) (B 1) (B 2) (B 3) (C 1) (C 2) (C 3))
;Проверяет, удовлетворяет ли каждый элемент списка условию
(defun Every (условие список)
(APPLY 'AND (Map-Car условие список))
)
;Проверяет, удовлетворяет ли хотя бы один элемент списка условию
(defun Some (условие список)
(APPLY 'OR (Map-Car условие список))
)
;Пример. (Every (lambda (x) (> x 0)) '(1 2 3 4 5))
;Результат: T
;Пример. (Every (lambda (x) (> x 0)) '(1 2 3 4 5 0 -1))
;Результат: nil
;Пример. (Some (lambda (x) (< x 0)) '(1 2 3 4 5 6))
;Результат: nil
;Пример. (Some (lambda (x) (< x 0)) '(1 2 3 0 -4))
;Результат: T
; Удаление элементов из списка, удовлетворяющих условию
(defun DeleteIf (условие список)
(Map-Can (lambda (элемент)
(if (условие элемент) nil (list элемент))
)
список
)
)
; Удаление элементов из списка, неудовлетворяющих условию
(defun DeleteIfNot (условие список)
(Map-Can (lambda (элемент) (if (условие элемент) (list элемент) nil)) список)
)
;Пример. (DeleteIf (lambda (x) (< x 0)) '(1 2 3 -4 4 5 -6 0 -8 9))
;Результат: (1 2 3 4 5 0 9)
;Пример. (DeleteIfNot (lambda (x) (> x 0)) '(1 2 3 0 9 -4))
;Результат: (1 2 3 9)
; 4.
; Одним из частных случаев списка можно считать матрицу.
; Операции над матрицами являются достаточно распространенными при решении численных задач.
; Поэтому ниже приводятся определения наиболее полезных функционалов,
; предназначенных для манипуляций со строками и столбцами матриц.
; Применение функции к каждому элементу матрицы
(defun Matr-Element (функция матрица)
(Map-Car (lambda (строка) (Map-Car функция строка)) матрица)
)
;Пример. Умножить каждый элемент матрицы на 3
;(Matr-Element (lambda (x) (* x 3)) '((1 2 3) (4 5 6)))
; Результат: ((3 6 9) (12 15 18))
; Первый столбец матрицы
(defun Matr-Car (функция матрица)
(Map-Def null ; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
caar ; выборОбрабатываемойЧастиСписка
cdr ; выборОстальнойЧастиСписка
функция матрица)
)
;Пример. (Matr-Car copy '((1 2 3) (4 5 6) (7 8 9)))
;Результат: (1 4 7)
;Возвращает матрицу без 1-го столбца
(defun Matr-Cdr (функция матрица)
(Map-Car cdr (функция матрица))
)
;Пример. (MATR-CDR copy '((1 2 3)(4 5 6)(7 8 9)))
;Результат: ((2 3) (5 6) (8 9))
;Пример. (MATR-CDR (lambda (x) (Matr-Element (lambda (y) (* y 3)) x)) '((1 2 3)(4 5 6)(7 8 9)))
;Результат: ((6 9) (15 18) (24 27))
;Возвращает список, содержащий саму матрицу, матрицу без 1-го столбца и т.д.
(defun Matr-Map-List (функция матрица)
(Map-Def (lambda (список) (Every null список))
; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
copy ; выборОбрабатываемойЧастиСписка
(lambda (список) (Map-Car cdr список)); выборОстальнойЧастиСписка
функция матрица)
)
;Пример. (Matr-Map-List copy '((1 2 3) (4 5 6) (7 8 9)))
;Результат: (((1 2 3) (4 5 6) (7 8 9)) ((2 3) (5 6) (8 9)) ((3) (6) (9)))
;Список столбцов матрицы
(defun Matr-Map-Car-2 (функция матрица)
(Matr-Map-List (lambda (x) (Matr-Car copy x)) (функция матрица))
)
; или через Map-Def
(defun Matr-Map-Car (функция матрица)
(Map-Def (lambda (список) (Every null список))
; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
(lambda (матрица) (Matr-Car copy матрица))
; выборОбрабатываемойЧастиСписка
(lambda (матрица) (Map-Car cdr матрица)); выборОстальнойЧастиСписка
функция матрица)
)
;Пример.(Matr-Map-Car copy '((1 2 3) (4 5 6) (7 8 9)))
;или (Matr-Map-Car-2 copy '((1 2 3) (4 5 6) (7 8 9)))
;Результат: ((1 4 7) (2 5 8) (3 6 9))
;Транспонирование матрицы (поворот матрицы на 180 градусов)
(defun Matr-Trans (функция матрица)
(Matr-Map-List (lambda (частьМатрицы) (Matr-Car copy частьМатрицы))
(функция матрица))
)
; Пример. (Matr-Trans copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: ((1 4 7) (2 5 8) (3 6 9))
;Поворот матрицы вправо
(defun Matr-RightRotate (функция матрица)
(Matr-Map-List (lambda (частьМатрицы) (Matr-Car copy частьМатрицы))
(функция (reverse матрица)))
)
; Пример. (Matr-RightRotate copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: ((7 4 1) (8 5 2) (9 6 3))
;Поворот матрицы влево
(defun Matr-LeftRotate (функция матрица)
(reverse (Matr-Map-List
(lambda (частьМатрицы) (Matr-Car copy частьМатрицы))
(функция (copy матрица))))
)
; Пример. (Matr-LeftRotate copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: ((3 6 9) (2 5 8) (1 4 7))
;Список матриц, полученных вычеркиванием 1-ых столбца и строки и т.д. до конца
(defun SubMatr-Map-List (функция матрица)
(Map-Def (lambda (список) (Every null список))
; проверкаЗавершенияОбработкиСписка
cons ; объединениеРезультатов
copy ; выборОбрабатываемойЧастиСписка
(lambda (список) (CADR (Matr-Map-List cdr список)))
; выборОстальнойЧастиСписка
функция матрица)
)
; Пример. (SubMatr-Map-List copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: (((1 2 3) (4 5 6) (7 8 9)) ((5 6) (8 9)) ((9)))
;1-я диагональ матрицы (слева направо сверху вниз ; самая левая нижняя - 1-я)
(defun Matr-Diag (функция матрица)
(SubMatr-Map-List (lambda (x) (caar x)) матрица)
)
; Пример. (Matr-Diag copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: (1 5 9)
;Список нижних диагоналей матрицы (слева направо сверху вниз)
(defun Matr-LowDiagList (функция матрица)
(Map-List (lambda (подматрица) (Matr-Diag функция подматрица)) матрица)
)
; Пример. (Matr-LowDiagList copy '((1 2 3) (4 5 6) (7 8 9)))
; Результат: ((1 5 9) (4 8) (7))