Что ж, существует append!
в качестве примитива, который решает большинство ваших проблем, как уже отмечалось. Scheme имеет тенденцию не одобрять мутацию, это возможно, но обычно ее избегают, поэтому все процедуры, которые мутируют, имеют !
(называемый взрывом) в их конец.
Кроме того, set!
не изменяет данные, а изменяет окружение, делает переменную ссылкой на другую вещь, исходные данные остаются неизменными.
Изменение данных в Scheme довольно громоздко, но, чтобы дать вам мою собственную реализацию append! посмотреть, как это делается:
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
(apply append! (cdr lst) lsts))))
Обратите внимание на использование set-cdr!
, который является настоящим мутатором, он работает только с парами, он изменяет данные в памяти, в отличие от `set!'. Если пара передана функции и изменена с помощью set-cdr! или set-car!, он мутирует везде в программе.
Это подчиняется добавлению SRFI! spec, в котором говорится, что он должен быть вариативным и, например, должен возвращать неопределенное значение.
(define l1 (list 1 2 3 4))
(define l2 (list 2 3 4))
(define l3 (list 3 1))
(append! l1 l2 l3)
l1
l2
l3
Что отображает:
(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
Как видно, дописываю! может принимать бесконечное количество аргументов и изменяет их все, кроме последнего.
Тем не менее, Scheme может быть не идеальным языком для вас. Использование добавления! как было сказано ранее, является нестандартным, вместо этого предпочтительнее добавление, которое не мутирует и вызывается для его возвращаемого значения. Который я реализую как таковой:
(define (append . lsts)
(cond
((null? lsts) '())
((null? (car lsts)) (apply append (cdr lsts)))
(else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))
> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
Который показывает более знакомый стиль Scheme при отсутствии мутаций, интенсивного использования рекурсии и без использования секвенирования.
Изменить: если вы просто хотите добавить некоторые элементы в список, а не сами по себе, присоединитесь к двум:
(define (extend l . xs)
(if (null? l)
xs
(cons (car l) (apply extend (cdr l) xs))))
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(extend '(0 1 2 3) 4 5 6)
(define list1 '(0 1 2 3))
(extend! list1 4 5 6)
list1
Что делает то, что вы ожидаете
person
Zorf
schedule
05.07.2010