Как отменить определение переменной в схеме? - PullRequest
15 голосов
/ 15 августа 2010

Как отменить определение переменной в схеме?Возможно ли это?

Ответы [ 8 ]

6 голосов
/ 13 декабря 2011

Ты дотрагиваешься до нерва.Схема не имеет четкого стандартного представления о том, как работают среды верхнего уровня.Зачем?Потому что стандарты Scheme представляют собой компромисс между двумя группами людей с совершенно разными представлениями о том, как должна работать Схема:

  • Толпа интерпретаторов, которая видит среду верхнего уровня, как вы описали выше: хэш времени выполнения-таблица, в которой привязки постепенно добавляются по мере выполнения интерпретации программы.
  • Затем есть группа компиляции, которая рассматривает среду верхнего уровня как нечто, что должно быть полностью вычислимо во время компиляции (т. е. компилятор должен иметь возможностьокончательно определите все имена, которые будут связаны в среде верхнего уровня).

Ваш вопрос «как определить переменную» имеет смысл только в первой модели.

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

Я твердо нахожусь влагерь компиляции здесь, поэтому я бы порекомендовал вам избегать написания кода, который опирается на возможность добавлять или удалять привязки верхнего уровня во время выполнения или даже требует использования переменных верхнего уровня (хотя это часто неизбежно),Некоторые системы Scheme (например, Racket) способны генерировать достаточно хороший скомпилированный код, но если вы сделаете эти предположения, вы в этом сработаете.

5 голосов
/ 15 августа 2010

В Схеме переменные определяются либо лямбда, либо с помощью одного из различных let.Если вы хотите, чтобы один из них был «неопределенным», тогда все, что вам нужно сделать, это оставить область видимости, в которой они находятся. Конечно, это на самом деле не определяет их, просто переменная больше не связана с ее предыдущим определением.

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

3 голосов
/ 27 марта 2017
* Схема

( R7RS ) не имеет стандартного способа удаления привязки верхнего уровня.

Если вы оцениваете несуществующую переменную, вы получите ошибку:

(eval 'a)
; => ERROR: undefined variable: a

Если вы определите его, переменная будет добавлена ​​в среду верхнего уровня.

(define a 1)
(eval 'a)
; => 1

Начиная с этого момента, независимо от того, что вы делаете, вы не получите сообщение об ошибке, если получите доступ к переменной.

Если вы установите значение false, вы получите false:

(set! a #f)
(eval 'a)
; => #f

Даже если вы установите что-то неопределенное, маловероятно, что вы получите ошибку:

(set! a (if #f #t))
(eval 'a)
; =>

Но Схемы могут иметь нестандартный способ удаления привязки верхнего уровня. Схема MIT обеспечивает функцию unbind-variable.

3 голосов
/ 17 августа 2010
(set! no-longer-needed #f)

Достигает ли это желаемого эффекта? Вы также можете использовать определение на верхнем уровне.

guile> (define nigel "lead guitar")
guile> nigel
"lead guitar"
guile> (define nigel #f)
guile> nigel
#f
guile> 

Затем вы можете повторно define переменную. Конечно, все зависит от области действия переменных: см. ответ Грега .

1 голос
/ 01 декабря 2014

Как указано в других ответах, в Схеме нет стандартного способа манипулирования пространством имен. Для конкретной реализации может быть решение.

В Racket переменные верхнего уровня хранятся в пространстве имен. Вы можете удалить переменную используя namespace-undefined-variable.

Нет способа удалить локальную переменную.

http://docs.racket -lang.org / ссылка / д = Namespaces.html пространство имен #% 28def?. % 28% 28quote. 23 ~ ~ 25kernel% 29._namespace-Undefine переменной % 21% 29% 29

1 голос
/ 17 августа 2010

Я думаю, что если вы хотите сделать эквивалент «свободного» или «перераспределить», то нет, вам не повезло. Вы не можете отменить выделение переменной. вы МОЖЕТЕ переопределить его на что-то маленькое, например #f, но как только вы это сделаете (определите строку 'foo'), переменная foo будет существовать в некоторой форме, пока вы не завершите программу.

С другой стороны, если вы используете let, или letrec, конечно, имя существует только до соответствующего закрытия ...

1 голос
/ 15 августа 2010

Вы не можете отменить привязку переменной в стандартной схеме.Вы могли бы установить!Я полагаю, что переменная 'undefined' или вы можете написать metainterpreter, который уточняет окружение, позволяя вам ввести собственное понятие неопределенных переменных.

0 голосов
/ 29 ноября 2014

Я думаю, что ваш вопрос не глупый.В AutoLISP есть несуществующая (неопределенная) переменная априори, допустимое значение «nil» (даже если переменная не существует в памяти - это означает - если ее нет в таблице переменных - тогда значение равно «nil» - «false»),Это также означает ложь.И это тоже пустой список.Если вы программируете какую-то функцию обработки списка, достаточно выполнить начальный тест только следующим образом:

(if input-list ....)

Если вы хотите явно отменить определение любой переменной, вы можете сделать это:

(setq old-var nil); or: (setq old-var ())

Мне это нравится.Ключевое слово «setq» означает «определить».Что лучше в ограничивающих и неограниченных переменных в других диалектах?Вы должны проверить, существуют ли они, если это списки, вам нужен сборщик мусора, вы не можете отменить определение переменной для явного освобождения памяти.Следующая команда не может быть записана, если переменная «my-list» не определена:

(define my-list (cons 2 my-list))

Так что я думаю, что AutoLISP гораздо лучше подходит для программирования.Возможности, которые я написал, вы можете использовать там.К сожалению, AutoLISP работает только в некоторых графических системах проектирования САПР.

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