Вопрос

В данный момент я изучаю схему R5RS (из PocketScheme) и нахожу, что мог бы использовать функцию, которая встроена в некоторые варианты Scheme, но не во все:Добавить!

Другими словами - деструктивное изменение списка.

Меня интересует не столько сам код как ответ, сколько понимание процесса, с помощью которого можно передать список в виде функции (или вектора, или строки), а затем изменить его.

пример:

(define (append! lst var)
    (cons (lst var))
)

Когда я использую подход, описанный выше, я должен сделать что-то вроде (define list (append! foo (bar)) из чего я бы хотел что-то более общее.

Это было полезно?

Решение

Мутация, хотя и разрешена, в Схеме категорически не рекомендуется.PLT даже зашел так далеко, что удалил set-car! и set-cdr! (хотя они "заменили" их на set-mcar! и set-mcdr!).Однако спецификация для append! появился в SRFI-1.Это append! это немного отличается от вашего.В SRFI реализация мочь, но не является требуемый изменить ячейки cons для добавления списков.

Если вы хотите иметь append! это гарантированный чтобы изменить структуру списка, к которому добавляется, вам, вероятно, придется написать его самостоятельно.Это не сложно:

(define (my-append! a b)
  (if (null? (cdr a))
      (set-cdr! a b)
      (my-append! (cdr a) b)))

Чтобы упростить определение, здесь нет проверки ошибок, но ясно, что вам нужно будет передать список длиной не менее 1 как a, и (предпочтительно) список (любой длины) в виде b.Причина a должна быть не менее длины 1, потому что вы не можете set-cdr! в пустом списке.

Поскольку вам интересно, как это работает, я посмотрю, смогу ли я объяснить.По сути, то, что мы хотим сделать, это пройтись по списку a пока мы не доберемся до последнего cons пара, которая является (<last element> . null).Итак, сначала мы посмотрим, есть ли a уже является последним элементом в списке, проверив наличие null в cdr.Если это так, мы используем set-cdr! чтобы добавить его в список, который мы добавляем, и все готово.Если нет, мы должны позвонить my-append! на cdr из a.Каждый раз, когда мы делаем это, мы приближаемся к концу a.Поскольку это операция мутации, мы не собираемся ничего возвращать, поэтому нам не нужно беспокоиться о формировании нашего измененного списка в качестве возвращаемого значения.

Другие советы

Лучше поздно, чем никогда, чтобы вложить пару-тройку центов в эту тему...

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

(2) Я думаю, ДОБАВИТЬ!должен вести себя как APPEND, только (потенциально) деструктивно.И так ДОБАВЛЯЙТЕ!следует ожидать любое количество списков в качестве аргументов.Каждый список, кроме последнего, предположительно будет установлен-CDR!'d для следующего.

(3) Приведенное выше определение APPEND!по сути, это NCONC из Mac Lisp и Common Lisp.(И другие шепелявые выражения).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top