Это пункт об использовании мутации в вашем коде: для этого не нужно переходить к макросам.Я пока возьмусь за операции со стеком: чтобы получить простое значение, которое вы можете передавать и изменять, все, что вам нужно, это обертка вокруг списка, а остальная часть вашего кода остается прежней (ну, с незначительным изменением, которое делаетон делает операции стека правильно).В схеме PLT это как раз то, для чего предназначены ящики:
(define (push x a-list)
(set-box! a-list (cons x (unbox a-list))))
(define (pop a-list)
(let ((result (first (unbox a-list))))
(set-box! a-list (rest (unbox a-list)))
result))
Обратите внимание, что вы можете использовать begin0
вместо let
:
(define (pop a-list)
(begin0 (first (unbox a-list))
(set-box! a-list (rest (unbox a-list)))))
Что касается его превращения вочередь, вы можете использовать один из вышеперечисленных методов, но кроме последней версии, написанной Джонасом, решения очень неэффективны.Например, если вы делаете то, что предлагает Сев:
(set-box! queue (append (unbox queue) (list x)))
, то это копирует целую очередь - это означает, что цикл, который добавляет элементы в вашу очередь, будет копировать все в каждомКроме того, генерируя много мусора для GC (подумайте о добавлении символа в конец строки в цикле).Решение "unknown (google)" изменяет список и добавляет указатель на его конец, поэтому оно не создает мусор для сбора, но все равно неэффективно.
Решение, написанное Джонасом, является распространенным способом сделать это.- сохранить указатель на конец списка.Однако, если вы хотите сделать это в схеме PLT, вам нужно будет использовать изменяемые пары: mcons
, mcar
, mcdr
, set-mcar!
, set-mcdr!
.Обычные пары в PLT являются неизменяемыми с момента выхода версии 4.0.