Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Various forms of looping and iteration in Elisp

Tags:

lisp

elisp

I am trying to understand all the looping constructs in Emacs Lisp. In one example I am trying to iterate over a list of symbols and print them to the *message* buffer like so:

(let* ((plist package-activated-list) ;; list of loaded packages
       (sorted-plist (sort plist 'string<)))
  (--map (message (format "%s" it)) sorted-plist))

--map is a function from the package dash.el.

How to do this in pure Elisp?

Now how do I iterate over a list in Elisp, without using other packages.

I have seen some examples using while and dolist macro, for example here:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Iteration.html

But those are destructive, non-functional ways to express a loop.

Coming from Scheme (having worked with it and with SICP some twenty years ago!), I tend to prefer functional, non destructive (does that always lead to recursive?) ways to express ideas.

So what are idiomatic ways to loop over a list of items in Emacs Lisp?

Also: Are there ways to express loops in a functional fashion in Emacs Lisp?

What I have found so far

  1. Loop Macros (from Common Lisp?) prefixed with "cl-*"

https://www.gnu.org/software/emacs/manual/html_node/cl/Loop-Facility.html

  1. Iteration Clauses

https://www.gnu.org/software/emacs/manual/html_node/cl/Iteration-Clauses.html#Iteration-Clauses

  1. Dash.el

https://github.com/magnars/dash.el

Magnar Sveen's excellent package marketed as "A modern list api for Emacs. No 'cl required."

What else is there? Any recommended reading?

like image 684
Ugur Avatar asked Oct 22 '25 22:10

Ugur


1 Answers

dolist is not destructive, and that is probably the most idiomatic way in Emacs Lisp, or Common Lisp for that matter, to loop over a list when you just want to do something with each member in turn:

(setq *properties* '(prop1 prop2 prop3))

(dolist (p *properties*)
  (print p))

The seq-doseq function does the same thing as dolist, but accepts a sequence argument (e.g., a list, vector, or string):

(seq-doseq (p *properties*)
  (print p))

If a more functional style is desired, the seq-do function applies a function to the elements of a sequence and returns the original sequence. This function is similar to the Scheme procedure for-each, which is also used for its side effects.

(seq-do #'(lambda (p) (print p)) *properties*)
like image 178
ad absurdum Avatar answered Oct 26 '25 00:10

ad absurdum



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!