Являются ли выражения, такие как (set! C (cons 3 c)), способом добавления элемента в список? - PullRequest
2 голосов
/ 23 января 2012

Схема уже установлена-машина! и set-cdr !, но никаких сет-минусов! .

Являются ли такие выражения, как

(установлено! C (минусы 3 c))

который помещает элемент 3 в список c, правильный / единственный / лучший / обычный способ изменить список?

Ответы [ 3 ]

5 голосов
/ 23 января 2012

(set! c (cons 3 c))

Хорошо, давайте выясним, что делает это выражение:

  • set! принимает переменную в качестве первого аргумента и выражение в качестве второго аргумента. Он оценивает второй аргумент и присваивает значение переменной.
  • cons принимает значение и список и создает список с заданным значением в качестве заголовка и заданным списком в качестве хвоста.

Итак, (set! c (cons 3 c)) создает список с 3 в качестве головы и c в качестве хвоста и назначает этот список в качестве значения c. Это изменение видно только для кода, который обращается к той же привязке c - если есть другие переменные или поля объекта, которые ссылаются на исходный список, они все еще ссылаются на этот исходный список.

Это можно условно описать как «добавление элемента в список» в некоторых контекстах , но это нечеткое описание, потому что вы не берете существующий список и не модифицируете его для получения нового вещь; скорее, вы создаете список с новым начальным элементом и исходным списком в качестве хвоста и изменяете некоторые (но, возможно, не все) ссылки на старый список, чтобы указывать на новый.

Я могу сразу подумать о двух основных вещах, которые также могут рассматриваться как «добавление элемента в список»:

  • Изменение структуры существующего списка, чтобы добавить новую пару где-то в середине или конце. Если вы действительно строго относитесь к терминологии, это единственный верный случай «добавления элемента в список».
  • Помещение элемента в начало списка и возврат его вызывающей стороне или передача его в качестве аргумента другой функции (без set!). Это даже более свободный язык, чем ваш пример, но это также самый распространенный случай!

Пример первого:

(define (insert-at-second-position! item list)
  (set-cdr! list (cons item (cdr list))))

Пример второго:

(define (list-copy xs)
  (if (null? xs)
      '()
      ;; We call list-copy recursively on the tail, and "add an item"
      ;; at the front:
      (cons (car xs)
            (list-copy (cdr xs)))))
1 голос
/ 23 января 2012

Это правильный способ изменить список c. Но такое использование встречается редко. Возможно, вы могли бы рассказать нам больше о том, что вы пытаетесь сделать.

0 голосов
/ 28 января 2012

Вы должны знать о конструкторах типов, модификаторах и методах доступа.

Пары создаются с cons, который представляет собой процедуру из 2 аргументов, первый аргумент (автомобиль) является первым элементом пары, а второй аргумент (cdr) является вторым элементом пары. Правильные списки требуют, чтобы его cdr был списком с нулевым символом в конце. В противном случае это всего лишь пара.

Пара селекторов (car и cdr) принимает один аргумент, список CONStructed, и либо извлекает первый (используя car), либо оставшийся (используя cdr) аргумент is-pair.

Модификаторы (сеттеры) принимают 2 аргумента: существующий CONStruct (пара, автомобиль пары и в основном все, что было построено) и заменяет выбранную конструкцию значением ее второго аргумента.

(set-car! (cons 'a (cons 'b '())) 'c) ;; is the same as
(set! (car (cons 'a (cons 'b '()))) 'c)

Понял?

...