Как удалить переменную/формы в Lisp? - программирование
Подтвердить что ты не робот

Как удалить переменную/формы в Lisp?

В Python у нас есть оператор del для удаления переменных.

например:

a = 1
del a

Что эквивалентно этому в Lisp?

(setq foo 1)
;; (del foo) ?
4b9b3361

Ответ 1

В общем Lisp.

Для символов как переменных:

CL-USER 7 > (setf foo 42)
42

CL-USER 8 > foo
42

CL-USER 9 > (makunbound 'foo)
FOO

CL-USER 10 > foo

Error: The variable FOO is unbound.

См:

  • MAKUNBOUND (определено)
  • SLOT-MAKUNBOUND (определено)
  • FMAKUNBOUND (определено)

Ответ 2

Имена Python находятся в пространствах имен, del удаляет имя из пространства имен. Общий Lisp имеет другой дизайн, гораздо более симпатичный для компиляции эффективного кода.

В общем Lisp мы имеем два вида "переменных". Лексические переменные составляют большинство из них. Лексические переменные аналогичны локальным. Во время выполнения лексическая переменная обычно реализуется как бит памяти (в стеке говорят), а связь с ним имя сохраняется только для целей отладки. На самом деле не имеет смысла говорить об удалении лексических переменных в смысле использования python, поскольку ближайшая аналогия с пространством имен python, которая существует для лексических переменных, - это лексическая область, и это чисто абстракция, используемая спецификацией и компилятором/оценщиком.

Вторая переменная типа "переменная" в CL - это "глобальные" символы. Символы - очень богатые структуры данных, намного богаче, чем метка в python. Они могут иметь много информации, связанной с ними, значение, печатное имя, их "домашний" пакет, функцию и другую произвольную информацию, хранящуюся в списке свойств. Большинство из них являются необязательными. Когда вы используете имя в своем исходном коде, например. (+ X 3), что имя X обычно обозначает лексический символ. Но в противном случае компилятор/оценщик предположит, что вы хотите значение "глобального" символа. То есть вы фактически написали (значение символа "X" ), а не X. Из-за опечаток, соглашений о программировании и других вещей несколько десятилетий назад компиляторы начали жаловаться на ссылки на "глобальные" символы в отсутствие объявления, которое сигнализировало, что символы были предназначенный быть "глобальным". Эта декларация известна как "специальная". Да, это глупая номенклатура. И что еще хуже, специальные переменные не просто глобальны, они также имеют очень полезную функцию, известную как динамическое связывание, но это другая тема.

Символы, которые являются специальными, почти всегда объявляются с использованием defvar, defparameter или defconstant. Существует почти обязательное соглашение о кодировании, которое они пишутся однозначно, т.е. * X *, а не X. Некоторые компиляторы и большинство разработчиков будут жаловаться, если вы отклоняетесь от этого соглашения.

Ok. Итак, теперь мы можем вернуться в дель. Специальные переменные обозначаются символом; и это аналогично тому, как в переменных python обозначается имя. В python имена просматриваются в текущем пространстве имен. В Common Lisp они отображаются в текущем пакете. Но когда поиск происходит, он отличается. В python это выполняется во время выполнения, поскольку имена могут динамически добавляться и удаляться по мере запуска программы. В Common Lisp имена просматриваются, поскольку программа считывается из файла перед ее компиляцией. (Есть исключения, но не позволяйте думать об этом.)

Вы можете удалить символ из пакета (см. unintern). Но это редкая вещь и, вероятно, просто заставляет больно больно. Это простая операция, но она путается по краям, потому что у системы пакетов есть небольшая доза умных функций, которые, хотя очень полезно, прикладывают немного усилий, чтобы стать комфортно. Итак, в некотором смысле, короткий ответ на ваш вопрос заключается в том, что для глобальных символов односторонняя операция является аналогичной. Но вы, вероятно, делаете что-то совершенно исключительное (и, скорее всего, неправильно), если используете это.

Ответ 3

Хотя то, что пишет @Ben, верно, я предполагаю, что вы ищете makunbound, а не unintern. Первый не удаляет символ из obarray (для Emacs Lisp) или пакета (для Common Lisp). Он просто удаляет его symbol-value, то есть его значение как переменную. Если вы хотите, чтобы поведение, пытающееся получить значение переменной, приводило к ошибке без привязки (aka void), попробуйте makunbound.

Ответ 4

Я не противоречу предыдущим ответам, но добавляю.

Учтите, что Lisp имеет сбор мусора. Как вы знаете, вы получаете символ, определенный разными способами: setf, defvar, defparameter, make-symbol, и множество других способов.

Но как вы получаете чистую систему? Как вы убедитесь, что вы не используете переменную по ошибке? Например, вы определили abc, а затем решили, что вы не хотите использовать abc. Вместо этого вы хотите использовать abc-1 и abc-2. И вы хотите, чтобы система Lisp сигнализировала ошибку, если вы пытаетесь использовать abc. Если вы не можете каким-либо образом удалить abc, система не остановит вас, сообщив об ошибке "undefined".

Другие ответы в основном говорят вам, что Lisp не предоставляет способ избавиться от abc. Вы можете использовать makunbound, чтобы символ был свежим без присвоенного ему значения. И вы можете использовать unintern, чтобы символ не был в каком-либо пакете. Тем не менее boundp сообщит вам, что символ все еще существует.

Итак, я думаю, что до тех пор, пока никакой другой символ не ссылается на abc, сбор мусора в конечном итоге избавится от abc. Например, ( setf pt-to-abc abc). Пока pt-to-abc все еще привязан к символу abc, abc будет продолжать существовать даже при сборке мусора.

Другой способ избавиться от abc - закрыть Lisp и перезапустить его. Кажется не столь желательным. Но я думаю, что закрытие Lisp и начало свежего - это то, что фактически избавляет от всех символов. Затем вы определяете нужные символы.

Вероятно, вы обычно хотите makunbound, потому что тогда система будет сигнализировать об ошибке, если вы попытаетесь добавить значение abc к чему-то другому, потому что у abc не будет никакого значения. И если вы попытаетесь добавить abc в строку, система будет сигнализировать об ошибке, потому что abc не имеет строки. Etc.