При определении
При обходе структуры, представляющей множество,
Ответ на каждый из таких вопросов может быть дан в виде отдельной функции или
Таким образом, определение
Любую информацию можно представить символьными выражениями. В качестве основных видов символьных выражений выбраны списки и атомы. Атом - неделимое данное, представляющее информацию произвольной природы. Но во многих случаях знание природы информации дает более четкое понимание особенностей изучаемых механизмов.
Программирование работы с числами и строками – привычная, хорошо освоенная область информационной обработки, удобная для оценки преимуществ использования
1 -123 9876543210000000000000123456789
Можно работать с дробными и вещественными числами:
8/12 ;= 2/3 3.1415926
Строки заключаются в обычные двойные кавычки:
"строка любой длины, из произвольных символов, включая все что угодно"
Со строками можно при необходимости работать посимвольно, хотя они рассматриваются как атомы.
(string-equal "строка 1" " строка1");=Nil (ATOM "a+b-c") ;= T (char "стр1" 4 ) ;= "1"
Список - составное данное, первый элемент которого может рассматриваться как функция, применяемая к остальным элементам, также представленным как символьные выражения.
Это относится и к операциям над числами и строками.
Большинство операций над числами при префиксной записи естественно рассматривать как мультиоперации от произвольного числа аргументов.
(+ 1 2 3 4 5 6) ;= 21 (- 12 6 3) ;= 3 (/ 3 5) ;= 3/5
Любое данное можно превратить в константу, поставив перед ним "'" апостроф. Это эквивалентно записи со специальной функцией " QUOTE ". Для чисел и строк в этом нет необходимости, но это не запрещено:
'1 ;= 1 '"abc" ;= "abc"
Отказ от барьера между представлениями функций и значений дает возможность символьные выражения использовать как для изображения заданных значений, включая любые структуры над числами и строками, так и для определения функций, обрабатывающих любые данные. (Напоминаем, что определение функции - данное.)
Функционалы - это функции, которые используют в качестве аргументов или результатов другие функции. При построении
| (= Число … ) | Истина, если разница между любыми двумя аргументами равна нулю |
| (/= Число … ) | Истина, если никакие два аргумента не равны между собой |
| (> Число … ) | Истина, если каждый аргумент превышает прешественника |
| (< Число … ) | Истина, если каждый аргумент меньше прешественника |
| (<= Число … ) | Истина, если каждый аргумент меньше или равен прешественнику |
| (>= Число … ) | Истина, если каждый аргумент превышает или равен прешественнику |
| (* Число … ) | Произведение произвольного числа аргументов. 1 при их отсутствии. |
| (+ Число … ) | Сумма произвольного числа аргументов. 0 при их отсутствии. |
| (- Число … ) | Эквивалентно расстановке минусов между аргументами, т.е. (- a b c ) = a – b – c |
| (/ Число … ) | Первое число делится на произведение остальных, среди которых не должно быть нуля. |
| (1+ Число ) | ( + Число 1) |
| (1- Число ) | ( - Число 1) |
| (Boole Операция Целое1 Целое2 ) | Вычисляет результат применеия побитовой Операции к двум Целым. |
| ( |
Наибольший общий делитель. Ноль без аргументов. |
| ( |
Наименьшее общее произведение, 1 при отсутствии аргументов. |
| (min Число …) | |
| (max Число …) |
Рассмотрим технику использования
(defun next (xl) ; Следующие числа:
(cond ; пока список не пуст
(xl (cons (1+ (car xl)) ; прибавляем 1 к его голове
(next (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(next '(1 2 5 )) ; = (2 3 6 )
(defun 1st (xl) ; "головы" элементов = CAR
(cond ; пока список не пуст
(xl (cons (caar xl) ; выбираем CAR от его головы
(1st (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(1st '((один два )(one two )(1 2 )) ) ; = (один one 1)
(defun lens (xl) ; Длины элементов
(cond ; Пока список не пуст
(xl (cons (length (car xl)); вычисляем длину его головы
(lens (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(lens '((1 2 ) () (a b c d ) (1 (a b c d ) 3 )) ) ; = (2 0 4 3 )
Внешние отличия в записи этих трех функций малосущественны, что позволяет ввести более общую функцию map-el, в определении которой имена " car ", " 1+ " и " length " могут быть заданы как значения параметра fn:
(defun map-el (fn xl) ; Поэлементное преобразование XL
; с помощью функции FN.
(cond ; Пока XL не пуст,
(xl (cons (funcall fn (car xl) )
; применяем FN как функцию к голове XL
(map-el fn (cdr xl))
; и переходим к продолжению списка,
) ) ) ) ; собирая результаты в новый список.
Примечание: – это аналог apply, не требующий заключения аргументов в общий список:
(APPLY (DEFUN Пара (x y) (CONS x y))
(QUOTE (A (B C))));=(A B C)
(FUNCALL (DEFUN Пара (x y) (CONS x y))
(QUOTE A)
(QUOTE (B C)));=(A B C)
Эффект функций next, 1st и lens можно получить выражениями:
(map-el #'1+ xl) ;следующие числа (map-el #'car xl) ;"головы" элементов = CAR
#’ x ;= (FUNCTION x) - сокращенное обозначение функции-значения соответственно.
(map-el #'length xl) ; Длины элементов
(map-el #'1+ '(1 2 5 )) ; = (2 3 6 )
(map-el #'car '
((один два)(one two)(1 2)));=(один one 1)
(map-el #'length '((1 2)()(a b c d)(1(a b c d)3)))
; = (2 0 4 3 )
Эти определения функций формально эквивалентны ранее приведенным – они сохраняют отношение между аргументами и результатами.
Все три примера можно решить с помощью таких
(defun next (xl) (map-el #'1+ xl ))
; Очередные числа:
(defun 1st (xl) (map-el #'car xl ))
; "головы" элементов = CAR
(defun lens (xl) (map-el #'length xl ))
; Длины элементов
Параметром
(defun sqw (x) (* x x)); Возведение числа в квадрат (sqw 3) ; = 9
Построить список квадратов чисел, используя функцию sqw:
(defun sqware (xl) ; ; Возведение списка чисел в квадрат
(cond ; Пока аргумент не пуст,
(xl (cons (sqw (car xl))
; применяем sqw к его голове
(sqware (cdr xl))
; и переходим к хвосту списка,
) ) ) ) ; собирая результаты в список
(sqware '(1 2 5 7 )); = (1 4 25 49 )
Можно использовать map-el:
(defun sqware (xl) (map-el #'sqw xl))
Ниже приведено определение функции sqware- без вспомогательной функции, выполняющее умножение непосредственно. Оно влечет двойное вычисление (CAR xl), т.е. такая техника не вполне эффективна:
(defun sqware- (xl)
(cond
(xl (cons (* (car xl) (car xl) ); квадрат головы
; вычислять приходится дважды
(sqware- (cdr xl))
) ) ) )
(defun tuple (x) (cons x x))
(tuple 3) ; = (3 . 3)
(tuple 'a) ; = (a . a)
(tuple '(Ха))
; = ((Ха).(Ха))=((Ха)Ха)-это одно и то же!
Чтобы преобразовать элементы списка с помощью такой функции, пишем сразу:
(defun duble (xl) (map-el #'tuple xl))
; дублирование элементов
(duble '(1(a)()));=((1.1)((a)a)(()))
Немногим сложнее организовать
(defun pairl (al vl); Ассоциативный список
(cond ; Пока AL не пуст,
(al (cons (cons (car al) (car vl))
; строим пары из "голов".
(pairl (cdr al) (cdr vl))
; Если VL исчерпается,
; то CDR будет давать NIL
) ) ) )
(pairl '(один два two three) '(1 2 два три))
; = ((один . 1)(два . 2)(two два )(three три ))
(defun map-comp (fn al vl) ; fn покомпонентно применить
; к соответственным элементам AL и VL
(cond
(xl (cons (funcall fn (car al) (car vl))
; Вызов данного FN как функции
(map-comp (cdr al) (cdr vl))
) ) ) )
Теперь покомпонентные действия над векторами, представленными с помощью списков, полностью в наших руках. Вот списки и сумм, и произведений, и пар, и результатов проверки на совпадение:
(map-comp #'+ '(1 2 3) '(4 6 9))
; = (5 8 12 ) - Суммы
(map-comp #'* '(1 2 3) '(4 6 9))
; = (4 12 27)-Произведения
(map-comp #'cons '(1 2 3) '(4 6 9))
; = ((1.4)(2.6)(3.9))-Пары
(map-comp #'eq '(4 2 3 ) '(4 6 9))
; = (T NIL NIL)-Сравнения
Достаточно уяснить, что надо делать с элементами списка, остальное делает отображающий map-comp.
(defun mapf (fl el)
(cond ; Пока первый аргумент не пуст,
(fl (cons (funcall (car fl) el)
; применяем очередную функцию
; ко второму аргументу
(mapf (cdr fl) el)
; и переходим к остальным функциям,
) ) ) ) ; собирая их результаты в общий список
(mapf '(length car cdr)'(a b c d));=(4 a(b c d))
Композициями таких
Определения в примерах 4 и 5 не вполне удобны по следующим причинам:
duble и sqwure встречаются имена специально определенных вспомогательных функций.С одной стороны последнее противоречит пониманию смысла именования как техники, обеспечивающей неоднократность применения поименованного объекта. С другой стороны придумывать хорошие, долго сохраняющие понятность и соответствие цели, имена - задача нетривиальная.
Учитывая это, было бы удобнее вспомогательные определения вкладывать непосредственно в определения целевых функций и обходиться при этом вообще без имен. Конструктор функций lambda обеспечивает такой стиль построения определений. Этот конструктор любое выражение expr превращает в функцию с заданным списком аргументов (x1 ... xK) в форме так называемых lambda-выражений:
( lambda (x1 ... xK) expr )
Имени такая функций не имеет, поэтому может быть применена лишь непосредственно. Defun использует этот конструктор, но, кроме того, дает функциям имена.
(defun sqware (xl)(map-el(lambda(x)(* x x))xl)) (defun duble (xl)(map-el(lambda(x)(cons x x))xl))
Любую систему взаимосвязанных функций можно преобразовать к одной функции, используя вызовы
Вызовы
Композиции
(defun decart (x y)
(map-el #'(lambda (i)
(map-el #'(lambda (j) (list i j))
y)
) x) )
Но результат вызова
(decart '(a s d) '( e r t))
дает
(((A E)(A R)(A T))((S E)(S R)(S T))((D E)(D R)(D T)))
вместо ожидаемого
((A E)(A R)(A T)(S E)(S R)(S T)(D E)(D R)(D T))
Дело в том, что map-el, как и map-comp (пример 7), собирает результаты cons так, что каждый результат функции образует отдельный элемент.
А по смыслу задачи требуется, чтобы список был одноуровневым.
Посмотрим, что получится, если вместо cons при сборе результатов воспользоваться функцией append.
(defun list-ap (ll)
(cond
(ll (append (car ll)
(list-ap (cdr ll) )
) ) ) )
(list-ap '((1 2)(3 (4)))); = (1 2 3 (4))
Тогда по аналогии можно построить определение фукнционала map-ap:
(defun map-ap (fn ll)
(cond
(ll (append (fn (car ll) )
(map-ap fn (cdr ll) )
) ) ) )
(map-ap 'cdr '((1 2 3 4)(2 4 6 8)( 3 6 9 12)))
; = (2 3 4 4 6 8 6 9 12)
Следовательно, интересующая нас форма результата может быть получена:
(defun decart (x y)
(map-ap #'(lambda (i)
(map-el #'(lambda (j) (list i j))
y) ) x) )
(decart '(a s d) '( e r t))
;=((A E)(A R)(A T)(S E)(S R)(S T)(D E)(D R)(D T))
Соединение результатов append обладает еще одним полезным свойством: при таком сцеплении исчезают вхождения пустых списков в результат. А в Лиспе пустой список используется как ложное значение, следовательно такая схема
(defun heads (xl) (map-ap
#'(lambda (x)(cond (x (cons (car x) NIL))))
; временно голова размещается в список,
; чтобы потом списки сцепить
xl
) )
(heads '((1 2)()(3 4)()(5 6))) ;=(1 3 5)
Рассмотрим еще один типичный вариант применения
(defun sum-el ( xl)
(cond ((null xl) 0)
(xl (+ (car xl)
(sum-el (cdr xl) )
) ) ) )
(sum-el '(1 2 3 4 ) ) ; = 10
Перестроим определение, чтобы вместо " + " можно было использовать произвольную бинарную функцию:
(defun red-el (fn xl)
(cond ((null xl) 0)
(xl (funcall fn (car xl)
(red-el fn (cdr xl) ) ))))
(red-el '+ '(1 2 3 4 ) ) ; = 10
В какой-то мере map-ap ведет себя как
Такие формулы удобны при моделировании множеств, графов и металингвистических формул, а к их обработке сводится широкий класс задач не только в информатике.
| (Mapc Функция Список … ) | Отображает ряд списков с помощью Функции. Число списков должно соотвествовать числу аргументов Функции. Возвращает первый аргумент. |
| (Mapcan Функция Список … ) | Отображает ряд списков с помощью Функции, прменяемой к элементам списков. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции, полученный с помощью nconc. |
| (Mapcar Функция Список … ) | Отображает ряд списков с помощью Функции, прменяемой к элементам списков. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции. |
| (Mapcon Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции, полученный с помощью nconc. |
| (Mapl Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает первый аргумент. |
| ( Maplist Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции. |
При определении
При обходе структуры, представляющей множество,
Ответ на каждый из таких вопросов может быть дан в виде отдельной функции или
Таким образом, определение
Любую информацию можно представить символьными выражениями. В качестве основных видов символьных выражений выбраны списки и атомы. Атом - неделимое данное, представляющее информацию произвольной природы. Но во многих случаях знание природы информации дает более четкое понимание особенностей изучаемых механизмов.
Программирование работы с числами и строками – привычная, хорошо освоенная область информационной обработки, удобная для оценки преимуществ использования
1 -123 9876543210000000000000123456789
Можно работать с дробными и вещественными числами:
8/12 ;= 2/3 3.1415926
Строки заключаются в обычные двойные кавычки:
"строка любой длины, из произвольных символов, включая все что угодно"
Со строками можно при необходимости работать посимвольно, хотя они рассматриваются как атомы.
(string-equal "строка 1" " строка1");=Nil (ATOM "a+b-c") ;= T (char "стр1" 4 ) ;= "1"
Список - составное данное, первый элемент которого может рассматриваться как функция, применяемая к остальным элементам, также представленным как символьные выражения.
Это относится и к операциям над числами и строками.
Большинство операций над числами при префиксной записи естественно рассматривать как мультиоперации от произвольного числа аргументов.
(+ 1 2 3 4 5 6) ;= 21 (- 12 6 3) ;= 3 (/ 3 5) ;= 3/5
Любое данное можно превратить в константу, поставив перед ним "'" апостроф. Это эквивалентно записи со специальной функцией " QUOTE ". Для чисел и строк в этом нет необходимости, но это не запрещено:
'1 ;= 1 '"abc" ;= "abc"
Отказ от барьера между представлениями функций и значений дает возможность символьные выражения использовать как для изображения заданных значений, включая любые структуры над числами и строками, так и для определения функций, обрабатывающих любые данные. (Напоминаем, что определение функции - данное.)
Функционалы - это функции, которые используют в качестве аргументов или результатов другие функции. При построении
| (= Число … ) | Истина, если разница между любыми двумя аргументами равна нулю |
| (/= Число … ) | Истина, если никакие два аргумента не равны между собой |
| (> Число … ) | Истина, если каждый аргумент превышает прешественника |
| (< Число … ) | Истина, если каждый аргумент меньше прешественника |
| (<= Число … ) | Истина, если каждый аргумент меньше или равен прешественнику |
| (>= Число … ) | Истина, если каждый аргумент превышает или равен прешественнику |
| (* Число … ) | Произведение произвольного числа аргументов. 1 при их отсутствии. |
| (+ Число … ) | Сумма произвольного числа аргументов. 0 при их отсутствии. |
| (- Число … ) | Эквивалентно расстановке минусов между аргументами, т.е. (- a b c ) = a – b – c |
| (/ Число … ) | Первое число делится на произведение остальных, среди которых не должно быть нуля. |
| (1+ Число ) | ( + Число 1) |
| (1- Число ) | ( - Число 1) |
| (Boole Операция Целое1 Целое2 ) | Вычисляет результат применеия побитовой Операции к двум Целым. |
| ( |
Наибольший общий делитель. Ноль без аргументов. |
| ( |
Наименьшее общее произведение, 1 при отсутствии аргументов. |
| (min Число …) | |
| (max Число …) |
Рассмотрим технику использования
(defun next (xl) ; Следующие числа:
(cond ; пока список не пуст
(xl (cons (1+ (car xl)) ; прибавляем 1 к его голове
(next (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(next '(1 2 5 )) ; = (2 3 6 )
(defun 1st (xl) ; "головы" элементов = CAR
(cond ; пока список не пуст
(xl (cons (caar xl) ; выбираем CAR от его головы
(1st (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(1st '((один два )(one two )(1 2 )) ) ; = (один one 1)
(defun lens (xl) ; Длины элементов
(cond ; Пока список не пуст
(xl (cons (length (car xl)); вычисляем длину его головы
(lens (cdr xl)) ; и переходим к остальным,
) ) ) ) ; собирая результаты в список
(lens '((1 2 ) () (a b c d ) (1 (a b c d ) 3 )) ) ; = (2 0 4 3 )
Внешние отличия в записи этих трех функций малосущественны, что позволяет ввести более общую функцию map-el, в определении которой имена " car ", " 1+ " и " length " могут быть заданы как значения параметра fn:
(defun map-el (fn xl) ; Поэлементное преобразование XL
; с помощью функции FN.
(cond ; Пока XL не пуст,
(xl (cons (funcall fn (car xl) )
; применяем FN как функцию к голове XL
(map-el fn (cdr xl))
; и переходим к продолжению списка,
) ) ) ) ; собирая результаты в новый список.
Примечание: – это аналог apply, не требующий заключения аргументов в общий список:
(APPLY (DEFUN Пара (x y) (CONS x y))
(QUOTE (A (B C))));=(A B C)
(FUNCALL (DEFUN Пара (x y) (CONS x y))
(QUOTE A)
(QUOTE (B C)));=(A B C)
Эффект функций next, 1st и lens можно получить выражениями:
(map-el #'1+ xl) ;следующие числа (map-el #'car xl) ;"головы" элементов = CAR
#’ x ;= (FUNCTION x) - сокращенное обозначение функции-значения соответственно.
(map-el #'length xl) ; Длины элементов
(map-el #'1+ '(1 2 5 )) ; = (2 3 6 )
(map-el #'car '
((один два)(one two)(1 2)));=(один one 1)
(map-el #'length '((1 2)()(a b c d)(1(a b c d)3)))
; = (2 0 4 3 )
Эти определения функций формально эквивалентны ранее приведенным – они сохраняют отношение между аргументами и результатами.
Все три примера можно решить с помощью таких
(defun next (xl) (map-el #'1+ xl ))
; Очередные числа:
(defun 1st (xl) (map-el #'car xl ))
; "головы" элементов = CAR
(defun lens (xl) (map-el #'length xl ))
; Длины элементов
Параметром
(defun sqw (x) (* x x)); Возведение числа в квадрат (sqw 3) ; = 9
Построить список квадратов чисел, используя функцию sqw:
(defun sqware (xl) ; ; Возведение списка чисел в квадрат
(cond ; Пока аргумент не пуст,
(xl (cons (sqw (car xl))
; применяем sqw к его голове
(sqware (cdr xl))
; и переходим к хвосту списка,
) ) ) ) ; собирая результаты в список
(sqware '(1 2 5 7 )); = (1 4 25 49 )
Можно использовать map-el:
(defun sqware (xl) (map-el #'sqw xl))
Ниже приведено определение функции sqware- без вспомогательной функции, выполняющее умножение непосредственно. Оно влечет двойное вычисление (CAR xl), т.е. такая техника не вполне эффективна:
(defun sqware- (xl)
(cond
(xl (cons (* (car xl) (car xl) ); квадрат головы
; вычислять приходится дважды
(sqware- (cdr xl))
) ) ) )
(defun tuple (x) (cons x x))
(tuple 3) ; = (3 . 3)
(tuple 'a) ; = (a . a)
(tuple '(Ха))
; = ((Ха).(Ха))=((Ха)Ха)-это одно и то же!
Чтобы преобразовать элементы списка с помощью такой функции, пишем сразу:
(defun duble (xl) (map-el #'tuple xl))
; дублирование элементов
(duble '(1(a)()));=((1.1)((a)a)(()))
Немногим сложнее организовать
(defun pairl (al vl); Ассоциативный список
(cond ; Пока AL не пуст,
(al (cons (cons (car al) (car vl))
; строим пары из "голов".
(pairl (cdr al) (cdr vl))
; Если VL исчерпается,
; то CDR будет давать NIL
) ) ) )
(pairl '(один два two three) '(1 2 два три))
; = ((один . 1)(два . 2)(two два )(three три ))
(defun map-comp (fn al vl) ; fn покомпонентно применить
; к соответственным элементам AL и VL
(cond
(xl (cons (funcall fn (car al) (car vl))
; Вызов данного FN как функции
(map-comp (cdr al) (cdr vl))
) ) ) )
Теперь покомпонентные действия над векторами, представленными с помощью списков, полностью в наших руках. Вот списки и сумм, и произведений, и пар, и результатов проверки на совпадение:
(map-comp #'+ '(1 2 3) '(4 6 9))
; = (5 8 12 ) - Суммы
(map-comp #'* '(1 2 3) '(4 6 9))
; = (4 12 27)-Произведения
(map-comp #'cons '(1 2 3) '(4 6 9))
; = ((1.4)(2.6)(3.9))-Пары
(map-comp #'eq '(4 2 3 ) '(4 6 9))
; = (T NIL NIL)-Сравнения
Достаточно уяснить, что надо делать с элементами списка, остальное делает отображающий map-comp.
(defun mapf (fl el)
(cond ; Пока первый аргумент не пуст,
(fl (cons (funcall (car fl) el)
; применяем очередную функцию
; ко второму аргументу
(mapf (cdr fl) el)
; и переходим к остальным функциям,
) ) ) ) ; собирая их результаты в общий список
(mapf '(length car cdr)'(a b c d));=(4 a(b c d))
Композициями таких
Определения в примерах 4 и 5 не вполне удобны по следующим причинам:
duble и sqwure встречаются имена специально определенных вспомогательных функций.С одной стороны последнее противоречит пониманию смысла именования как техники, обеспечивающей неоднократность применения поименованного объекта. С другой стороны придумывать хорошие, долго сохраняющие понятность и соответствие цели, имена - задача нетривиальная.
Учитывая это, было бы удобнее вспомогательные определения вкладывать непосредственно в определения целевых функций и обходиться при этом вообще без имен. Конструктор функций lambda обеспечивает такой стиль построения определений. Этот конструктор любое выражение expr превращает в функцию с заданным списком аргументов (x1 ... xK) в форме так называемых lambda-выражений:
( lambda (x1 ... xK) expr )
Имени такая функций не имеет, поэтому может быть применена лишь непосредственно. Defun использует этот конструктор, но, кроме того, дает функциям имена.
(defun sqware (xl)(map-el(lambda(x)(* x x))xl)) (defun duble (xl)(map-el(lambda(x)(cons x x))xl))
Любую систему взаимосвязанных функций можно преобразовать к одной функции, используя вызовы
Вызовы
Композиции
(defun decart (x y)
(map-el #'(lambda (i)
(map-el #'(lambda (j) (list i j))
y)
) x) )
Но результат вызова
(decart '(a s d) '( e r t))
дает
(((A E)(A R)(A T))((S E)(S R)(S T))((D E)(D R)(D T)))
вместо ожидаемого
((A E)(A R)(A T)(S E)(S R)(S T)(D E)(D R)(D T))
Дело в том, что map-el, как и map-comp (пример 7), собирает результаты cons так, что каждый результат функции образует отдельный элемент.
А по смыслу задачи требуется, чтобы список был одноуровневым.
Посмотрим, что получится, если вместо cons при сборе результатов воспользоваться функцией append.
(defun list-ap (ll)
(cond
(ll (append (car ll)
(list-ap (cdr ll) )
) ) ) )
(list-ap '((1 2)(3 (4)))); = (1 2 3 (4))
Тогда по аналогии можно построить определение фукнционала map-ap:
(defun map-ap (fn ll)
(cond
(ll (append (fn (car ll) )
(map-ap fn (cdr ll) )
) ) ) )
(map-ap 'cdr '((1 2 3 4)(2 4 6 8)( 3 6 9 12)))
; = (2 3 4 4 6 8 6 9 12)
Следовательно, интересующая нас форма результата может быть получена:
(defun decart (x y)
(map-ap #'(lambda (i)
(map-el #'(lambda (j) (list i j))
y) ) x) )
(decart '(a s d) '( e r t))
;=((A E)(A R)(A T)(S E)(S R)(S T)(D E)(D R)(D T))
Соединение результатов append обладает еще одним полезным свойством: при таком сцеплении исчезают вхождения пустых списков в результат. А в Лиспе пустой список используется как ложное значение, следовательно такая схема
(defun heads (xl) (map-ap
#'(lambda (x)(cond (x (cons (car x) NIL))))
; временно голова размещается в список,
; чтобы потом списки сцепить
xl
) )
(heads '((1 2)()(3 4)()(5 6))) ;=(1 3 5)
Рассмотрим еще один типичный вариант применения
(defun sum-el ( xl)
(cond ((null xl) 0)
(xl (+ (car xl)
(sum-el (cdr xl) )
) ) ) )
(sum-el '(1 2 3 4 ) ) ; = 10
Перестроим определение, чтобы вместо " + " можно было использовать произвольную бинарную функцию:
(defun red-el (fn xl)
(cond ((null xl) 0)
(xl (funcall fn (car xl)
(red-el fn (cdr xl) ) ))))
(red-el '+ '(1 2 3 4 ) ) ; = 10
В какой-то мере map-ap ведет себя как
Такие формулы удобны при моделировании множеств, графов и металингвистических формул, а к их обработке сводится широкий класс задач не только в информатике.
| (Mapc Функция Список … ) | Отображает ряд списков с помощью Функции. Число списков должно соотвествовать числу аргументов Функции. Возвращает первый аргумент. |
| (Mapcan Функция Список … ) | Отображает ряд списков с помощью Функции, прменяемой к элементам списков. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции, полученный с помощью nconc. |
| (Mapcar Функция Список … ) | Отображает ряд списков с помощью Функции, прменяемой к элементам списков. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции. |
| (Mapcon Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции, полученный с помощью nconc. |
| (Mapl Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает первый аргумент. |
| ( Maplist Функция Список … ) | Отображает ряд списков с помощью Функции, применяемой к редуцируемым спискам. Число списков должно соотвествовать числу аргументов Функции. Возвращает список результатов Функции. |
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.