Emacs Lisp nested function - void-variable error

社会主义新天地 提交于 2019-12-11 12:49:06

问题


I want to make a timer, like this one:

(defun dumb (y)
  (defun P () (print y))
  (run-with-timer 0 5 'P))

(dumb 5)

Then Emacs gives me this error:

Error running timer `P': (void-variable y)

I guess the problem is that in the (defun P () (print y)) line, the variable y is not evaluated, so when I run (dumb 5), the function P tries to print y, which is undefined, instead of a literal 5. But I don't know how to solve it. Any idea?


回答1:


First, defun is for defining functions in the global scope. You only need to build an anonymous function instead, with a lambda form.

Second, y is only bound to a value while dumb is being executed (dynamic extent). Registering the function with run-with-timer is asynchronous and exits immediately. When your callback is called, y is not bound anymore.

You can activate lexical binding in you current buffer with a file-local variable:

;;; -*- lexical-binding: t -*-
(defun dumb (y)
  (run-with-timer 0 5 (lambda () (print y))))

Alternatively, when lexical-binding is nil, you can "build" the lambda form with the currently bound value of y injected in it:

(defun dumb (y)
  (run-with-timer 0 5 `(lambda () (print ,y))))



回答2:


Another way to solve this is to pass the extra argument to run-with-timer:

(defun dumb (y)
  (run-with-timer 0 5 'print y))

run-with-timer accepts any number of arguments after the function to call, and those arguments will be passed along when the timer fires.



来源:https://stackoverflow.com/questions/33382928/emacs-lisp-nested-function-void-variable-error

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!