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
.
for value = (seq-elt my-list index)
is O(n^2), you should probably usefor value in my-list
instead.seq-elt
, I agree with you. I've just asked a new question: emacs.stackexchange.com/questions/52251/…collect (lambda () (message "value%s" value))
and then funcall the returned lambdas outside the loop. But that would invalidate @Tobias' answer.