Let's consider the following functions:
(defun test (x)
"X."
(request "http://example.com"
:parser 'json-read
:complete (cl-function
(lambda (&key response &allow-other-keys)
(message "%s" x)))))
(defun test2 (x)
"X."
(funcall (cl-function (lambda (z) (message "%s" z))) x))
Calling (test2 3)
Works fine and produces the desired message. Calling (test 3)
, however, fails with the following error:
error in process sentinel: let*: Symbol’s value as variable is void: x
error in process sentinel: Symbol’s value as variable is void: x
My guess is that request
is a macro doing something weird to variable scoping. Unfortunately, the documentation does not mention anything like this. Is there a way to overcome that?
CodePudding user response:
request
is probably an ordinary function.
The problem is that the lambda
you pass to it is not called immediately but is
saved and called later:
(defun make-function (x)
(lambda () (message "received %s" x)))
=> make-function
(defconst f (make-function 3))
=> f
(funcall f)
=> Lisp error: (void-variable x)
x
that make-function
bound no longer exists.
This is because by default Emacs uses dynamic binding and you need lexical binding to get the behavior you want.
If you add
;; -*- lexical-binding:t -*-
to the first line of your file, it will be compiled with lexical binding and
the code above will produce the message received 3
instead of an error.