В языке Common LISP, как я изменяю часть параметра списка из функции, не изменяя исходный список?

Значение по умолчанию читаемо, применимо, но не придерживается или предлагает любой стандарт кодирования.

я думаю причина, IntelliJ не использует теги Javadoc в значении по умолчанию, то, так, чтобы это избежало возможной интерференции с любыми coding/javadoc стандартами, которые могли бы существовать в магазинах разработки. Для пользователя должно быть очевидно, если значение по умолчанию должно быть изменено к чему-то более соответствующему.

, Где я работаю, использованию тегов автора препятствуют по различным причинам.

6
задан Ross 27 September 2009 в 20:01
поделиться

4 ответа

SETF изменяет место . n может быть местом. Первый элемент списка n , на который указывает, также может быть местом.

В обоих случаях список, содержащийся в исходном , передается в модифицировать как его параметр n . Это означает, что оба исходный в функции test и n в функции modify теперь содержат один и тот же список, что означает, что оба original и n теперь указывают на его первый элемент.

После того, как SETF изменяет n в первом случае, он больше не указывает на этот список, а на новый список. Список, на который указывает оригинал , не изменяется. Затем новый список возвращается командой modify , но поскольку это значение не присвоено ничему, оно исчезает и вскоре будет собрано для сбора мусора.

Во втором случае SETF изменяет не n , а первый элемент списка ] n указывает на. Это тот же список, на который указывает исходный , поэтому впоследствии вы можете видеть измененный список также через эту переменную.

Чтобы скопировать список, используйте COPY-LIST .

7
ответ дан 8 December 2019 в 04:09
поделиться

Списки Лиспа основаны на cons-ячейках. Переменные подобны указателям на cons-ячейки (или другие объекты Lisp). Изменение переменной не изменит другие переменные. Изменение cons-ячеек будет видно везде, где есть ссылки на эти cons-ячейки.

Хорошая книга - Touretzky, Common Lisp: Gentle Introduction to Symbolic Computing .

Существует также программа, которая рисует деревья списков и cons-ячеек.

Если вы передадите список такой функции:

(modify (list 1 2 3))

Тогда у вас есть три различных способа использования списка:

деструктивная модификация cons-ячейки

(defun modify (list)
   (setf (first list) 'foo)) ; This sets the CAR of the first cons cell to 'foo .

совместное использование структуры

(defun modify (list)
   (cons 'bar (rest list)))

Выше возвращается список, который разделяет структуру с переданным списком: остальные элементы одинаковы в обоих списках.

копирование

(defun modify (list)
   (cons 'baz (copy-list (rest list))))

Вышеупомянутая функция BAZ похожа на BAR, но не общие ячейки списка,

12
ответ дан 8 December 2019 в 04:09
поделиться

это почти то же самое, что и в этом примере в C:

void modify1(char *p) {
    p = "hi";
}

void modify2(char *p) {
    p[0] = 'h';
}

в обоих случаях передается указатель, если вы измените указатель, вы измените копию параметра значения указателя (что он находится в стеке), если вы измените содержимое, вы измените значение любого объекта, на который указали.

5
ответ дан 8 December 2019 в 04:09
поделиться

У вас, вероятно, есть проблемы, потому что, хотя Lisp является передачей по значению, ссылки на объекты передаются, как в Java или Python. Ваши cons-ячейки содержат ссылки, которые вы изменяете, поэтому вы изменяете как исходную, так и локальную.

ИМО, вам следует попытаться написать функции в более функциональном стиле, чтобы избежать таких проблем. Несмотря на то, что Common Lisp является мультипарадигмальным, функциональный стиль является более подходящим способом.

(defun modify (n) (cons 'x (cdr n))

2
ответ дан 8 December 2019 в 04:09
поделиться
Другие вопросы по тегам:

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