Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elisp: How to push-back to a list

Tags:

lisp

elisp

Is there a way to push-back to a list in elisp?

The closest thing I found was

(add-to-list 'myList myValue t) ;; t tells it to put to back of the list

The problem, however, is that add-to-list enforces uniqueness. The other alternative is (push 'myList myVal) but that can only push to the front of a list. I tried using (cons myList myVal) but IIRC that returns something other than a list.

The only thing that has worked is

(setq myList (append myList (list myVal)))

but that syntax is hideous and feels like a lot of extra work to do something simple.

Is there a faster way to push to the back of a list. It's clearly possible as seen in (add-to-list), but is there a way to do it without enforcing uniqueness?

In other words, a good old push-back function like with C++ and the <List> class

like image 831
Cameron Avatar asked Apr 04 '17 14:04

Cameron


1 Answers

Lisp lists vs "lists" in other languages

Lisp lists are chains of cons cells ("linked lists"), not specialized sequential containers like in C, and not a weird blend of lists and vectors like in Perl and Python.

This beautiful approach allows the same methodology to be applied to code and data, creating a programmable programming language.

The reasons Lisp does not have a "push-back" function are that

  • it does not need it :-)
  • it is not very well defined

No need

Adding to the end is linear in the length of the list, so, for accumulation, the standard pattern is to combine push while iterating and nreverse when done.

Not well defined

There is a reason why add-to-list takes a symbol as the argument (which makes it useless for programming).

What happens when you are adding to an empty list? You need to modify the place where the list is stored.

What happens when the list shares structure with another object? If you use

(setq my-list (nconc my-list (list new-value)))

all the other objects are modified too.

If you write, like you suggested,

(setq my-list (append my-list (list new-value)))

you will be allocating (length my-list) cells on each addition.

like image 145
sds Avatar answered Oct 06 '22 00:10

sds