Here is some asynchronous code in a cl-loop:
;;; foo.el --- -*- lexical-binding: t; -*-
(let ((my-list '(a b c)))
(cl-loop for index below (length my-list)
for value = (seq-elt my-list index)
do (run-at-time 0 nil
(lambda () (message "index=%s,value=%s" index value)))))
This code prints "index=3,value=c" 3 times in the *Messages* buffer. This is not what I want. I would like to see "index=0,value=a", "index=1,value=b", "index=2,value=c" (I don't care about the order of messages).
A workaround is to let-bind the index and value variables:
;;; foo.el --- -*- lexical-binding: t; -*-
(let ((my-list '(a b c)))
(cl-loop for index below (length my-list)
for value = (seq-elt my-list index)
do (let ((index index) (value value))
(run-at-time 0 nil
(lambda () (message "index=%s,value=%s" index value))))))
This is good enough for me but I thought there might be a more elegant solution.
Another workaround is to pass #'message as third argument to run-at-time instead of the lambda and to pass the arguments to message as &rest arguments to run-at-time. This is not good enough for me though because my real code is a bit more complex and involves calling a callback variable which may or may not do a run-at-time.