(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)))))