set! q …
внутри addq!
определения изменяет значение внутреннего идентификатора q
. Вы должны вернуть его значение, а затем захватить возвращаемое значение в вашем пользовательском коде.
Но ваша функция addq!
возвращает неиспользованное значение.
Другими словами, нет необходимости использовать set!
, просто верните результат вызова соответствующего cons …
. Таким образом, ваша очередь равна persistent - наличие новой обновленной очереди не отменяет предыдущих копий, которые могут быть у вас.
Обычно в схеме, челка !
в имени функцию, указывает, что эта функция работает, мутирует структуру он получает в качестве аргумента (т.е. через set-car!
или set-cdr!
). Но для создания новой обновленной копии очереди будут аннулированы старые копии.
Если вы абсолютно уверены, что вы будете иметь только самую последнюю копию вашей очереди, вы можете не писать, как вы показываете, потому что set!
изменит идентификатор внутреннего, как я уже говорил выше.
Путь вокруг это иметь структурировать и использование структурно-мутирует примитивов. Просто используйте с пометкой список для ваших очередей; то вы можете использовать set-cdr!
на своем содержании - потому что передача аргумента схемы «по значению указателя» (или она «указателем значения»?) - указатель скопирован, но скопированный указатель все еще указывает на одно и то же место:
(define (make-empty-queue) (list 'queue))
(define (is-queue-empty? q) (null? (cdr q)))
Теперь вам не нужно возвращать никаких значений, так же, как вы не хотели бы в первую очередь:
(define (addq! q x)
(if (or (is-queue-empty? q) (< x (cadr q)))
(set-cdr! q (cons x (cdr q)))
(addq! (cdr q) x)))
Это немного «грязный», потому что последующие призываний addq!
воны» t получает очередь в виде помеченного списка, с тегом QUEUE
; хотя он все равно будет работать, так как ему требуется только поле cdr
структуры.Но, чтобы быть хорошим, лучше сделать это внутреннее определение, инкапсулировать нечистоту:
(define (addq! q x)
(let g ((q q))
(if (or (is-queue-empty? q) (< x (cadr q)))
(set-cdr! q (cons x (cdr q)))
(g (cdr q)))))
Остальные процедуры изменяются соответственно:
(define (getq q) ; no bang
(if (is-queue-empty? q)
(error " Empty Queue ")
(cadr q)))
(define (remq! q)
(if (is-queue-empty? q)
(error " Empty Queue ") ; or make it some no-op like #f
(set-cdr! q (cddr q))))
пожалуйста * покажите нам код *, который вы запускаете, чтобы создать свою очередь, добавить в очередь и затем распечатать результат. –
Ничего не найдено. – GoZoner
Хотя это не дубликат, вам может быть интересно взглянуть на [Как установлено! определенный в схеме?] (http://stackoverflow.com/q/16733472/1281433) В принятом ответе описывается, как вы можете реализовать функции set-car! '-like для структур, основанных на лексических замыканиях. В вашем случае вам нужна функция 'remq!' Для чего-то, что не является лексическим закрытием, но ответ там может дать некоторые идеи. –