lambda функция объясните понятно. - Страница 3
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > lambda функция объясните понятно.

lambda функция объясните понятно.

Ответ
Поиск в этой теме
Непрочитано 21.11.2012, 16:31
lambda функция объясните понятно.
Kirill_Ja
 
Мурманск
Регистрация: 28.07.2008
Сообщений: 208

Функция Lambda очень часто встречается в текстах кодов на форуме. У Николая Полещука в книге описана как функция для того, чтобы прямо в тексте программы определить и тут же выполнить пользовательскую функцию. В документации для разработчиков AutoCad тоже какой-то неочевидный и не очень понятный пример.

В общем как-то так.

Объясните понятно на примере как это и зачем именно определять функцию одноразового применения.
Просмотров: 15734
 
Непрочитано 27.12.2012, 20:00
#41
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,372


Цитата:
лучше написать свой нормальный *error*
Ну, попробуй напиши. Такую *error*, чтобы перехватывала ESC. Функция *error* срабатывает, когда уже "поздно пить боржоми". Т.е. когда ошибку уже не предотвратить, программа уже вылетает. Причем независимо от того, на каком уровне вложенных функций произошел вылет. Здесь можно только что-то мявкнуть, да что-то восстановить.

ESC для AutoLISP - "лом, против которого нет приема".

А ловушки ошибок действуют наподобие try... except ... end. vl-catch-all-ххх - наилучшая новинка в LISP за последние 10 лет. С их помощью можно предотвратить любую ошибку на любом уровне вложения.
ShaggyDoc вне форума  
 
Непрочитано 27.12.2012, 21:53
#42
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от ShaggyDoc Посмотреть сообщение
А ловушки ошибок действуют наподобие try... except ... end. vl-catch-all-ххх - наилучшая новинка в LISP за последние 10 лет.
Согласен, вот только такие ловушки напоминают комивояжера, который пока не продаст, не отстанет.
Цитата:
Сообщение от ShaggyDoc Посмотреть сообщение
ESC для AutoLISP - "лом, против которого нет приема".
ну это логично. Нажимаешь ты отмену, а тебе программа так ехидно
Цитата:
А может, все же, на балет?
С другой стороны, если программе не хватает данных, она правильно работать дальше не будет.
К тому же vl-catch-all-apply по барабану на ошибки command, например, при вставке блока
gomer вне форума  
 
Непрочитано 27.12.2012, 22:19
#43
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,372


Цитата:
Нажимаешь ты отмену, а тебе программа так ехидно
А это уже зависит от того, как автор напишет. Где-то можно разрешить, где-то нельзя. Об ошибках можно сообщать, а можно и не сообщать.
Цитата:
если программе не хватает данных, она правильно работать дальше не будет
Опять же зависит от программиста.

Цитата:
К тому же vl-catch-all-apply по барабану на ошибки command, например, при вставке блока
И это зависит от программиста. Исключительно. Применяется не одна функция, а связка из них, чтобы появился как бы try... except ...end, только на Lisp
ShaggyDoc вне форума  
 
