Как при помощи ф-ции mapcar обрабатывать сложные списки?

Автор Тема: Как при помощи ф-ции mapcar обрабатывать сложные списки?  (Прочитано 25078 раз)

0 Пользователей и 4 Гостей просматривают эту тему.

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
#9 lambda lambda ...   
мне показалось проще чем
#12 mapcar function lambda  ...  apply  function

если предположить, что проще это лучше то выбор за Димой #9
но в качестве ответа к вопросу темы больше подходит #12 от gomer

Оффлайн gomer

  • ADN OPEN
  • Сообщений: 4
  • Карма: 2
#9 lambda lambda ...   
мне показалось проще чем
#12 mapcar function lambda  ...  apply  function

если предположить, что проще это лучше то выбор за Димой #9
но в качестве ответа к вопросу темы больше подходит #12 от gomer


на самом деле
Код - Auto/Visual Lisp [Выбрать]
  1. (apply (function f)  (list x))
легко заменяется на
Код - Auto/Visual Lisp [Выбрать]
  1. (f x)
и функция выглядит совсем просто
Код - Auto/Visual Lisp [Выбрать]
  1. (defun tree-apply (f lst)
  2.   (mapcar (function
  3.             (lambda (x)
  4.               (if (listp x)
  5.                 (tree-apply f x)
  6.                 (f x))))
  7.           lst))

В классическом варианте это выглядит так
Код - Auto/Visual Lisp [Выбрать]
  1. (defun tree-apply (f lst)
  2.   (cond
  3.     ((null lst) nil)
  4.     ((listp (car lst))
  5.      (cons (tree-apply f (car lst))
  6.            (tree-apply f (cdr lst))))
  7.     (t
  8.      (cons (f (car lst))
  9.            (tree-apply f (cdr lst))))))
Код в #9 как раз и является танцами с бубном вокруг этой функции с целью уменьшить количество букаф
другой классический вариант выглядит так
Код - Auto/Visual Lisp [Выбрать]
  1. (defun tree-apply (f lst)
  2.   (cond
  3.     ((null lst) nil)
  4.     ((atom lst) (f lst))
  5.     (t
  6.      (cons (tree-apply f (car lst))
  7.            (tree-apply f (cdr lst))))))
Тоже достаточно простой
Вариант от Дима_ на самом деле достаточно сложен для понимания, но полезен для общего развития

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
gomer, спасибо за развернутые пояснения!
Проверил, все три ф-ции работают.

Но при наличии такого количества вариантов обработки сложных (структуризированных) списков возникает сл. вопросы.

1. Какой способ наиболее рациональный с точки зрения скорости выполнения?

2. В каких случаях целесообразнее использовать mapcar при обработке структуризированных списков если вполне можно обходиться без него?

3. В чем состоит особенность применения ATOM в последней ф-ции в отличии  от LISTP во всех предыдущих?



Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
В чем состоит особенность применения ATOM в последней ф-ции в отличии  от LISTP во всех предыдущих?
Проверяется тип передаваемого аргумента - атом или список.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
а атом, если я правильно понял из руководства,
это все то что не является списком

т.е. функция Atom - функция, обратная к LISTP
если Listp - проверка на список
то Atom - проверка  на "не список" т.е. атом

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
В каких случаях целесообразнее использовать mapcar при обработке структуризированных списков если вполне можно обходиться без него?
Да практически во всех. В автолиспе рекурсия очень "слабая" - нет "хвостовой" оптимизации, а в "стеке" хранит максимум на 20 тысяч "уровней" - то есть это только для самой простой "одноуровневой" рекурсивной структуры - например для создания списка - для более сложной в соответствующее кол-во раз меньше. Автолисп написан очень давно, когда байты и машинные такты еще приходилось считать - и задачи на него возлагались в более приземленном виде, а требование к "качеству" кода были выше. Если есть "большая" задача (и тут самое сложное заранее понять в каком измерении она может вылезти за разумные рамки автолиспа) автолиспом ее как правило реализовать-таки можно - но не эффективно - на него очень хорошо ложатся задачи до определенного уровня (быстро, просто и "красиво") - а сверх него - обрастает костылями сводя на нет все свои сильные стороны - а их не мало. Практически все "встроенные" функции написаны не на автолиспе (как это принято делать в "классических" лиспах), а являются менее высокоуровневыми скомпилированными структурами (хотя на момент создания автолиспа уже были эффективные трансляторы с лиспа - производительность которых не уступала, но автодеск пошел по более простому и менее затратному, но в конечном счете тупиковому пути).

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
В каких случаях целесообразнее использовать mapcar при обработке структуризированных списков если вполне можно обходиться без него?
Да практически во всех...

