问题
I have not found any examples of how to replace the nth element of a list without first adding every element (one-by-one) with the function add-to-ordered-list -- e.g., (add-to-ordered-list 'the-list 'a 1). That requires subsequently deleting the element -- e.g., (delq a the-list). The third step in the process is to add the new element -- e.g., (add-to-ordered-list 'the-list "HELLO-WORLD!" 1). As the following function named variable-list-example uses 26 elements, I'm looking for a better way than first adding all 26 elements (one-by-one) to essentially assign each element a position number. The function add-to-ordered-list uses a number assignment that is one digit different than the standard nth element approach where the first element has a value of 0, whereas add-to-ordered-list uses the value of 1 for the first element. Here is the link to the documentation for add-to-ordered-list: http://www.gnu.org/software/emacs/manual/html_node/elisp/List-Variables.html
In addition, using the combination '( at the beginning of a list seems to prevent using a let-bound variable inside the list -- e.g., the let-bound variable appears in the list as my-variable instead of HELLO-WORLD!. The only work-around I have found is the above-mentioned example using add-to-ordered-list -- which is a lengthy three-step process (i.e., adding each element one-by-one at the outset).
To resolve both issues, I am looking for some assistance please to replace the 17th element of the-list (which is the letter r) with my-variable (which is HELLO-WORLD!).
(defun variable-list-example ()
(interactive)
(let* (
(my-variable "HELLO-WORLD!")
(the-list '(a b c d e f g h i j k l m n o p q r s t u v w x y z)))
;; replace the 17th element of `the-list` with `my-variable`
(message "Presto -- this is your new list: %s" the-list)
))
THE LIST
'(a b c d e f g h i j k l m n o p q r s t u v w x y z)
nth ELEMENT -- CHEAT SHEET / LEGEND
element 0: a
element 1: b
element 2: c
element 3: d
element 4: e
element 5: f
element 6: g
element 7: h
element 8: i
element 9: j
element 10: k
element 11: l
element 12: m
element 13: n
element 14: o
element 15: p
element 16: q
element 17: r
element 18: s
element 19: t
element 20: u
element 21: v
element 22: w
element 23: x
element 24: y
element 25: z
回答1:
You need to use setcar and nthcdr:
(setcar (nthcdr 17 the-list) my-variable)
The more common-lisp-like approach is to use Generalized Variables:
(setf (nth 17 the-list) my-variable)
回答2:
Emacs has a concept of Generalized Variables, which essentially lets you change arbitrary storage places with setf. For instance, you can change car and cdr places of list, including the car returned by nth. Hence, the following code
(let ((foo 10)
(l '(1 2 3 4 5 6 7 8)))
(setf (nth 4 l) foo)
l)
will return the list (1 2 3 4 10 6 7 8).
To put variables directly into a quoted list, you must change the kind of quoting. The standard quote ' inhibits any evaluation inside the quoted expression.
The special Backquote however lets you evaluate expressions inside a quoted expression:
(let* ((foo 10)
(l `(1 2 3 4 5 ,foo 7 foo)))
l)
The leading comma marks the subsequent expression for evaluation, whereas expressions without a leading comma will be taken literally. In the above example, the first occurrence of foo in the list will be evaluated, and hence replace with 10, whereas the second occurrence ends up literally in the list.
来源:https://stackoverflow.com/questions/22440069/emacs-how-to-replace-nth-element-of-a-list-with-a-let-bound-variable