gpt4 book ai didi

asynchronous - Emacs Lisp中async.el说 "Symbol'的函数定义无效的原因是什么?

转载 作者:行者123 更新时间:2023-12-04 05:14:53 25 4
gpt4 key购买 nike

我使用异步在elisp中调用异步函数。

首先,我在github中测试自述代码,它运行良好。

然后我写一个测试代码:

(defun async-function ()
(async-start
;; What to do in the child process
(lambda ()
(shell-command-to-string "~/test.sh"))

;; What to do when it finishes
(lambda (result)
(message "Async process done, result is: %s" result)))

而test.sh代码非常简单:
#! /usr/bin/env sh
sleep 2
echo "shell finish"

它可以工作,但是当我像这样更改lisp代码时,它失败了:
;;;###autoload
(defun test ()
(shell-command-to-string "~/test.sh"))

(defun async-function ()
(async-start
;; What to do in the child process
(lambda ()
(test))

;; What to do when it finishes
(lambda (result)
(message "Async process done, result is: %s" result)))

结果是:
 error in process sentinel: Symbol's function definition is void: test

我使用 autoload函数加载函数文件,但结果告诉我找不到该文件。

我不知道会发生什么以及如何解决。

最佳答案

async.el的工作方式是产生另一个Emacs进程来评估表达式。在这种情况下,您可以在主Emacs进程中定义测试功能,但是异步Emacs进程无法从主进程访问函数和变量。如果要指定供异步调用使用的函数,请将它们放在文件中,然后将该文件加载到异步函数中。但是请记住,变量等不会转移。

这是一个示例,它在一个文件中:

;; ~/.emacs.d/my-functions.el
(defun test ()
(sit-for 2)
"Hello, World!.")

这是其他地方:

;; somewhere else
(async-start
(lambda ()
(load-file "~/.emacs.d/my-functions.el")
(test))
(lambda (result)
(message "result: %s" result))) ;; will message hello world

关于共享变量,异步不支持此功能。您不能做的是启动一个异步函数,该函数会连续修改变量并希望可以在主emacs进程中访问它,甚至只是将变量传递给异步lambda,因为在打开该符号之前不会对其进行求值不存在的新流程。

我们可以利用Lisp的反引号语法将变量按值传递给异步函数。下面是在异步函数中使用局部变量和函数的一种非常怪诞的方法。

;; We will declare a local variable `myvar'
(setq myvar "Bob")

;; Here is a simple function, notice that it does not
;; refer to other non standard functions or other local variables
(defun hello (name)
(format "Hello, %s!" name))


(defun my-async-function ()
(async-start
;; notice the backquote!
`(lambda ()
;; in our async lambda we dont use the local `myvar' variable,
;; instead we are replacing it with the current local value of `myvar'
(set 'myvar ,myvar)
;; we can also do this by actually obtaining the lambda expression
;; behind `hello' and putting that inside our lambda
(fset 'hello ,(symbol-function 'hello))
;; then we wait!
(sit-for 1)
;; now we are modifiying the async copy of `myvar'
(setq myvar (concat myvar " Johnson"))
;; here we want the result of the async lambda to be a call to our
;; `hello' function, but we also want to update our local version
;; of myvar with its value in th async process, so we will return
;; a list of both values which we can handle in our callback
(list myvar (hello myvar)))

(lambda (result)
;; once we get the results we'll update our local version of `myvar'
;; with the value returned by the async function
(setq myvar (first result))
;; then we can print out the message we recieved from the output
;; of our async `hello' call.
(message "The new value myvar is: %s\nThe result of the function was: %s"
myvar
(second result)))))


;; executed top down, the async callback will message:

;;The new value myvar is: Bob Johnson
;;The result of the function was: Hello, Bob Johnson!

我已经抽象出了使用宏将值和变量替换为立即值的概念:value-bound-lambda,您可以获取宏并在此处查看示例:

value-bound-lambda example

关于asynchronous - Emacs Lisp中async.el说 "Symbol'的函数定义无效的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22842554/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com