Непрочитано 28.12.2012, 02:31
#44
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от ShaggyDoc Посмотреть сообщение
Опять же зависит от программиста.
если для вставки блока нужна точка масштаб и угол поворота, то без них блок вставить нельзя, не выдумывать же, это не правильно, более того, vl-catch-all-apply эту ситуацию не отловит, потому что command своя логика, да и вообще она с command работать не хочет, только с лямбдой
для примера
(vl-catch-all-apply '(lambda nil (command "_.insert" "d:\\test" pause 1 1 pause))) - ошибка при нажатии еск во время выбора угла поворота ловится
(vl-catch-all-apply '(lambda nil (command "_.insert" "d:\\test" pause))) - ошибка при нажатии еск во время выбора угла поворота не ловится
(vl-catch-all-apply 'command (list "_.insert" pause "d:\\test" pause 1 1 pause)) - ; ошибка: неверная порядковая функция: COMMAND
так что vl-catch-all-apply - не панацея
gomer вне форума  
 
Непрочитано 28.12.2012, 08:24
#45
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,372


Цитата:
vl-catch-all-apply - не панацея
Читай ещё раз:
Цитата:
Применяется не одна функция, а связка из них, чтобы появился как бы try... except ...end, только на Lisp
Эту связку я не раз приводил в пример.
Цитата:
(vl-catch-all-apply '(lambda nil (command "_.insert" "d:\\test" pause))) - ошибка при нажатии еск во время выбора угла поворота не ловится
Читай ещё раз:
Цитата:
А это уже зависит от того, как автор напишет...Опять же зависит от программиста
Всегда можно умудриться написать так, что работать не будет. Ловушки ставятся для ситуаций времени выполнения, а не для ловли ошибок в коде.

Однако, раз тема про lambda, приведу пример использования как раз в ловушке ошибок.
Сначала напишем саму функцию-ловушку.

Код:
[Выделить все]
 
(defun ru-error-catch (protected_expression on_error_expression / catch_error_result)
  (setq catch_error_result (vl-catch-all-apply protected_expression)) 
  (if (and (vl-catch-all-error-p catch_error_result) on_error_expression)
    (apply on_error_expression (list (vl-catch-all-error-message catch_error_result))) 
    catch_error_result
  )
)
Обратите внимание - используются три функции семейства vl-catch-all-

Как надо вызывать - схема:
Код:
[Выделить все]
 
(ru-error-catch
     ;;; Аналог try в других языках
    (function (lambda ()
                ;;; защищаемое выражение  , которое надо попробовать
                (
                
                )
                ;;; То что вернет - будет результатом
              ) 
    ) 
     ;;; Аналог  except  в других языках
	 ;;; что делать, если произошла ошибка
    (function
      (lambda (err_msg)
        ;; если надо - выводим сообщение. err_msg подставит Автокад
        (princ (strcat "\nОШИБКА такой-то функции: " err_msg))
        ;; возвращаем NIL при ошибке
        nil
      ) 
    )   
)

Обратите внимание - два раза используется lambda.

Конечно, "простому инженеру" (прикладному программисту), который механизирует свои типовые задачи, наподобие вставок блоков, с этим трудновато разобраться. Для упрощения работы прикладных программистов создаются библиотеки низкоуровневых функций, в которых спрятаны все сложности. А в конкретной программе (функции, конечно), навешиваемой "на кнопку", надо применять простые высокоуровневые функции. Надежные. Чтобы не писали муру наподобие (command "_.insert" "d:\\test" pause 1 1 pause) только потому что так проще.

Если уж упомянули блоки, то каждому надо вставлять, например, блоки условных обозначений. Причем надо, чтобы вставка блочишки была многократная, в цикле. Чтобы при этом блок "висел" на курсоре. Чтобы можно было задать поворот или не задавать. Чтобы блок ещё и масштабировался правильно. Чтобы могли быть атрибуты, а могли и не быть. И чтобы это можно было легко применить. Чтобы на уровне меню можно было написать:

Сантехнику: (ru-block-insert-from-lib "sanitary\\ru-lib-abok-schem-free-valves-ind" "abok_2_8_05_F-03" 1 1 1 nil))
Топографу: (ru-block-insert-from-lib "land\\ru-lib-topo" "ru_topo_0139" 1 1 1 T))
Строителю: (ru-block-insert-from-lib "common\\ru-lib-common" "number_door_ru" 1 1 1 T))

Здесь применяется библиотечная функция ru-block-insert-from-lib, которая объявлена так
(ru-block-insert-from-lib block_lib_name block_name ins_code x_scale y_scale is_angle0)
Она делает множественную вставку блока с заданными параметрами из библиотеки блоков. Эту функцию здесь не привожу для экономии места. Она внедряет в чертеж блок из библиотеки, вычисляет масштабы вставки и вызывает низкоуровневую функцию _ru-block-multi-insert-scaled-rotated-or-angleask с подготовленными параметрами. Вот её-то и покажу
Код:
[Выделить все]
 
(defun _ru-block-multi-insert-scaled-rotated-or-angleask 
(block_name  x_scale y_scale block_angle msg_insert msg_angle /   
old_attdia old_attreq  result is_angle_ok is_point_ok  do)
 (setq old_attdia (getvar "ATTDIA") old_attreq(getvar "ATTREQ")  do t)
 (setvar "ATTDIA" 0)
 (setvar "ATTREQ" 0)
 (ru-var-clear-insunit)
 (while do
  (ru-error-catch
   (function (lambda ()
              (princ (strcat "\n" msg_insert " или ESC для выхода: "))
              (setq is_point_ok
                    (vl-cmdf "_.INSERT"
                             block_name
                             "_PROTATE"
                             (if block_angle
                              block_angle
                              0
                             )
                             "_PXScale"
                             x_scale
                             "_PYScale"
                             y_scale
                             pause
                    )
              )
              (if is_point_ok
               (progn
                (vl-cmdf
                 x_scale
                 y_scale
                 (if (not block_angle)
                  (progn  (princ "\nУгол поворота <0>: ") pause)
                  block_angle
                 )
                )
                (ru-block-dlg-attedit (entlast))
               )
              )
              (setq do is_point_ok)
             )
   ) 
   nil
  ) 
 ) 
 (ru-var-restore-insunit)
 (setvar "ATTDIA"  old_attdia)
 (setvar "ATTREQ"  old_attreq)
 (princ)
)
Тут и ловушка ошибок есть, и обработка ESC - специально для прерывания цикла, но не для прерывания программы. Ну и lambda - тема ветки.
ShaggyDoc вне форума  
 
Непрочитано 28.12.2012, 09:01
#46
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,450


Касательно отлова ошибок - в свое время я пришел в выводу, что *error* лучше не переопределять (причины, в частности, рассматривал тут). Особенно при работе в вертикальных приложениях.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 31.12.2012, 11:14
#47
G-RAV

Геодезист
 
Регистрация: 16.08.2009
г.Новосибирск
Сообщений: 86
<phrase 1=


Объясните, пожалуйста, как с помощью Lambda получить максимальные и минимальные значения списка, т.е. есть список, например:
Код:
[Выделить все]
((22 12) (1 34) (56 -32) (0 12) (-4 12))
, а получить необходимо минимальное
Код:
максимальное
Код:
. С Foreach разобрался, а вот Lambda не поддается).
G-RAV вне форума  
 
