[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: interactive closure — variables not bound
From: |
Ricardo Wurmus |
Subject: |
Re: interactive closure — variables not bound |
Date: |
Wed, 28 Sep 2016 23:12:08 +0200 |
User-agent: |
mu4e 0.9.16; emacs 25.1.1 |
Stefan Monnier <address@hidden> writes:
>> The problem with this definition is that it doesn’t work (the other
>> problem is that I’m replacing one ugly hack with another). At runtime
>> Emacs says that “field-type” is undefined. At compile time Emacs says
>> that in the callback “xww”, “field-value”, and “field-type” are
>> references to free variables.
>
> Indeed, currently, the `interactive' spec can't be re-created
> individually for every closure. IOW the spec is built once and forall
> for a given lambda expression and hence can't refer to surrounding
> non-global variables.
>
> I suggest you M-x report-emacs-bug.
Okay, I will report a bug.
> This said, in your example, I don't see what benefit you expect to get
> from writing
>
> (call-interactively
> (lambda (str)
> (interactive
> (list (cond ((equal "text" field-type)
> (read-string "Text: " field-value))
> ((equal "password" field-type)
> (read-passwd "Password: " nil field-value))
> ((equal "textarea" field-type)
> (xwidget-webkit-begin-edit-textarea xww
> field-value)))))
> (xwidget-webkit-execute-script
> xww
> (format "findactiveelement(document).value='%s'" str)))))))))
>
> instead of
>
> (let ((str (cond ((equal "text" field-type)
> (read-string "Text: " field-value))
> ((equal "password" field-type)
> (read-passwd "Password: " nil field-value))
> ((equal "textarea" field-type)
> (xwidget-webkit-begin-edit-textarea xww
> field-value)))))
> (xwidget-webkit-execute-script
> xww
> (format "findactiveelement(document).value='%s'" str)))))))))
I’ve tried this first and I’m getting unexpected behaviour. Emacs
prompts for a string in the minibuffer as expected, but the process
becomes *very* busy, stays at 100% CPU usage, grows in memory, and key
presses are registered extremely slowly. Emacs becomes unusable at this
point. I cannot even abort this with C-g and have to kill Emacs.
The C code is pretty straight forward:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DEFUN ("xwidget-webkit-execute-script", …)
(Lisp_Object xwidget, Lisp_Object script, Lisp_Object fun)
{
…
CHECK_STRING (script);
if (!NILP (fun) && (!FUNCTIONP (fun)))
wrong_type_argument (Qinvalid_function, fun);
…
// This runs the JavaScript SCRIPT and then calls the C procedure
// `webkit_javascript_finished_cb', passing FUN.
webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (xw->widget_osr),
SSDATA (script),
NULL,
&webkit_javascript_finished_cb,
(gpointer) fun);
return Qnil;
}
…
static void
webkit_javascript_finished_cb (GObject *webview,
GAsyncResult *result,
gpointer lisp_callback)
{
…
Lisp_Object lisp_value = … /* JavaScript return value */
…
// Run the Lisp callback, passing the converted JavaScript return value
call1 ((Lisp_Object)lisp_callback, lisp_value);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I.e., a user calls `xwidget-webkit-execute-script' with a script and a
lisp callback, the script is executed. When the script is done, a C
callback will be invoked with a reference to the Lisp_Object holding the
lisp callback. All that does is retrieve the JS return value and pass
it to the lisp callback.
I guessed that this odd behaviour must be a result of calling the
callback procedure from C with “call1”. I thought that maybe this is
expected behaviour when calling a procedure that interacts with the user
through the mini-buffer (as read-string does) when it is not using the
“interactive” form.
Is this a bug? (It looks and buzzes like one…)
Or am I doing something stupid?
> [ Oh, and while I'm here, let me advertize pcase:
>
> (let ((str (pcase field-type
> ("text" (read-string "Text: " field-value))
> ("password" (read-passwd "Password: " nil field-value))
> ("textarea" ...
>
> ]
Nice! I’ll keep it in mind.
~~ Ricardo