Дима, тогда получается, что лучшим на данный момент является решение от gomer  в  #12?

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
Я думаю, что самым лучшим решением будет то, которое понятно. Скорость выполнения (мне кажется) будет сейчас далеко не на первом месте в перечне критериев выбора.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
Алексей, по поводу скорости согласен, сейчас она далеко не на первом месте...
Вероятнее всего с ней можно будет поразбираться если программа будет медленно работать из-за больших объемов данных.

В дальнейшем все таки постараюсь разобраться во всех представленных решениях, чтобы было понятно...

Ни одно из решений не подошло для обработки данных вида -
(
  (набор1 характеристика3)
  (набор1 характеристика12)
  (
     (набор2 характеристика1)
     (набор2 характеристика3)
     (набор3 характеристика1)
  )
  ...
)

т.к. конечным элементом для обработки является список а не атом

попробовал подкорректировать одну из ф-ций  #16 (пока более понятную)
вроде получилось -
Код - Auto/Visual Lisp [Выбрать]
  1. (defun tree-apply (f lst)
  2.   (cond
  3.     ((null lst) nil)
  4.    
  5.     (
  6.       (= (type (car lst)) 'STR)
  7.       (cons (f (read(car lst)))
  8.            (tree-apply f (cdr lst)))
  9.     )
  10.    
  11.     ((listp (car lst))
  12.      (cons (tree-apply f (car lst))
  13.            (tree-apply f (cdr lst))))
  14.     (t
  15.      (cons (f (car lst))
  16.            (tree-apply f (cdr lst))))))
  17.  
  18.  
  19.  
  20. ;пример 1
  21. (defun d (a)  (+ 10 a))
  22. (setq lst '(1 2 3 (4 5 6) ((7 8 9) (10 11 12))))
  23. (tree-apply d lst)
  24. (11 12 13 (14 15 16) ((17 18 19) (20 21 22)))
  25.  
  26. ;пример 2
  27. (defun d1 (a)  (+ 100 (car a)(cadr a)))
  28. (setq lst1 '("(1 1)" "(2 2)" "(3 3)" ("(4 4)" "(5 5)" "(6 6)") (("(7 7)" "(8 8)" "(9 9)") ("(10 10)" "(11 11)" "(12 12)"))))
  29. (tree-apply d1 lst1)
  30. (102 104 106 (108 110 112) ((114 116 118) (120 122 124)))
  31.  
« Последнее редактирование: 22-02-2015, 00:20:48 от Юрий Ананьев »

Отмечено как Решение Юрий Ананьев 22-02-2015, 00:17:07

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
Подкорректировал функцию от gomer из #16, использующую mapcar lambda
Код - Auto/Visual Lisp [Выбрать]
  1. (defun tree-apply (f lst)
  2.   (mapcar
  3.     '(lambda (x)
  4.        (cond
  5.          ((null lst) nil)
  6.          ((=(type x)'STR) (f(read x)))
  7.          ((atom x)(f x))
  8.          (t(tree-apply f x))
  9.        );cond
  10.      )
  11.      lst)
  12. );defun
  13.  
  14. ;пример 1
  15. (defun d (a)  (+ 10 a))
  16. (setq lst '(1 2 3 (4 5 6) ((7 8 9) (10 11 12))))
  17. (tree-apply d lst)
  18. (11 12 13 (14 15 16) ((17 18 19) (20 21 22)))
  19.  
  20. ;пример 2
  21. (defun d1 (a)  (+ 100 (car a)(cadr a)))
  22. (setq lst1 '("(1 1)" "(2 2)" "(3 3)" ("(4 4)" "(5 5)" "(6 6)") (("(7 7)" "(8 8)" "(9 9)") ("(10 10)" "(11 11)" "(12 12)"))))
  23. (tree-apply d1 lst1)
  24. (102 104 106 (108 110 112) ((114 116 118) (120 122 124)))
  25.  

на ней пока и решил остановиться в качестве решения
« Последнее редактирование: 22-02-2015, 12:04:37 от Юрий Ананьев »

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
Подкорректировал Димину функцию  из #9, использующую lambda lambda cons

Код - Auto/Visual Lisp [Выбрать]
  1. (defun map-rec(fn lst)
  2.   (
  3.     (lambda (frec) (frec lst))
  4.     (lambda (lst)
  5.       (if lst
  6.          (cons
  7.            (
  8.              (if
  9.                (listp (car lst))
  10.                 frec
  11.                 fn
  12.              );if
  13.              (if
  14.                 (=(type (car lst))'STR)
  15.                 (read (car lst))
  16.                 (car lst)
  17.              );if
  18.            )
  19.            (frec (cdr lst))
  20.          ); cons
  21.       );if
  22.     );lambda
  23.   )
  24. );defun
  25.  
  26. ;пример 1
  27. (defun d (a)  (+ 10 a))
  28. (setq lst '(1 2 3 (4 5 6) ((7 8 9) (10 11 12))))
  29. (map-rec d lst)
  30. (11 12 13 (14 15 16) ((17 18 19) (20 21 22)))
  31.  
  32. ;пример 2
  33. (defun d1 (a)  (+ 100 (car a)(cadr a)))
  34. (setq lst1 '("(1 1)" "(2 2)" "(3 3)" ("(4 4)" "(5 5)" "(6 6)") (("(7 7)" "(8 8)" "(9 9)") ("(10 10)" "(11 11)" "(12 12)"))))
  35. (map-rec d1 lst1)
  36. (102 104 106 (108 110 112) ((114 116 118) (120 122 124)))
  37.  

% понимания растет )))
« Последнее редактирование: 22-02-2015, 12:04:10 от Юрий Ананьев »

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Если придираться - то проверка в строке 14 частично избыточна с строкой 9 (если ((car)lst) список - то он точно не строка*) - да так в общем можно делать - но если идет процесс увеличения "% понимания", то желательно, хотя-бы в целях самообразования подумать как это лучше исправить.

* хотя в некоторых диалектах функциональных языков строка представлена как последовательность символов.

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
Если придираться - то проверка в строке 14 частично избыточна с строкой 9 (если ((car)lst) список - то он точно не строка*) - да так в общем можно делать - но если идет процесс увеличения "% понимания", то желательно, хотя-бы в целях самообразования подумать как это лучше исправить.

Подумать подумал ))
но безрезультатно (
Справиться с частичной избыточностью строки 14 так и не смог ((



Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
ну главное процесс...
Код - Auto/Visual Lisp [Выбрать]
  1. (defun map-rec(fn lst)
  2.   (
  3.     (lambda (frec) (frec lst))
  4.     (lambda (lst)
  5.       (if lst
  6.       (cons (if (listp (car lst))
  7.                 (frec (car lst))
  8.                 (fn (if (=(type (car lst))'STR)
  9.                         (read (car lst))
  10.                         (car lst))))
  11.             (frec (cdr lst)))
  12.       );if
  13.     );lambda
  14.   )
  15. );defun
а ведь еще есть cond...

Оффлайн Юрий АнаньевАвтор темы

  • ADN Club
  • Сообщений: 21
  • Карма: 1
  • Skype: ananiev-yuriy
Дима, спасибо, теперь понятно.

А с использованием cond похоже будет так -

Код - Auto/Visual Lisp [Выбрать]
  1. (defun map-rec(fn lst)
  2.   (
  3.     (lambda (frec) (frec lst))
  4.     (lambda (lst)
  5.      (if lst
  6.       (cons
  7.             (cond
  8.                 ((listp (car lst))   (frec (car lst)))
  9.                 ((=(type (car lst))'STR) (fn(read (car lst))))
  10.                 (t (fn (car lst)))
  11.             );cond         
  12.             (frec (cdr lst))
  13.       );cons
  14.      );if
  15.     );lambda
  16.   )
  17. );defun
  18.  
  19.