Asynchronous async.el say“的原因是什么;符号';s函数定义为void“;在Emacs Lisp中

Asynchronous async.el say“的原因是什么;符号';s函数定义为void“;在Emacs Lisp中,asynchronous,emacs,Asynchronous,Emacs,我在elisp中使用async调用async函数 首先,我在github中测试自述代码,它运行良好 然后我编写了一个测试代码: (defun async-function () (async-start ;; What to do in the child process (lambda () (shell-command-to-string "~/test.sh")) ;; What to d

我在elisp中使用async调用async函数

首先,我在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
我使用
自动加载
函数加载函数文件,但结果显示找不到该文件


我不知道会发生什么以及如何修复。

async.el通过生成另一个Emacs进程来计算表达式。在本例中,您在主Emacs进程中定义了测试函数,但异步Emacs进程无法访问主进程中的函数和变量。如果要为异步调用指定要使用的函数,请将它们放在一个文件中,然后将该文件加载到异步函数中。但请记住,变量等不会转移

下面是一个示例,它位于一个文件中:

;;~/。emacs.d/my-functions.el
(defun测试()
(坐2分钟)
“你好,世界!”)
这是另一个地方:

;;其他地方
(异步启动
(lambda()
(加载文件“~/.emacs.d/my functions.el”)
(测试)
(兰姆达(结果)
(消息“结果:%s”结果));;你会向世界问好吗
关于共享变量,异步不支持这一点。您不能启动一个异步函数,该函数不断修改变量,并期望在主emacs进程上访问该变量,或者甚至只是将该变量传递到异步lambda中,因为符号在新进程上不存在时才会计算

我们可以利用Lisp的backquote语法将变量按值传递到异步函数中。下面是在异步函数中使用局部变量和函数的一种非常简单的方法

;;我们将声明一个局部变量“myvar”
(setq myvar“Bob”)
;; 这是一个简单的函数,请注意它不是
;; 参考其他非标准函数或其他局部变量
(德芬你好(姓名)
(格式为“Hello,%s!”name))
(取消我的异步函数()
(异步启动
注意倒引号!
`(lambda()
;在异步lambda中,我们不使用局部“myvar”变量,
;相反,我们用当前本地值“myvar”替换它
(设置“myvar,myvar”)
我们也可以通过实际获得lambda表达式来实现这一点
在“你好”后面,把它放进我们的lambda里
(fset'hello,(符号函数'hello))
然后我们等待!
(坐1分钟)
;现在我们正在修改“myvar”的异步副本
(setq myvar(concat myvar“约翰逊”))
在这里,我们希望异步lambda的结果是对
“hello”函数,但我们还想更新本地版本
在异步进程中使用myvar的值,因此我们将返回
;我们可以在回调中处理的两个值的列表
(列出myvar(hello myvar)))
(兰姆达(结果)
;一旦得到结果,我们将更新本地版本的“myvar”
;;使用异步函数返回的值
(setq myvar(第一个结果))
然后我们可以打印出从输出中收到的消息
我们的异步“hello”调用的。
(消息“新值myvar为:%s\n函数结果为:%s”
迈瓦尔
(第二个结果((())))
;; 自上而下执行时,异步回调将显示以下消息:
;;新的myvar值是:Bob Johnson
;;函数的结果是:你好,鲍勃·约翰逊!
我已经抽象出了用宏替换变量和函数的概念:值绑定lambda,你可以得到宏并在这里看到一个例子:


我只想分享一种使用
异步运行自定义函数的技术,而不想硬编码文件路径。假设我想运行文件
my custom.el
中的函数
my custom函数
(即“~/emacs.d/my custom/my custom.el”)。因此,
符号文件
将返回定义函数的文件名,
文件名目录
将返回其父目录

(let ((script-filename (file-name-directory (symbol-file 'my-custom-function))))
    (async-start
     `(lambda()
        (add-to-list 'load-path ,script-filename)
        (require 'my-custom)
        (my-custom-function)
    ....

我相信你在(测试)后错过了一个关闭lambda的paren。