2

How to specify a list, which's last element is referring to the first element?

By specify I mean, for example, how to write a setq statement with this list.
I have seen this in the documentation, but I can't find it anymore. Here some pointers:

  • You could loop over the elements of the list forever, but it uses only about as much memory as it has real elements.
  • Its cdr points to its car.
  • You could call it a ring list, but I do not mean stuff from the ring package.
  • It is something basic.

I do not have a use in mind, it's just for learning and experimenting.

jue
  • 4,476
  • 8
  • 20
  • So you want an infinite list or you want a circular list? (-1 since this appears in search results for the title, but the contents are different) – mihai Jun 06 '19 at 11:32
  • @mihai I don't know what you are talking about. Maybe writing an answer would be more helpful than downvoting. – jue Jun 19 '19 at 19:56
  • [see this answer](https://stackoverflow.com/questions/25498431/what-is-the-difference-between-a-cyclic-list-and-an-infinite-list-in-haskell). It has a nice picture, too. Cyclic and infinite are two different things. You ask for one in the title, but for the other one in your actual question. – mihai Jun 20 '19 at 06:11
  • @mihai thats the way learning goes, It didn't occured to me there is difference. Also I'm no native english speaker, so I rely on (maybe inaccurate) dictionarys and approximations ... Anyway, thanks for the hint. – jue Sep 17 '19 at 10:28

1 Answers1

3

See the Elisp manual, node Circular Objects.

A circular list is one way to implement an infinite list.

For example (from the doc), this creates a list in which the first element recurs as the third element:

(setq x  '(#1=(a) b #1#))

In your case:

(setq ys  '(1 2 3 4))
(setq ll  (last ys))
(setcdr ll ys) 

C-h v ys:

#1=(1 2 3 4 . #1#)
Drew
  • 75,699
  • 9
  • 109
  • 225
  • 1
    It would be better to write `(setq ys (list 1 2 3 4))` since you're going to modify the list object – npostavs Jun 29 '17 at 14:25
  • This is exactly the documentation I was searching for. This `#1=(a #1#)` was what I meant. Thank you for the nice `setq` example. – jue Jun 29 '17 at 14:25
  • @npostavs Thanks for the hint, I thought `'` and `list` are just different notations. I better have an extra look into the manual. :) – jue Jun 29 '17 at 14:29
  • `list` vs `'` doesn't matter for this simple illustration. What matters is that you must not expect `'` to always create new list structure (it doesn't). `list` always creates a new cons. – Drew Jun 29 '17 at 14:51
  • @Drew It doesn't matter until someone copies it into a function, [and gets confused about why they keep getting a different result...](https://emacs.stackexchange.com/questions/20535/why-does-a-constant-in-let-change-with-repeated-calls) – npostavs Jun 29 '17 at 17:50
  • 2
    @npostavs: Agreed. For its purpose here it is OK. Plugged into a different context, the behavior might surprise someone unaware of how `'` is handled. – Drew Jun 29 '17 at 17:53
  • `(setq mod3 '#1=(0 1 2 . #1#))` and `(nth 4 mod3)` gives 1. :-) I never thought that the hash sign used for printing is a valid read-syntax. Thanks for that info even if it is more like a philosophical one. Are the conses assigned to your `x` garbage collected if `x` goes out of scope (e.g., for `let`-bound `x`)? A note on practical implementation would be nice. I think structures like `kill-ring` are not implemented that way. – Tobias Sep 17 '19 at 12:00
  • @tobias: I believe that a circular list is realized by a pointer. No extra conses are needed - the same cons is reused by pointing to it. And no, Emacs "rings" such as `kill-ring` and `search-ring` do not use circular lists. There's no need for that (which would require modifying list structure in order to update etc. But you could certainly play with such an implementation, to see what the effects might be. See `ring.el` for the usual handling of Emacs rings. – Drew Sep 17 '19 at 15:05