Ниже мой код, который берет автомобильный элемент списка(carVal)
и список (инициализированный для освобождения) как параметры. Я хочу добавить элемент к списку, но то же не работает.
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal ))
(display currVal)))
Дисплей показывает пустой список все время ()
. Кто-либо может помочь мне понять почему?
Ну вот и дописать!
как примитив, который решает большинство ваших проблем, как уже отмечалось, Scheme имеет тенденцию неодобрительно относиться к мутации, это возможно, но обычно избегается, поэтому все процедуры, которые мутируют, имеют !
(называется взрывом) на их конце.
Также установлен!
не изменяет данные, он изменяет среду , он заставляет переменную указывать на другое, исходные данные остаются неизменными.
Преобразование данных в 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! or 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 может быть не лучшим языком для вас. Использование append! как было сказано ранее, является нестандартным, вместо этого предпочтительным является 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)
Который показывает более знакомый стиль схемы при отсутствии мутации, интенсивном использовании рекурсии и никакого использования секвенирования.
Изменить: если вы просто хотите добавить несколько элементов в список, а не сами по себе, присоединитесь к двум:
(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
Что делает то, что вы ожидаете
(добавить foo bar)
возвращает конкатенацию foo
и bar
. Это не меняет ни foo
, ни bar
.
append
создает новый , он не изменяет существующий. !
- но даже это вас разочарует, поскольку изменится только локальная привязка. Вы должны обновить значение currVal с помощью set !. В вашем примере должно быть
(set! currVal (append currVal (list carVal))
(display currVal)
Вам действительно нужно подумать о том, какую именно функциональность вы ищете.
Если вы хотите изменить ссылочный список на месте, вы должны выполнить эквивалент добавления! (как указано в других ответах). Но это опасно, ПОТОМУ ЧТО у вас может быть другой код, который считается неизменным в списке, и если вы собираетесь это сделать, ваша процедура должна иметь! в конце концов, чтобы обозначить эту опасность.
Дешевое приближение к тому, что вы хотите сделать, в более функциональном стиле:
(define (populateValues carVal currVal)
(let ((ll (append currVal (list carVal))))
(display ll)
ll))
Обратите внимание, что он создает новый список, выполняет добавление, отображает результат и ВОЗВРАЩАЕТ новый список как значение. Это полезный метод отладки, если у вас нет доступа к промежуточному значению: привязать к переменной, отобразить или записать ее, а затем вернуть.