Непрочитано 31.12.2012, 12:47
#48
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,839


Ну с помощью голой лямбда наверное никак, тебе непонятно как алгоритм реализовать, или алгоритм понятен но не получается выразить его через лямбда выражения?
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 31.12.2012, 12:53
#49
G-RAV

Геодезист
 
Регистрация: 16.08.2009
г.Новосибирск
Сообщений: 86
<phrase 1=


Через Лямбда не получается, а хотелось бы...
Через Foreach получилось как то вот так:
Код:
[Выделить все]
(foreach x myLIST
    (cond
    ((< (car x) Xmin) (setq Xmin (car x)))
    ((> (car x) Xmax) (setq Xmax (car x)))
    )
    (cond    
    ((< (cadr x) Ymin) (setq Ymin (cadr x)))
    ((> (cadr x) Ymax) (setq Ymax (cadr x)))
    )
  )
Наверное стоит добавить, что перед кодом стоит:
Код:
[Выделить все]
(SETQ Xmin (caar myLIST) Ymin (cadar myLIST) Xmax Xmin Ymax Ymin)

Последний раз редактировалось G-RAV, 02.01.2013 в 16:09.
G-RAV вне форума  
 
Непрочитано 31.12.2012, 15:13
1 | #50
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,450


Код:
[Выделить все]
 (setq lst '((22 12) (1 34) (56 -32) (0 12) (-4 12)))
(mapcar (function (lambda (f)
                    (apply (function min)
                           (mapcar
                             (function (lambda (x) (f x)))
                             lst
                             ) ;_ end of mapcar
                           ) ;_ end of apply
                    ) ;_ end of lambda
                  ) ;_ end of function
        (list car cadr)
        ) ;_ end of mapcar
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 31.12.2012, 17:55
1 | #51
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Сначала не понял, но потом понял, что думаю о том же. Мой вариант попроще:
Код:
[Выделить все]
 ((lambda (fpar lst)
   (mapcar
     (function
       (lambda (f)
	 (apply fpar (mapcar f lst))
       )
     )
     '(car cadr)
   )
 )
  'min
  '((22 12) (1 34) (56 -32) (0 12) (-4 12))
)
Вариант с foreach, но проще

Код:
[Выделить все]
 ((lambda (f lst / result)
   (setq result (car lst))
   (foreach x lst
     (setq result
	    (list
	      (f (car  result) (car  x))
	      (f (cadr result) (cadr x))
	    )
     )
   )
 )
  min
  '((22 12) (1 34) (56 -32) (0 12) (-4 12))
)

Последний раз редактировалось gomer, 31.12.2012 в 18:57.
gomer вне форума  
 
Непрочитано 02.01.2013, 17:13
#52
G-RAV

Геодезист
 
Регистрация: 16.08.2009
г.Новосибирск
Сообщений: 86
<phrase 1=


Большое спасибо за варианты. С последним разобрался, а вот с первым….
gomer, правильно ли я понял первый вариант? Все первые элементы подсписков объединяются в один список
Код:
[Выделить все]
(22 1 56 0 -4)
, все вторые элементы объединяются во второй список
Код:
[Выделить все]
(12 34 -32 12 12)
и уже в этих списках поиск минимальных значений?
G-RAV вне форума  
 
Непрочитано 02.01.2013, 20:37
#53
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от G-RAV Посмотреть сообщение
Все первые элементы подсписков объединяются в один список
Цитата:
Сообщение от G-RAV Посмотреть сообщение
все вторые элементы объединяются во второй список
Цитата:
Сообщение от G-RAV Посмотреть сообщение
и уже в этих списках поиск минимальных значений?
да, собственно первый вариант, проистекает из второго в два действия, важно понять, что точка отсчета функции - содание списка (list), просто mapcar это делает неявно, причем шиворот-навыворот
gomer вне форума  
 
Непрочитано 09.01.2013, 16:10
#54
G-RAV

Геодезист
 
Регистрация: 16.08.2009
г.Новосибирск
Сообщений: 86
<phrase 1=


А вот в этом случае, можно еще оптимальнее?
Код:
[Выделить все]
  ((lambda (str / rs)
(setq rs t i 0)
(foreach x (vl-string->list str)
(cond
((and(<= x 57)(>= x 48))t)
((and(= x 46)(= i 0))(setq i (1+ i)))
(t(setq rs nil))
))rs
)
"текст")
Проверяет является ли содержимое строки положительным числом (целым или вещественным) с точкой в качестве разделителя, если нет возвращает nil, если да t.
G-RAV вне форума  
 
Непрочитано 09.01.2013, 16:58
#55
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,839


Цитата:
Сообщение от G-RAV Посмотреть сообщение
можно еще оптимальнее
У Вас идет проверка всего списка - а достоточно закончить на первом неверном.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 09.01.2013, 16:58
#56
TararykovDG

Программист-энтузиаст
 
Регистрация: 17.07.2009
Воронеж
Сообщений: 575


Цитата:
Сообщение от G-RAV Посмотреть сообщение
А вот в этом случае, можно еще оптимальнее?
А при чем тут lambda?

На тему
Цитата:
Сообщение от G-RAV Посмотреть сообщение
Проверяет является ли содержимое строки положительным числом (целым или вещественным) с точкой в качестве разделителя, если нет возвращает nil, если да t.
{Конкурс} Lisp. Пребразование в число при возможности
__________________
cadtools
TararykovDG вне форума  
 
Непрочитано 09.01.2013, 17:08
#57
G-RAV

Геодезист
 
Регистрация: 16.08.2009
г.Новосибирск
Сообщений: 86
<phrase 1=


Цитата:
Сообщение от Дима_ Посмотреть сообщение
У Вас идет проверка всего списка - а достоточно закончить на первом неверном.
Спасибо.. Попробую додумать...

Цитата:
Сообщение от TararykovDG Посмотреть сообщение
А при чем тут lambda?
Дык.. а тема как называется? Разбераемся ж с lambda, а #54 просто в качестве примера..
За ссылку спасибо..
G-RAV вне форума  
 
Непрочитано 11.01.2013, 13:07
1 | #58
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


а я, для поиска минимального списка использую другую конструкцию:

Код:
[Выделить все]
 (setq l '((22 12) (1 34) (56 -32) (0 12) (-4 12)))
(apply (function mapcar) (cons (function min) l))
Правда в этой конструкции, лямбда только подразумевается...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Непрочитано 11.01.2013, 20:32
#59
gomer

строю, ломаю
 
Регистрация: 03.04.2008
Украина
Сообщений: 5,515


Цитата:
Сообщение от Елпанов Евгений Посмотреть сообщение
а я, для поиска минимального списка использую другую конструкцию:
однако следует помнить это
gomer вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > lambda функция объясните понятно.



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Научите лиспу на примере (или как kpblc, VVA и компания пытаются обучить чайника лиспу) Red Nova LISP 5025 20.08.2025 22:52
Выравнивание полилинии в одну линию. f0lk Программирование 50 13.03.2025 14:04
Растягивание Mtext по контуру замкнутой области PlayKid Программирование 7 27.08.2009 13:41
структурированный список Holon Программирование 22 11.09.2007 14:09