Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы функционального программирования. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
Отображающий функционал можно написать самим, а можно и воспользоваться одним из встроенных. Согласно стандарту, в реализацию языка Clisp обычно включены функционалы: MAP, MAPCAR, MAPLIST, MAPCAN, MAPCON, MAPC, MAPL [6, 7]. Каждый из них покомпонентно обработает любой набор списков. Отличаются они схемами выбора аргументов для отображающей функции, характером воздействия на исходные данные и оформлением результатов, передаваемых объемлющим формулам.
Map
( map result-type function sequences ... )
Функция FUNCTION вызывается на всех первых элементах последовательностей, затем на всех вторых и т.д. Из полученных результатов FUNCTION формируется результирующая последовательность, строение которой задается параметром RESULT­TYPE с допустимыми значениями CONS, LIST, ARRAY, STRING, NIL.
Mapcar
( mapcar funct list ... )
Функция FUNCTION применяется к первым элементам списков, затем ко вторым и т.д. Другими словами, FUNCTION применяется к ";головам" методично сокращающихся списков, и результаты применения собираются в результирующий список.
(mapcar #'+ '(1 2 3) '(4 5 6)) ; = (5 7 9) (mapcar #'list '(1 2 3)'(4 5 6)) ; = ((1 4)(2 5)(3 6)) (DEFUN evlis (args) (mapcar #'EVAL args)) ; вычисление аргументов
Пример 4.14.
(Без учета ассоциативного списка)
(DEFUN evlis (args AL) (mapcar #'(LAMBDA (x) (EVAL x AL)) args))
Основы функционального программированияЛ.В. Городняя
81
Maplist
( maplist function list ... )
Функционал аналогичен MAPCAR, но FUNCTION применяется к "хвостам" списков LIST, начиная с полного списка.
(maplist #'list '(1 2 3)'(4 5 6)) ; = (((1 2 3) (4 5 6)) ((2 3) (5 6)) ((3) (6)))
Пример 4.15.
Mapc и Mapl
Оба функционала работают как MAPCAR и MAPLIST, соответственно, за исключением того, что они в качестве формального результата выдают первый список (своеобразная аналогия с формальными аргументами).
(mapc #'list '(1 2 3)'(4 5 6)) ; = (1 2 3) (mapl #'list '(1 2 3)'(4 5 6)) ; = (1 2 3)
Пример 4.16.
Mapcan и Mapcon
И эти два функционала аналогичны MAPCAR и MAPLIST, но формирование результатов происходит не с помощью операции CONS, которая строит данные в новых блоках памяти, а с помощью деструктивной функции NCONC, которая при построении новых данных использует память исходных данных, из-за чего исходные данные могут быть искажены.
В общем случае, отображающие функционалы представляют собой различные виды структурной итерации или итерации по структуре данных. При решении сложных задач полезно использовать отображения и их композиции, а также иметь в виду возможность создания своих функционалов.
MAP-INTO отображает результат в конкретную последовательность.
Основы функционального программированияЛ.В. Городняя
82
Подведение итогов
Показанные построения достаточно разнообразны, чтобы можно было сформулировать, в чем преимущества применения техники функционального программирования:
отображающие функционалы позволяют строить программы из крупных действий ; функционалы обеспечивают гибкость отображений ; определение функции может совсем не зависеть от конкретных имен ; с помощью функционалов можно управлять выбором формы результатов ; параметром функционала может быть любая функция, преобразующая элементы структуры; функционалы позволяют формировать серии функций от общих данных ; встроенные в Clisp функционалы приспособлены к покомпонентной обработке произвольного числа параметров ; любую систему взаимосвязанных функций можно преобразовать к одной функции, используя вызовы безымянных функций.
Для самостоятельного решения
Можно предложить следующие задачи на применение функционалов:
1) Напишите определение функционала F-ALL, выясняющего, все ли элементы множества SET удовлетворяют заданному предикату PRED.
(DEFUN f-all (Pred Set ) . . . )
2) Напишите определение функционала F-EX, выясняющего, найдется ли в множестве SET элемент, удовлетворяющий заданному предикату PRED.
(DEFUN f-ex (Pred Set ) . . . )
3) Пусть программа представляет собой набор списков, содержащих имя команды и произвольное число операндов. Имя расположено первым в
Основы функционального программированияЛ.В. Городняя
83
списке. Напишите определение функционала, удобного для выдачи списка операндов, встречающихся в программе, а также для выдачи отдельных интегральных характеристик, таких как суммарное число всех операндов, максимальное число операндов в команде и т.п.
4) Напишите универсальный фильтр, позволяющий из произвольного списка выделять при необходимости атомы, числа, строки или списки, начинающиеся с заданного атома, и т.д.
5) Пусть клетки доски типа шахматной пронумерованы по горизонтали символами, а по вертикали числами. И то, и другое перечислено в отдельных списках по порядку. Напишите функцию перечисления координат всех клеток доски, соответствующей размерам списков.
6) При анализе труднодоступных данных требуется всю потенциально полезную информацию выяснять сразу, <в одно касание>. Напишите модель такого стиля работы на примере покомпонентной обработки двух списков чисел. Роль полезной информации могут играть значения любых бинарных операций, таких как +, *, -, /, MAX, MIN и т.п.
7) Пусть программа представляет собой набор списков, содержащих имя команды и не более двух операндов. Имя расположено в списке первым. Напишите определение функционала, удобного для выдачи по мере необходимости перечня команд, или перечня первых операндов, или вторых операндов и т.п.
Подготовьте определения вспомогательных функций на все эти случаи.
8) Список содержит ежедневные сведения о количестве осадков, выпавших за весьма длительный период. Напишите функционал, позволяющий по этому списку оперативно выяснять различные сведения, наподобие:
суммарный объем осадков; максимальное количество осадков в день; минимальное количество осадков в день; максимальная разница в количестве осадков в соседние дни.
9) Задача повышенной сложности (с решением).
Основы функционального программированияЛ.В. Городняя
84
Лексикон ***)
Условие задачи: Группа специалистов договорилась подготовить лексикон программирования для электронной публикации. Было решено, что надо добиться <правильности> определения понятий программирования, а именно не допускать цепочек понятий прямо или косвенно определяемых через себя. Кроме того, следует обеспечить полноту комплекта определений, т.е. всякое включенное в лексикон понятие должно иметь определение.
Напишите программу, помогающую по ходу разработки лексикона отслеживать его <правильность> и полноту.
Входные данные:
(( имя_понятия объяснение ) ... ) ­ двухуровневый список, в котором имя_понятия - атом, обозначающий определяемое понятие, объяснение - последовательность строк и/или атомов, строки не требуют определения, а атомы должны получить определения в процессе разработки, но, возможно, еще не все слова удалось объяснить.
Выходные данные:
Словарь правилен или Есть неправильные цепочки имя_понятия1 ... имя_понятияN |___________________|______ начала неправильных цепочек и/или Есть неопределенные понятия имя_понятия1 ... имя понятияN |___________________|_______ имена неопределенных понятий (слова перечисляются в порядке включения в словарь.)
Основы функционального программированияЛ.В. Городняя
85
Пример ввода:
(( автокод язык_программирования <используется для создания> операционная_система <и> транслятор) ( язык_программирования <задается множеством правил для написания> программ) ( операционная_система <комплекс> программа <управляющих решением задач на имеющемся оборудовании>) ( транслятор <компилирующая> программа) ( программа <описание> алгоритм <решения задачи на соответствующем языке>) ( алгоритм <точно определенное правило действий>) )
Уточнения:
Может ли объяснение быть пустым? - Да. Может ли быть много объяснений для одного имени? - Да. Могут ли быть идентичные объяснения? - Да. Может ли одно слово входить в объяснение неоднократно? - Да. Предполагается ли одновременная диагностика и циклов, и неопределенностей? - Да. При выводе результата неопределенные имена надо вывести все.
Пример теста:
(( а-к яп <используется для создания> ос <и> сп) ( яп <задается множеством правил для написания> пр) ( ос <комплекс> пр <управляющих решением задач на имеющемся оборудовании>) ( сп <компилирующая> пр) ( пр <описание> алг <решения задачи на соответствующем языке>) ( алг <точно определенное правило действий>) )
'(( а-к яп ос сп) ( яп пр) ( ос пр) ( сп пр) ( пр алг) ( алг ))
Основы функционального программированияЛ.В. Городняя
86
;;=== Лексикон****) - проверка корректности == ;; Предполагается, что из теста уже ;; отфильтрованы строки, ;; т.к. они не влияют на логику анализа корректности
(DEFUN NAMES (VAC) (MAPCAR 'CAR VAC)) ;; определяемые имена - список левых частей
(DEFUN WORDS (VAC) (COND ;; используемые имена - список правых частей ((NULL VAC) NIL) (T (UNION (CDAR VAC) (WORDS (CDR VAC)))) )) (DEFUN UNDEF (VAC) (SET-DIFFERENCE (WORDS VAC) (NAMES VAC))) ;; неопределенные имена - список висячих ссылок (DEFUN CIRCLE (V) ;; проверка термина на явный цикл (COND ((NULL (CDR V)) NIL)
((MEMBER (CAR V) (CDR V)) (CAR V)) (T NIL) ))
(DEFUN CIRC-V (VAC) (MAPCAR 'CIRCLE VAC)) ;; список явных циклов с NIL-ами на нециклах
(DEFUN MASKA (ARG XXX) (COND (XXX NIL) (T ARG))) ;; ВЫБОР, ЕСЛИ NIL
(DEFUN DEL-CIR (AL XL) (DELETE NIL (MAPCAR 'MASKA AL XL))) ;; стирание непомеченных определений, т.е. циклов
(DEFUN SKOBKI (LL) (COND((NULL LL)NIL) ((NULL (CAR LL)) (SKOBKI (CDR LL)) ) ((ATOM (CAR LL))(CONS(CAR LL) (SKOBKI(CDR LL))) ) (T (UNION (CAR LL) (SKOBKI (CDR LL)) ))
Основы функционального программированияЛ.В. Городняя
87
)) ;; раскрыть скобки на один уровень
(DEFUN ONESTP (VC)(SETQ VAC VC) ;; однократная постановка всего словаря
(MAPCAR '(LAMBDA (X) (CONS (CAR X) (SKOBKI (SUBLIS VAC (CDR X))) )) VC ))
(DEFUN CLEAN-S (LINE XL) (COND ((NULL XL) LINE) (T (CLEAN-S (DELETE (CAR XL) LINE)(CDR XL) )) ))
(DEFUN CLEAN-U (VC XL) (SETQ WL XL)
;; стирание заданного списка слов => висячих ссылок
(MAPCAR '(LAMBDA (XX) (SETQ X XX) (CONS (CAR X) (CLEAN-S (CDR X) WL) )) VC ))
(DEFUN CVR (VAC)(DELETE NIL (CVR-D (DEL-CIR VAC (CIRC-V VAC)) (DELETE NIL(UNION (CIRC-V VAC) NIL))))) ;; список всех циклов полного словаря - без ;; висячих ссылок
(DEFUN CVR-D (VC CCL) (PROG (VAC CL CV DCV CLEANV) (SETQ VAC (CLEAN-U VC CCL)) (SETQ CL CCL)
;; пополнение списка циклов со второго шага LAB (COND ((WORDS VAC) (SETQ CV (CIRC-V VAC)) (SETQ DCV (DELETE NIL CV))
Основы функционального программированияЛ.В. Городняя
88
(SETQ CLEANV (CLEAN-U (DEL-CIR VAC CV) DCV)) (SETQ VAC (ONESTP CLEANV)) (SETQ CL (APPEND DCV CL)) (GO LAB) )) (RETURN CL) ))
(DEFUN VAC-OK (VAC) (PROG (VC UL CL) ;; ПРОВЕРКА СЛОВАРЯ НА КОРРЕКТНОСТЬ (SETQ VC VAC) (SETQ UL (UNDEF VC)) (SETQ CL (CVR (CLEAN-U VAC UL)))
(COND ((EQ UL CL) (RETURN(PRINT 'OK)) ) ; = лишь если пусты <> корректность словаря ( CL (PRINT (LIST 'CIRCLES CL))) )
(COND (UL (RETURN (PRINT (LIST 'UNDEFINED UL))) ) (T (RETURN (LIST 'CIRCLE CL))) ) ))
*) Символ ";" - начало комментария.
**) На Lisp 1.5 это определение выглядит изящнее, не требует встроенной функции FUNCALL, при отладке примеров на Clisp-е [7]:
(DEFUN map-el (fn xl) (COND (xl (CONS (fn (CAR xl) ) ; применяем первый аргумент как функцию ; к первому элементу второго аргумента (map-el fn (CDR xl) ) ) ) ) )
***) Эта задача была предложена участникам Открытой Всесибирской студенческой олимпиады в 2000 году и оказалась в числе никем не решенных. Многих смутило отсутствие численных ограничений на допустимые данные. При решении задач на Паскале и Си такие
Основы функционального программированияЛ.В. Городняя
89
ограничения обычно подсказывают выбор структур данных, поэтому отсутствие ограничений было воспринято как риск. Немногочисленные попытки решить задачу привели к отбраковке на минимальных тестах, вызванной тем, что программы не допускали пустой словарь или словарь, выглядящий как перечень терминов без определений. (Впрочем, возможно, это ошибка разработчика тестов. Видимо, первыми должны располагаться тесты на наиболее типичные, естественные случаи.)
****) Решение этой задачи может быть сведено к задаче <Проверка ацикличности графа>.
1)
Здесь и далее, следуя CLISP, (COND NIL) = NIL, т.е. допускается
отсутствие предиката со значение "истина".
Основы функционального программированияЛ.В. Городняя
90
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]