Добавление элемента для Списка в Схеме

Ниже мой код, который берет автомобильный элемент списка(carVal) и список (инициализированный для освобождения) как параметры. Я хочу добавить элемент к списку, но то же не работает.

(define populateValues
   (lambda (carVal currVal)
      (append currVal(list carVal ))
       (display currVal)))

Дисплей показывает пустой список все время () . Кто-либо может помочь мне понять почему?

8
задан Yasir Arsanukaev 12 February 2011 в 12:18
поделиться

5 ответов

Ну вот и дописать! как примитив, который решает большинство ваших проблем, как уже отмечалось, 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

Что делает то, что вы ожидаете

25
ответ дан 5 December 2019 в 05:18
поделиться

(добавить foo bar) возвращает конкатенацию foo и bar . Это не меняет ни foo , ни bar .

2
ответ дан 5 December 2019 в 05:18
поделиться
  1. append создает новый , он не изменяет существующий.
  2. Это связано с тем, что в целом Scheme (и в данном случае Racket) - это язык, который предпочитает функциональный стиль.
  3. Вы можете немного приблизиться с набором ! - но даже это вас разочарует, поскольку изменится только локальная привязка.
  4. Обратите внимание, что в Racket, в частности, списки неизменяемы, поэтому ничто не может изменить список.
  5. Более того, даже если вы можете изменить список таким образом, это очень неэффективный способ накапливать длинные списки, поскольку вам придется многократно сканировать весь список.
  6. Наконец, если у вас есть проблемы на этом уровне, я настоятельно рекомендую перейти на HtDP
5
ответ дан 5 December 2019 в 05:18
поделиться

Вы должны обновить значение currVal с помощью set !. В вашем примере должно быть

(set! currVal (append currVal (list carVal))
(display currVal)
0
ответ дан 5 December 2019 в 05:18
поделиться

Вам действительно нужно подумать о том, какую именно функциональность вы ищете.

Если вы хотите изменить ссылочный список на месте, вы должны выполнить эквивалент добавления! (как указано в других ответах). Но это опасно, ПОТОМУ ЧТО у вас может быть другой код, который считается неизменным в списке, и если вы собираетесь это сделать, ваша процедура должна иметь! в конце концов, чтобы обозначить эту опасность.

Дешевое приближение к тому, что вы хотите сделать, в более функциональном стиле:

(define (populateValues carVal currVal)
 (let ((ll (append currVal (list carVal))))
   (display ll)
   ll))

Обратите внимание, что он создает новый список, выполняет добавление, отображает результат и ВОЗВРАЩАЕТ новый список как значение. Это полезный метод отладки, если у вас нет доступа к промежуточному значению: привязать к переменной, отобразить или записать ее, а затем вернуть.

0
ответ дан 5 December 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: