1

How do I subtract 1 from the second element of the list (3 6)?

(setq x '(3 6))
(- (nth 1 x) 1)

The above quote does the math but does not return a modified list.

3
  • 1
    The function - is a pure arithmetic function which accepts numbers and returns a number. It knows nothing about where the arguments came from and does not modify any stored data. If you care about the result of the arithmetic operation then you should store it back in the list, e.g. using the convenient macros listed in the answer(s) below. Be careful, though, not to destructively modify quoted constant lists such as '(3 6) in-place; make a copy of the list using copy-sequence first or allocate a new one using (list 3 6) instead.
    – Basil
    Commented Feb 11, 2020 at 14:37
  • This Q and emacs.stackexchange.com/q/55428/105 are essentially the same question. One of them should be deleted. (@Basil: would you like to consolidate the underlying question as a community question?)
    – Drew
    Commented Feb 11, 2020 at 16:27
  • @Drew How do I do that? If you know how to, feel free to do so.
    – Basil
    Commented Feb 11, 2020 at 16:45

2 Answers 2

7

Using the built-in cl-lib package, you can write the following:

(eval-when-compile
  (require 'cl-lib))

(cl-decf (nth 1 x))

Alternatively, in vanilla Elisp:

(setf (nth 1 x) (1- (nth 1 x)))

Be careful, though, to avoid modifying quoted constant lists such as '(3 6) in-place, as doing so modifies the constant globally and may cause the code to behave differently in separate runs.

Instead, make sure to operate on a new list each time, e.g. via:

(setq x (list 3 6))
6
  • 1
    @Basil You actually hijacked low-level answer to transform it into a high-level one. You should have written your own answer.
    – Tobias
    Commented Feb 11, 2020 at 14:56
  • 1
    @Tobias I did not change how low- or high-level the answer is. I merely extended and corrected the answer to distinguish between cl-lib (not the obsolete cl) and vanilla Elisp, and added a warning against destructive modifications. If you or the author are opposed to these additions, you are free to revert my suggestions. Writing a separate answer for these extensions would be redundant and off-topic.
    – Basil
    Commented Feb 11, 2020 at 15:00
  • 1
    @Basil: cl.el is not obsolete. Some features of that library are obsolete. See CL: Obsolete Features.
    – Drew
    Commented Feb 11, 2020 at 16:13
  • 1
    FWIW, I agree that @Basil did the right thing (a right thing). He by no means hijacked anything, IMO.
    – Drew
    Commented Feb 11, 2020 at 16:15
  • 1
    @Drew You're right, cl.el is not officially obsolete, but its use is discouraged in favour of cl-lib.el where practical. See (cl) Organization.
    – Basil
    Commented Feb 11, 2020 at 16:43
1

Just tinkering, you can use car and cdr too. I'm sure someone will comment on whether this is good or bad.

(let ((v 99) (p 3) (l (list 1 2 3 4)))
  (setcar (nthcdr p l) (+ (car (nthcdr p l)) v))
  l)
;; => (1 2 3 103)
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.