Область видимости, как ее игнорируют. И как лечить. Локальные и глобальные шутки.

Сегодня был очень интересный разговор, суть которого свелась к вопросу: "Если есть несколько кодов lsp от разных авторов, то как быть с повторением имен функций?" Действительно, в LISP нет (как бы) понятия public и private, но есть локальные функции и параметры. Честно говоря, я уже не помню, разговор был или нет про это дело. Но если был, то ничего страшного - слегка повторимся.

Сначала немного теории. Кто ее знает, ближайшие 5-6 абзацев могут спокойно пропускать.

Как известно, в lisp-функцию можно передавать какое-то количество параметров (подробнее см. О параметрах вызова и "перегрузке" фунций). Но существуют еще и т.н. локальные переменные. Они упоминаются в объявлении функции после знака слеша:

1
2
3
(defun ИмяФункции(ПараметрыФункции / ЛокальныеПеременныеФункции)
;;; <...>
  );_ end of defun

Чем хороши локальные элементы? Ну, хотя бы тем, что они уничтожаются после выхода из функции. Рассмотрим элементарный пример:

1
2
3
4
5
(defun test1 (/ x)
  (setq x "qwer")
  (princ (strcat "\n" x))
  (princ)
  ) ;_ end of defun

И тут же выполним:

1
2
3
4
5
6
7
8
_$ (setq x "1234")
"1234"
_$ (test1)

qwer
_$ x
"1234"
_$

Переменная х на момент вызова test1 равна "1234", внутри функции test1 новой переменной с тем же именем присваивается значение "qwer", а после выхода новая переменная уничтожается.

Точно так же можно оперировать не только с переменными, но и с функциями, задавая их область видимости. Подобный подход, например, показывался в Код без ошибок - возможно ли?.

Теперь теория кончилась, начинается практика :)

Допустим, у нас есть два кода от разных авторов. Первый:

1
2
3
4
5
6
7
(defun fun1 ()
  (aa "fun1")
  ) ;_ end of defun

(defun aa (name)
  (alert (strcat "aa from " name))
  ) ;_ end of defun

Второй:

1
2
3
4
5
6
7
(defun fun2 ()
  (aa "fun2" "test")
  ) ;_ end of defun

(defun aa (name param1)
  (alert (strcat "aa from " name ". " param1))
  ) ;_ end of defun

Видно, что функция aa в разных кодах имеет разное количество параметров. Что делать, как быть, если надо использовать и первый код, и второй? Ведь последовательность загрузки lsp определит, какая функция aa будет использоваться!

Мораль сей басни очень проста: надо "загнать" все подобные шутки в локальные переменные. Для этого откроем, например, Notepad++ и загрузим туда lsp-файлы. Поскольку в Notepad++ прекрасно работает подсветка синтаксиса и "сворачивание" функций, "сворачиваем" функции до уровня объявлений:
Вид Notepad++
Теперь осталась самая малость: сделать глобальное объявление своей функции, загнав все имеющиеся в ее локальные:
Останется только загрузить новый файл.

Аналогичным образом можно поступить со всеми имеющимися кодами. Да, работа нудная и тяжелая, но иногда необходимая.

P.S. В некоторых случаях может помочь клавиатурное сочетание в vlide Ctrl+Shift+C, но лично у меня оно почему-то работает не совсем корректно, так что я не могу его рекомендовать.

Размещено в Код LISP, Новости, Среда разработки · Метки:



Поделитесь своим мнением


Я не робот.