help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Returning variable "references" under lexical binding


From: Sean McAfee
Subject: Re: Returning variable "references" under lexical binding
Date: Tue, 21 May 2013 15:43:30 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1 (gnu/linux)

Barry Margolin <barmar@alum.mit.edu> writes:
> In article <87bo84b85k.fsf@gmail.com>, Sean McAfee <eefacm@gmail.com> 
> wrote:
>> Similarly, in my original code, I can't just return "timer", because the
>> calling code would only ever see the very first timer created, and would
>> not be able to see the new values for timer that the callbacks store
>> later.
>
> What "new values"? Your code didn't have any way to change the value of 
> timer.  All it did was wrap it in a closure, but that closure doesn't do 
> anything other than return the initial value. Did you leave something 
> out of the original example?

I said:

> It's a routine that sets up a series of idle timers, storing
> each successive timer object INTO THE SAME LEXICAL VARIABLE.

> I want my routine to return an object that can be used to cancel THE
> MOST RECENTLY SET TIMER.

Emphasis added.  And later I elaborated on my example:

> (defun start-my-timer ()
>   (let (timer)
>     (setq timer (make-timer ...))
>     ;; ... (later (occasionally (setq timer (make-timer ...)))) ...
>     (lambda () timer))

"later" was meant to indicate "later in time, after the function
returns."

Because it's not too long, here's the actual code that inspired my
question.  It manages a number of idle timers to implement a new kind of
timer that repeats at regular intervals as long as Emacs remains idle,
and as long as the callback it's given returns true:

--------------------
;; -*- lexical-binding: t; -*-

(defun run-periodically-when-idle (seconds func)
  (let (timer count)
    (labels ((on-first-idle ()
               (when timer
                 (cancel-timer timer))
               (setq count 1)
               (run-and-schedule-next))
             (run-and-schedule-next ()
               (setq timer
                 (and (funcall func count)
                      (run-with-idle-timer
                       (* seconds (incf count))
                       nil
                       #'run-and-schedule-next)))))
      (list (run-with-idle-timer seconds t #'on-first-idle)
            (lambda () timer)))))

(defun cancel-periodic-idle-timer (timer)
  (cancel-timer (first timer))
  (aif (funcall (second timer))
    (cancel-timer it)))
--------------------

I've been using it to automatically refresh my Gnus group buffer every
two minutes:

(setq watch-mail-timer
      (run-periodically-when-idle 120
        (lambda (n)
          (when (string= (buffer-name) "*Group*")
            (let ((message-log-max nil))
              (gnus-group-get-new-news)
              (message "Checked mail #%d" n)
            t))))


reply via email to

[Prev in Thread] Current Thread [Next in Thread]