| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Сброс переменных: глобальные переменные vs error handling

Сброс переменных: глобальные переменные vs error handling

Ответ
Поиск в этой теме
Непрочитано 25.01.2021, 21:28 #1
Сброс переменных: глобальные переменные vs error handling
Browning Zed
 
Регистрация: 17.01.2014
Сообщений: 97

Всем привет. Пытаюсь на данный момент выработать для себя стратегию, каким образом лучше всего возвращать переменные к их исходному состоянию. Помимо самого простого и очевидного:
(setq OldVar (getvar ...) (progn ...) (setvar ... OldVar)
существует два подхода:
1. Определить глобальную переменную со списком нужных нам переменных в одной функции, и вернуть исходное состояние переменных через другую функцию, что-то в духе:
Код:
[Выделить все]
 (defun get-defin-sysvar (set_sysvar ext_sysvar_list) 
	(setq *sysvar-list* (append '(CLAYER CECOLOR CELTYPE CELWEIGHT PLINEWID) ext_sysvar_list))
	(setq *sysvar-value* (mapcar 'GetVar *sysvar-list*))
	(if set_sysvar (mapcar 'SetVar (cdr *sysvar-list*) '("ByLayer" "ByLayer" -1 0)))
)
(defun res-defin-sysvar ()
	(if	*sysvar-list* (mapcar 'SetVar *sysvar-list* *sysvar-value*))
	(setq *sysvar-list* nil *sysvar-value* nil)
)
2. Либо возвращать переменные в исходное состояние через error handling, например, как это представлено здесь.
В связи с чем, у меня вопрос к гуру лиспа, и не только.
Какими методами пользуетесь лично вы? Какой подход более рационален? Если возможно, хотелось бы услышать мнение с аргументацией pro et contra.
Просмотров: 3170
 
Непрочитано 25.01.2021, 21:46
#2
Кулик Алексей aka kpblc
Moderator

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


Есть третий вариант. Как пример, который у меня существует уже много лет:
Код:
[Выделить все]
 
(defun sysvars-save (sysvar-list)
                    ;|
*    Переустановка / запоминание системных переменных
*    Параметры вызова:
  sysvar-list   ; список точечных пар "имя" "устанавливаемое значение". Если "устанавливаемое" пропущено,
                ; состояние переменной просто запоминается
*    Примеры вызова:
(sysvars-save '(("osmode" . 0) ("sysmon")))
|;
  (vl-remove nil
             (mapcar (function (lambda (x / temp)
                                 (if (setq temp (getvar (car x)))
                                   (progn (if (cdr x)
                                            (setvar (car x) (cdr x))
                                            (cons (car x) temp)
                                          ) ;_ end of if
                                   ) ;_ end of progn
                                 ) ;_ end of if
                               ) ;_ end of lambda
                     ) ;_ end of function
                     sysvar-list
             ) ;_ end of mapcar
  ) ;_ end of vl-remove
) ;_ end of defun

(defun sysvars-restore (sysvar-list)
                       ;|
*    Восстановление системных переменных
*    Параметры вызова:
  sysvars-save  ; список точечных пар "имя" "исходное значение"
*    Примеры вызова:
(setq lst (sysvars-save '(("osmode" . 0) ("sysmon"))))
;; some code
(sysvars-restore lst)
|;
  (foreach item sysvar-list (setvar (car item) (cdr item)))
) ;_ end of defun
Ну и использование:
Код:
[Выделить все]
 (defun main-fun (/ sysvar_status err)
  (setq sysvar_status (sysvars-save '(("clayer" . "0")
                                      ("cecolor" . "bylayer")
                                      ("celtype" . "bylayer")
                                      ("osmode" . 0)
                                      ("sysmon" . 0)
                                      ("cmdecho" . 0)
                                     )
                      ) ;_ end of sysvars-save
  ) ;_ end of setq
  ;; опасный код
  (if (vl-catch-all-error-p (setq err (vl-catch-all-apply (function (lambda () (/ 50 0.))))))
    (princ (strcat "\nError : " (vl-catch-all-error-message err)))
  ) ;_ end of if
  (sysvars-restore sysvar_status)
  (princ)
) ;_ end of defun
Код не проверял, просто для иллюстрации. Как видно, глобальных переменных нет, и ошибки обрабатываются вполне себе достойно.
P.S. На будущее старайся не использовать глобальные переменные. Лично у меня это указатели на приложение ACAD, текущий документ, пространство модели документа - и, пожалуй, все. Хотя нет, вру - иногда приходится запоминать результаты длинных запросов к БД в глобальной переменной уровня документа (а то и приложения), но это не потоково, а достаточно редко и разово.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 25.01.2021, 22:13
#3
Browning Zed


 
Регистрация: 17.01.2014
Сообщений: 97


Алексей, спасибо за комментарий, код на досуге попробую поюзать. А в чем проблема частого использования глобальных переменных? Ну, помимо того, что имена переменных могут пересечься со всеми вытекающими (что, впрочем, решается назначением им каких-нибудь замысловатых имен)? Замусоривают память? Ну так вроде сейчас не девяностые годы, ОЗУ уже не мегабайтами измеряются, так ли актуальна проблема?
И все же, хотелось еще услышать твоё мнение об error handling. Насколько понимаю, ты его не котируешь?
Browning Zed вне форума  
 
Непрочитано 25.01.2021, 23:33
1 | #4
Кулик Алексей aka kpblc
Moderator

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


Почему не котирую? Очень активно. Просто помню о его старом ограничении - не больше 9 уровней вложенности (словил как-то на 2006, с тех пор стараюсь подобного избегать; повторять эксперимент не хочу).
На данный момент очень редко превышается 4 уровень - и то на кусках, которые реально могут вывалить ошибку и обрушить весь код.
С глобальными переменными у меня была оочень веселая ошибка - всего в одном месте вмесо pr написал pt (сократил, блин, prop / property), потом полдня искали причину некорректного поведения достаточно большого куска. С тех пор правило: короткие имена - только внутри анонимных функций, локальные переменные имеют внятные обозначения, глобальные переменные идут лесом. И каждая функция обязательно подвергается проверке через Ctrl+Alt+C.
P.S. Про переопределение *error* можешь даже не спрашивать Не пользуюсь уже лет 8, наверное (если не больше).
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 26.01.2021, 00:15
1 | #5
Петр-и-Алекс


 
Регистрация: 18.01.2021
Сообщений: 404


"В связи с чем, у меня вопрос к гуру лиспа, и не только.
Какими методами пользуетесь лично вы? Какой подход более рационален? Если возможно, хотелось бы услышать мнение с аргументацией pro et contra."
Сразу: я далеко не гуру. Просто в свое время (к концу 90х) написал ооочень много разных лиспов и в силу необходимости, и со скуки. Например, авто переводчики на аглицкий (с удаленным участием отдела переводов), разные анимации по типу "тараканы от курсора", редактор текстов пачкой собственных бигфонтов, всякое типа нынешнего спдс, автомат.заполнение весов спецификаций с генерацией "выборки стали" без ексел и не помню уж чего еще.
И все без vla-, до которого тогда не дорос. С литературой тогда был совсем швах.
Исключительно личный опыт, приобретенный методом тыка. При смене версий имел несколько раз засады из-за изменения состава и имен системных переменных, в том числе и досовских\виндовских. В какой то момент перегорел и послал это дело подальше.
Потому рекомендация: без крайней необходимости не общаться со средой системы.

Я считаю, что "любителям" лучше пользовать тот метод, который автору проще/понятнее. В моем случае это ваш первый. Лучше больше понятного кода, чем компактный код, но лишний напряг интеллекта.
А в принципе, если б не бросил, то приближался к решению Кулика.
---
Сейчас под финал вернулся, смотрю что актуально на сегодня. С печалью вижу, что "спецификация\выборка" актуально по сей день... Очень лень, но похоже реанимирую. Мне странно смотреть, как молодежь тыркает "формулы" в ячейки таблиц, когда у компа и так под носом все нужные данные..
Хорошо хоть "профили проката" реализовали в СПДСах, и то - прогресс.
А еще смотрю полная печаль в excel… с интерполяцией например. Я сейчас про анналы сайта.
Петр-и-Алекс вне форума  
 
Непрочитано 26.01.2021, 09:27
1 | #6
koMon


 
Блог
 
Регистрация: 26.09.2017
Сообщений: 1,678


Цитата:
Сообщение от Browning Zed Посмотреть сообщение
каким образом лучше всего возвращать переменные к их исходному состоянию
имхо
1) системные переменные лучше вообще не трогать, поскольку в своём большинстве они придуманы для разного поведения конкретной команды (группы команд) автокада.
2) использование командных методов в программировании на лиспе, при своей кажущейся простоте не есть правильно и тут логичнее всего юзать по-полной activex, который почти всегда позволяет с лёгкостью обойти системные переменные. хотя есть очевидные случаи, когда без них не обойтись, например если нужно что-то заштриховать.
3) использовать переопределение *error* - имхо полное кощунстсво, поскольку привязывает каждый код к этому переопределению, даже возможно тогда, когда это и не нужно. и последствия этого переопределения не очень желательны, когда что-то пошло не так. лучше использовать отлов ошибок опять же на activex.
koMon вне форума  
 
Автор темы   Непрочитано 26.01.2021, 16:32
#7
Browning Zed


 
Регистрация: 17.01.2014
Сообщений: 97


Кулик Алексей aka kpblc,
Спасибо, ситуация с глобальными переменными прояснилась. У меня, к сожалению, пока не получается отказаться от их использования, в силу крайне скудных, на данный момент, познаний в программировании вообще, и лиспе в частности. Приходится пользоваться чем знаю и что умею, а другие пути еще предстоит изучить. Сейчас приходится использовать достаточно много глобальных переменных в которых, как правило, сидят списки с определением различных стилей (текста, размеров, мультивыносок, таблиц), которые я, в случае необходимости, прогоняю через определенную функцию создания стиля. Профессиональные программисты, наверное, сочтут это за порочную практику.

Петр-и-Алекс, спасибо, за столь развернутый ответ. Метод проще и понятнее, имееется в виду (setq OldVar (getvar ...)) (progn ...) (setvar ... OldVar)? Но что, если в процессе выполнения кода случится ошибка (например, пользователь нажимает Esc)? Отката к исходному состоянию переменных в таком случае не происходит.

koMon, activex круто юзать, если умеешь конечно, но для меня это пока недостижимый хай-левел. На счет переопределения *error* усвоил – исключу, пожалуй, этот метод из практики на данном этапе. Спасибо за комментарий.
Browning Zed вне форума  
 
Непрочитано 26.01.2021, 16:56
#8
Кулик Алексей aka kpblc
Moderator

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


Если есть время и желание - советую найти "САПР на базе AutoCAD" (на форуме где-то лежит в достаточно хорошем качестве). Скачать, прочитать, попробовать применить.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 26.01.2021, 17:04
#9
Петр-и-Алекс


 
Регистрация: 18.01.2021
Сообщений: 404


Уважаемый, хочу обратить внимание на такое понятие из жизни программистов, как "выгорание". Это дело существует. Особенно оно ранит "любителей". В том числе и потому, что у них нет (как правило) поддержки административной.
Мой вам искренний совет:
- старайтесь сделать законченный продукт. Тот, который работает и решает поставленную задачу. Даже если Вы видите, что его "можно сделать много лучше", на первом этапе просто "достигните финиша". Потом будете шлифовать по мере возможностей.
- подумайте, как можно ввести работающий продукт в практику. Это не менее творческая задача. Если это не удается в желаемом масштабе - хотя бы опубликуйте здесь.
- при этом, имейте ввиду такие засады: работодатель может выразить неудовольствие тем, что вы вообще этим занимаетесь, ващей публикацией вне конторы.
- мне прилетало неудовольствие от самого автодеска… к примеру
Юридическая сторона подобного вида хобби тоже тема любопытная... больше сейчас говорить не буду
Но в любом случае, удачи Вам! и слегка завидую Вам в том, что Вы в начале этого пути
Петр-и-Алекс вне форума  
 
Непрочитано 26.01.2021, 17:32
#10
ShaggyDoc

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


Цитата:
Сообщение от Browning Zed Посмотреть сообщение
Профессиональные программисты, наверное, сочтут это за порочную практику.
Совсем без глобальных обойтись можно, но часто это слишком накладно. Если уж их использовать, то четко выделяя имена префиксами и регистром.

Цитата:
Сообщение от Browning Zed Посмотреть сообщение
много глобальных переменных в которых, как правило, сидят списки с определением различных стилей (текста, размеров, мультивыносок, таблиц), которые я, в случае необходимости, прогоняю через определенную функцию создания стиля
А вот тут как раз не надо глобальных. Если есть функция создания стиля или каких-то настроек, так эта функция может прочитать и установить необходимые значения как системных переменных, так и чего угодно, без создания глобальных переменных. А прочитать можно из разных мест, например из текстового файла, в котором можно менячть любые настройки не затрагивая тексты программ.

Но одну глобальную для сохранения и восстановления списка системных переменных использовать стоит. Это понадобится для обработки ошибок.

Цитата:
Сообщение от Browning Zed Посмотреть сообщение
activex круто юзать, если умеешь конечно, но для меня это пока недостижимый хай-левел.
Да никакого "хая там нет". Осваивается легко. От command надо уходить, тем более, что она становится несовместимой в разных версиях Автокада.

Но зато в active-x возможно сделать настоящий (в отличие от *error*) обработчик ошибок. Любых - хоть прерывание пользователем, хоть какие-то действия программы, вплоть до деления на ноль. Это аналог try.... except... end в "больших" языках.

Для этого имеются функции vl-catch-all-apply, vl-catch-all-error-p, vl-catch-all-error-message. Они работают в связке, для простоты применения их лучше обернуть в свою функцию наподобие


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

|;
  
  (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
  ) 
) 
Когда есть обработчик ошибок, то ваши программы смогут работать надежно даже без присутствия автора.

В результате в начале и конце любой функции-программы можно вставить собственную библиотечную функцию и навсегда забыть про обработку ошибок. Например у меня делается так:

Код:
[Выделить все]
 (defun МОЯ (/)

  (ru-app-begin)
;; делаем что угодно
    (ru-app-end)
  (princ)
)
И непременно надо формировать свою библиотеку функций, а не повторять все в программах.
ShaggyDoc вне форума  
 
Непрочитано 26.01.2021, 17:58
#11
Петр-и-Алекс


 
Регистрация: 18.01.2021
Сообщений: 404


ShaggyDoc - славно!
Петр-и-Алекс вне форума  
 
Непрочитано 26.01.2021, 19:22
#12
Кулик Алексей aka kpblc
Moderator

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


Цитата:
Сообщение от Петр-и-Алекс Посмотреть сообщение
ShaggyDoc - славно!
САПР на базе, все дела...
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 26.01.2021, 22:13
#13
Петр-и-Алекс


 
Регистрация: 18.01.2021
Сообщений: 404


Понял.
Тема в сторону: столько лет прошло, а то, что я вижу из-за плеча бойцов - никакого "сапра" нет... в массовом использовании по крайней мере.
Есть более менее актуальный кад + СПДС... Не таким мечталось будущее 20 лет назад.
Я про строительное проектирование на своей поляне. Надеюсь где то САПР существует. Впрочем, да, даже видел его в бою.
Петр-и-Алекс вне форума  
 
Непрочитано 27.01.2021, 08:49
#14
nickname2019


 
Регистрация: 18.11.2019
Сообщений: 1,513


Цитата:
Сообщение от Петр-и-Алекс Посмотреть сообщение
Понял.
Тема в сторону: столько лет прошло, а то, что я вижу из-за плеча бойцов - никакого "сапра" нет... в массовом использовании по крайней мере.
Если Вы подразумеваете под САПР готовое коробочное решение в котором "все есть", и которое не позволяет его настраивать под себя - это не сапр, это недоразумение.
Цитата:
Есть более менее актуальный кад + СПДС... Не таким мечталось будущее 20 лет назад.
Я про строительное проектирование на своей поляне. Надеюсь где то САПР существует. Впрочем, да, даже видел его в бою.
Какой САПР Вы имеете ввиду?
nickname2019 вне форума  
 
Непрочитано 27.01.2021, 09:49
#15
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,036


Offtop:
Цитата:
Сообщение от Петр-и-Алекс Посмотреть сообщение
столько лет прошло, а то, что я вижу из-за плеча бойцов - никакого "сапра" нет... в массовом использовании по крайней мере.
а откуда он может появиться, если софтверные компании подстраиваются под некую усредненную модель потребителя - чтобы "окучить" максимально возможное число потенциальных покупателей. Удобство пользования, стабильность работы приложения - все принесено в жертву прибыли. А сейчас уже на следующую стадию перешли - ищут волонтеров на практическое тестирование продукта) Ну а разрабатывают под себя (силами внутренних/приглашенных программистов либо одиночек-энтузиастов) ПО сейчас единицы - многие даже толковых проектировщиков не могут себе в штат набрать, какое там программирование. Так что так и будет набор костылей и надстроек для базовых рисовалок + некоторая часть проектировщиков в вертикальных решениях фигачат в меру своего разумения.
Сергей812 вне форума  
 
Непрочитано 27.01.2021, 14:01
#16
koMon


 
Блог
 
Регистрация: 26.09.2017
Сообщений: 1,678


Цитата:
Сообщение от ShaggyDoc Посмотреть сообщение
Да никакого "хая там нет".
абсолютно!

----- добавлено через ~1 мин. -----
Цитата:
Сообщение от Петр-и-Алекс Посмотреть сообщение
мне прилетало неудовольствие от самого автодеска
это как?!
koMon вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Сброс переменных: глобальные переменные vs error handling

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Самопроизвольно меняются значения системных переменных PRESELECTIONEFFECT и SELECTIONEFFECT Denger777 AutoCAD 2 14.05.2016 22:58
Выборка локальных переменных в функции wluk1958 Программирование 7 24.06.2012 05:58
Что за системные переменные plimmin и plimmax? Кулик Алексей aka kpblc AutoCAD 5 13.06.2012 10:20
Программно получить список системных переменных (без вывода в текстовый файл) Ax3 Программирование 3 27.12.2010 16:29
Значение переменных, "спрятанных" в чертеже Airiz Программирование 11 05.06.2007 17:53