Ну, есть append!
как примитив, который решает большинство ваших проблем, как уже отмечалось, Схема имеет тенденцию хмуриться при мутации, это возможно, но обычно избегается, поэтому все процедуры, которые мутируют, имеют !
(называется взрывом) в конце.
Кроме того, 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)
Как видно, добавь! может принимать бесконечное количество аргументов, и оно мутирует их всех, кроме последнего.
Хотя схема не может быть идеальным языком для вас. Использование дополнения! как было сказано ранее, является нестандартным, вместо этого предпочтительнее append, который не изменяется и вызывается для его возвращаемого значения. Который я реализую как таковой:
(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
Что делает то, что вы ожидаете