Понимание области видимости переменной в данном коде - PullRequest
0 голосов
/ 11 февраля 2020

Я новичок в Emacs lisp, так что это действительно нубский вопрос. Допустим, мне нужно написать функцию, которая использует al oop для добавления 1 к каждому элементу вектора цифр c.

Вот код, который я написал (комментарии указывают, что я пытается делать на каждом шаге):

(defun add-one (x)
  "Use a loop to add 1 to each element of list X"
  (let* ((res x) ; make a copy of X
         (counter 0)) ; set counter to 0
    (while (< counter (length x))
      ;; Replace each element of RES by adding 1:
      (setcar (nthcdr counter res) (1+ (car (nthcdr counter x))))
      (setq counter (1+ counter)))
    ;; Display result:
    (message "%s" res)))

Но мой код кажется разрушительным для x, так как несколько вызовов функции не дают один и тот же результат:

;; Define a list:
(setq mylist '(1 2 3 4))
;; Several calls to the function:
(add-one mylist) ; -> (2 3 4 5)
(add-one mylist) ; -> (3 4 5 6)

Вот мой вопрос: я не понимаю, почему мой код разрушителен (я ожидал, что результат будет (2 3 4 5) при каждом выполнении). Я знаю, что setcar разрушителен, но он применяется к копии x, а не к x. Так почему же меняется результат?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 22 февраля 2020

Для ясности: несмотря на то, что вы не копируете список ввода, ваш код совсем не лишний. Попробуйте вместо этого:

(mapcar '1+ '(1 2 3 4))
1 голос
/ 11 февраля 2020

Let не делает копии чего-либо, поэтому это присваивает значение, на которое ссылается переменная x, переменной res. Следовательно, любые изменения в списке, на который ссылается res, также изменяют список, на который ссылается x

(let* ((res x) ; make a copy of X

...