;; I promised an example of a map-like function that changes the list passed to it ;; rather than making a new copy. Here it is. ;; The first take will be imperfect in that it will create some unneeded cons cells. ;; We'll nail it with the second take. (setq ll '(1 2 3 4 5)) ; this list will keep changing in place (1 2 3 4 5) ;; MAPCAR and MAPC only give us CARs of the list given to them as argument. ;; What we need instead is the cons cells of that list. ;; For that, we can use MAPLIST or MAPCON. ;; Looking up documentation on MAPLIST (C-h f on the function name), we get: ;; (maplist FUNCTION LIST) ;; Map FUNCTION to each sublist of LIST or LISTs. ;; Like ‘cl-mapcar’, except applies to lists and their cdr’s rather than to ;; the elements themselves. ;; Let's try it. Note that it returns a new list, made up of returned values, like MAPCAR. ;; So we get double the cons cells of the original list, which we don't really want. But OK. (maplist (lambda (c) (rplaca c (* 2 (car c)))) ll) (2 4 6 8 10) ; <<-- new cons cells, not EQ to ll ll ; But ll changes as well, as we intended: (2 4 6 8 10) (maplist (lambda (c) (rplaca c (* 2 (car c)))) ll) (4 8 12 16 20) ll (4 8 12 16 20) (maplist (lambda (c) (rplaca c (* 2 (car c)))) ll) (8 16 24 32 40) ll (8 16 24 32 40) (maplist (lambda (c) (rplaca c (* 2 (car c)))) ll) (16 32 48 64 80) ll (16 32 48 64 80) ;; We can get rid of these unwanted new cons cells by using MAPCON. ;; However, we need to be careful with it, because MAPCON not only maps FUNCTION over ;; the CDRs of the argument LIST but also NCONCs the results (see NCONC, destructive concatenation). ;; With NCONC it's really easy to end up in a loop of circular cons cells that not only confuse ;; the PRINT part of your REPL, but also effectively disable Emacs if you do this in eLisp. ;; I actually managed to do it :) and barely avoided having to kill my Terminal. ;; GCL's (help 'nconc) specifically warns about it -- see the example the doc provide. (setq ll '(1 2 3 4 5)) ; reset our test list (1 2 3 4 5) (mapcon (lambda (c) (rplaca c (* 2 (car c))) nil) ll) nil ; ^^^ -- this just hands a bunch of nils to NCONC ll (2 4 6 8 10) (mapcon (lambda (c) (rplaca c (* 2 (car c))) nil) ll) nil ll (4 8 12 16 20) ;; So this works without wasting cons cells. MAPCON tries to do a bit more than we need, ;; with the (surprisingly) destructive NCONC. However, our little trick of returning ;; NIL out of the LAMBDA neutralizes it and gets us what we want. ;; Suggested exercises: ;; - Write your own MAPLISTC that returns the same list as the argument (like MAPC vs MAPCAR) ;; - See the documentation for NREVERSE and NCONC and run the examples safely