Мутация, хотя и разрешена, настоятельно не рекомендуется на Схеме. 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
. Поскольку это операция мутации, мы ничего не вернем, поэтому нам не нужно беспокоиться о том, чтобы сформировать наш измененный список в качестве возвращаемого значения.
Последующий вопрос - если мутация сильно обескуражена, то что лучше всего подходит для шаблона типа «создание списка из диалогового окна мастера»? Исходя из фона Ruby, это то, с чем я боролся с пониманием ... мышление moreso, чем просто фактический код для решения проблемы. –
В функциональном программировании, когда вы хотите изменить структуру данных или что-то подобное, вы передаете ее в функцию и возвращаете модифицированную структуру данных в качестве возврата. Однако «оригинальная» структура остается нетронутой, и то, что вам дано, это новая, измененная копия (так сказать). –
Возможна полная гарантия, что является проблемой с деструктивными функциями - если список пуст, то никакая версия 'append!' Никогда не сможет его модифицировать. –