Как определить переменную в схеме?

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

8 ответов


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

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


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

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

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

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

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


(set! no-longer-needed #f)

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

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

вы могли бы тогда повторно -define переменной. Все это зависит от объема переменных, конечно: см. Грег.


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

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

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

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

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

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

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

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

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

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

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


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


Я думаю, если ваша точка зрения состоит в том, чтобы сделать эквивалент "бесплатно" или де-выделить, то нет, вам в значительной степени не повезло. вы не можете отменить выделение переменной. вы CAN переопределите его на что-то маленькое, например #f, но как только вы это сделаете (определите foo 'bar), переменная foo будет существовать в какой-то форме, пока вы не закончите программу.

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


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

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

нет способа удалить локальный переменная.

http://docs.racket-lang.org/reference/Namespaces.html?q=namespace#%28def.%28%28quote.~23~25kernel%29._namespace-undefine-variable%21%29%29


Я думаю, что ваш вопрос не глупый. В AutoLISP есть unexisting (undefined) переменная, априори предполагаемая значением "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 работает только в некоторых графических системах САПР.