Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a pointer to a list element in Emacs Lisp

Tags:

lisp

elisp

For example, I have a list:

(setq foo '(1 2 3 4 5))

Then I need to get a pointer to its 3rd index element (which contains 4 in the example):

(setq p (SOME_FUNCTION foo 3))

The element with p address can be moved to another list so I can't just save its current foo's index.

And I need to be able to say later on:

(push 0 foo)
=> (0 1 2 3 4 5)
(setf p 444)

and list foo must be (0 1 2 3 444 5) afterwards.

Is this possible in Emacs lisp?

like image 424
Alexander Gromnitsky Avatar asked Feb 05 '13 12:02

Alexander Gromnitsky


2 Answers

In general, you can't store the "address" of an object. However, you can refer to a cons cell (a cons cell is what lists are made of). The cons cell could later be modified using setcar and setcdr.

For example:

(defvar my-cons-cell nil)

(defun my-save-cons-cell (cons-cell)
  (setq my-cons-cell cons-cell))

(defun my-set-car-in-saved-cons-cell (value)
  (setcar my-cons-cell value))

;; Test

(setq foo '(1 2 3 4 5))

(my-save-cons-cell (cdr (cdr (cdr foo))))

(push 0 foo)

(my-set-car-in-saved-cons-cell 444)

Here, foo has the value (0 1 2 3 444 5).

Note that this is really un-lisp like and breaks the functional programming paradigm...

like image 157
Lindydancer Avatar answered Sep 18 '22 04:09

Lindydancer


You can do

(setq p (nth 3 foo))

and it stores in p the value stored at the index you want. You can also do

(setf (nth 3 foo) 444)

to store 444 at that place. But if you try to do something like

(setq pointer (nth 3 foo))
...
(setf pointer 444)

that won't work. In Emacs's trunk I have recently added gv-ref and gv-deref which would work just fine in such a case. They work pretty much like C's & and *:

(setq pointer (gv-ref (nth 3 foo)))
...
(setf (gv-deref pointer) 444)
like image 24
Stefan Avatar answered Sep 18 '22 04:09

Stefan