From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Johan Andersson Newsgroups: gmane.emacs.help Subject: Re: Timer variable binding Date: Tue, 7 Jan 2014 20:52:01 +0100 Message-ID: References: <87d2k3ydij.fsf@yahoo.fr> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 X-Trace: ger.gmane.org 1389124351 19911 80.91.229.3 (7 Jan 2014 19:52:31 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 7 Jan 2014 19:52:31 +0000 (UTC) Cc: help-gnu-emacs@gnu.org To: Nicolas Richard Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Tue Jan 07 20:52:38 2014 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1W0chY-0006k4-O7 for geh-help-gnu-emacs@m.gmane.org; Tue, 07 Jan 2014 20:52:36 +0100 Original-Received: from localhost ([::1]:42534 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W0chY-0000fW-FS for geh-help-gnu-emacs@m.gmane.org; Tue, 07 Jan 2014 14:52:36 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60271) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W0chM-0000fJ-IY for help-gnu-emacs@gnu.org; Tue, 07 Jan 2014 14:52:26 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W0chL-0007oA-8D for help-gnu-emacs@gnu.org; Tue, 07 Jan 2014 14:52:24 -0500 Original-Received: from mail-oa0-x235.google.com ([2607:f8b0:4003:c02::235]:38433) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W0chK-0007ns-T6 for help-gnu-emacs@gnu.org; Tue, 07 Jan 2014 14:52:23 -0500 Original-Received: by mail-oa0-f53.google.com with SMTP id h16so701078oag.26 for ; Tue, 07 Jan 2014 11:52:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=a+pi5LJYeho/2MFvL0v+00U8jwDWC+ZD9ttzUZgwTs8=; b=TsLTIufw4d2nUepsD0QQCh+j1MmwYwXi7/mnzEiNwNgOLsCCFMGIlJHXAK8lNIe0kF 8HrScQEJa+EdsL62Gl/5nVJpSIKzZ8Tshs0zAkXyRMankMc9uS6+GU056Qbe7BlMssYv ioBXa9uvH6Nba74sJRHVqDnwRp1IPCzhtOrdyEq6MimH2Cd7w3TVCLBTNsR/cfaegXOS MsvVfw5o2U0XqQ5fHrcqNhI82TgOURlCd6Q4dYzouqh93WDtkl1IKwl3mycFSWPDszJr MOooEBqu9rxqPcTTs9GsQy1IFw3G5hUvIQ6ZP2QP4+MncUloKTNK6Swn+Q2W4fd2Cehu ImIQ== X-Received: by 10.182.247.68 with SMTP id yc4mr1722909obc.67.1389124341635; Tue, 07 Jan 2014 11:52:21 -0800 (PST) Original-Received: by 10.182.154.73 with HTTP; Tue, 7 Jan 2014 11:52:01 -0800 (PST) In-Reply-To: <87d2k3ydij.fsf@yahoo.fr> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4003:c02::235 X-Content-Filtered-By: Mailman/MimeDel 2.1.14 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:95300 Archived-At: > In fact you are lucky (or not, depending on the point of view) to give > your variable a symbol (namely, "timer") that is dynamically bound to > the 'current timer' at the time the callback function is being run. Of course, should have figured that out. :) I definitely understand how this can work with lexical scoping, but I'm not sure I understand why it does not work in with dynamic scoping. We are wrapping the function call to run-at-time with a let statement. That should make the variable my-var available in everything "under" it? let (my-var=10) -> run-at-time -> *magic* -> callback-function Looks to me like this should work? But why doesn't it? ;) On Tue, Jan 7, 2014 at 5:15 PM, Nicolas Richard < theonewiththeevillook@yahoo.fr> wrote: > Johan Andersson writes: > > I have some questions regarding timers. > > To understand what's going on, you also need to understand what lexical > and dynamical binding is. See (info "(elisp) Variable Scoping") > > > This code will start a timer and the first time the callback runs, the > > timer is canceled. Works great! > > > > (let ((timer (run-at-time 0 1 (lambda () > > (cancel-timer timer)))))) > > > > In the above example I can access the timer variable inside the function > > callback. > > Just changing the name from "timer" to "foobar" will make it complain : > > (let ((foobar (run-at-time 1 1 (lambda () > (cancel-timer foobar)))))) > > In fact you are lucky (or not, depending on the point of view) to give > your variable a symbol (namely, "timer") that is dynamically bound to > the 'current timer' at the time the callback function is being run. > > I guess it happens in the function "timer-event-handler" : the argument > of that function is named "timer", and it is dynamically bound because > that file does not use lexical binding -- if it did, it'd make an error > with "timer" as well as with "foobar". > > > But in this code, I cannot access the variable my-var. Nothing is > > printed. In Emacs 24.3.1 I see no error, but in 24.3.50.1 I get > > (void-variable my-var). Why is there no error in 24.3.1? > > I don't know. > > > (let* (timer (my-var 10)) > > (setq timer (run-at-time 0 1 (lambda () > > (print my-var) > > (cancel-timer timer))))) > > This now should make sense : in fact none of your "timer" or "my-var" > are seen by the callback. It's pure luck that "timer", when the lambda > is run, refers to the current timer. > > Now if you run your code with lexical-binding set to 't' > (let* (timer (my-var 10)) > (setq timer (run-at-time 0 1 (lambda () > (print my-var) > (cancel-timer timer))))) > It'll work as expected: the lambda now is made into a closure (i.e. a > function which knows about its current lexical environment). > > Then this will work : > (let* (timer (my-var 10)) > (setq timer (run-at-time 0 1 (lambda nil > (setq my-var (1- my-var)) > (message "my-var: %s" my-var) > (when (= my-var 0) > (cancel-timer timer)))))) > > but this won't work : > > (let* (timer (my-var 10)) > (setq timer (run-at-time 0 1 (lambda (my-var) > (setq my-var (1- my-var)) > (message "my-var: %s" my-var) > (when (= my-var 0) > (cancel-timer timer))) > my-var))) > > > Can someone please explain these weird behaviors? > > I hope I did ; don't hesitate to ask further. > > -- > Nicolas >