📗
elisp manual zh
  • LAND OF LISP
  • 引言
  • 进度 & 计划
  • 一些记录
  • Lisp 数据类型
    • 2 Lisp 数据类型
    • 2.1 打印表示 和 读取语法
    • 2.2 特定的读取语法
    • 2.3 注释
    • 2.4 编程类型
      • 2.4.1 整型
      • 2.4.2 浮点型
      • 2.4.3 字符型
        • 2.4.3.1 基本字符语法
        • 2.4.3.2 通用转义语法
        • Page 2
        • Page 3
        • Page 4
        • Page 1
      • 2.4.4 符号类型
      • 2.4.5 序列类型
      • 2.4.6 点对类型
        • 2.4.6.1 点对可视化
        • 2.4.6.2 点对记法
        • 2.4.6.3 关联列表
      • 2.4.7 数组类型
      • 2.4.8 字符串类型
        • 2.4.8.1 字符串的语法
        • 2.4.8.2 字符串中的非ASCII码
        • 2.4.8.3 不可打印字符
        • 2.4.8.4 字符串的文本属性
      • 2.4.9 向量类型
      • 2.4.10 字符表类型
      • 2.4.11 布尔向量类型
      • 2.4.12 哈希映射类型
      • 2.4.13 函数类型
      • 2.4.14 宏类型
      • 2.4.15 原函数类型
      • 2.4.16 字节码类型
      • 2.4.17 记录类型
      • 2.4.18 类型描述符
      • 2.4.19 自动加载类型
      • 2.4.20 终止类型
    • 2.5 编辑类型
      • 2.5.1 缓冲区变量
      • 2.5.2 标记类型
      • 2.5.3 窗口类型
      • 2.5.4 框架类型
      • 2.5.5 终端类型
      • 2.5.6 窗口配置类型
      • 2.5.7 框架配置类型
      • 2.5.8 进程类型
      • 2.5.9 线程类型
      • 2.5.10 互斥锁类型
      • 2.5.11 条件变量类型
      • 2.5.12 流类型
      • 2.5.13 按键映射类型
      • 2.5.14 覆盖类型
      • 2.5.15 字体类型
    • 2.6 循环结构对象
    • 2.7 类型谓语
    • 2.8 相等谓语
    • 2.9 可变性
  • 数字
    • 3.1 整型数
    • 3.2 浮点型基础
    • 3.3 谓词:数字相关
    • 3.4 数字比较
    • 3.5 数字类型转换
    • 3.6 数学变换
    • 3.7 取整
    • 3.8 位运算
    • 3.9 数学函数
    • 3.10 随机数
  • 字符串 和 字符
    • 4 字符串和字符
    • 4.1 字符串基础
    • 4.2 谓语:字符串相关
    • 4.3 创建字符串
    • 4.4 修改字符串
    • 4.5 字符串比较
    • 4.6 字符串转换
    • 4.7 字符串格式化
    • 自定义格式化
    • Case Conversion
    • Case Table
  • 列表
    • 5 列表
    • 5.1 列表与点对
    • 5.2 列表相关的谓词
    • 5.3 列表元素的存取
    • 5.4 列表与点对的构建
    • 5.5 列表变量的修改
    • 5.6 列表结构的修改
    • 5.7 列表和集合的使用
    • 5.8 关联列表 Association Lists (alist)
    • 5.9 属性列表 Property Lists (plist)
  • 序列, 数组, 和 向量
    • 6 序列、数组、以及向量
    • 6.1 序列
    • 6.2 数组
    • 6.3 数组相关函数
    • 6.4 向量
    • 6.5 向量相关函数
    • 6.6 字符表
    • 6.7 布尔向量
    • 6.8 大小固定的对象环的管理
  • 记录
    • 7 记录
    • 7.1记录相关函数
    • 7.2 向后兼容
  • 哈希表
    • 8 哈希表
    • 8.1 哈希表创建
    • 8.2 哈希表存取
    • 8.3 哈希表定制
    • 8.4 其他哈希表相关函数
  • 符号
    • 9 符号(3/4)
    • 9.1 符号的组成(DONE)
    • 9.2 定义符号(DONE)
    • 9.3 创建(Creating)并注册(Interning)符号(DONE)
    • 9.4 符号属性
      • 9.4.1 存取符号属性(DONE)
      • 9.4.2 标准符号属性
  • 求值
    • 10 求值(DONE)
    • 10.1 表达式类型(DONE)
      • 10.2.1 自求值表达式(DONE)
      • 10.2.2 符号表达式(DONE)
      • 10.2.3 列表表达式(DONE)
      • 10.2.4 函数符号转义(DONE)
      • 10.2.5 函数表达式求值(DONE)
      • 10.2.6 Lisp 宏求值(DONE)
      • 10.2.7 特殊表达式(DONE)
      • 10.2.8 自动加载(DONE)
    • 10.2 引用(Quoting)(DONE)
    • 10.3 反引用(DONE)
    • 10.4 Eval(求值)(DONE)
    • 10.5 延迟求值(DONE)
  • 控制结构
    • 11. 控制结构
    • 11.1 顺序执行(DONE)
    • 11.2 条件判断(DONE)
    • 11.3 条件组合结构(DONE)
    • 11.4 模式匹配(TODO)
    • 11.5 迭代(DONE)
    • 11.6 生成器(DONE)
    • 11.7 非局部退出
      • 11.7.1 显式非局部退出:catch 和 throw
      • 11.7.2 catch 和 throw 的例子
      • 11.7.3 错误
        • 11.7.3.1 如何传递出一个错误
        • 11.7.3.2 Emcas 的错误处理流程
        • 11.7.3.3 编写错误处理函数
        • 11.7.3.4 错误符号和条件名
      • 11.7.4 非局部退出后的清理工作
  • 变量
    • 12 变量
    • 12.1 全局变量
    • 12.2 常量变量
    • 12.3 局部变量
    • 12.4 无效(Void)变量
    • 12.5 定义全局变量
    • 12.6 定义变量的建议
    • 12.7 变量获取
    • 12.8 变量设置
    • 12.9 变量监视
      • 12.9.1 限制
    • 12.10 变量作用域规则
      • Untitled
      • 12.10.1 动态绑定
      • 12.10.2 动态绑定的建议
      • 12.10.3 词法绑定
      • 12.10.4 如何正确的使用词法绑定
    • 文件变量
    • 目录变量
    • 通信变量
    • 变量别名
    • 变量限制
    • 泛型变量
  • 函数
    • 13 函数
    • 13.1 函数是什么?(DONE)
    • 13.2 Lambda 表达式(WORKING)
      • 13.2.1 lambda表达式的组成部分
      • 13.2.2 一个简单的lambda表达式例子
      • 13.2.3 参数列表的特性
      • 13.2.4 函数的文档字符串
    • 13.3 函数命名
    • 13.4 函数定义
    • 13.5 函数调用
    • 13.6 函数映射式调用
    • 13.7 匿名函数
    • 13.8 泛型函数
    • 13.9 读取函数槽信息
    • 13.10 闭包
    • 13.11 Emacs Lisp 函数最佳实践
    • 13.12 声明废弃函数
    • 13.13 内联函数
    • 13.14 declare 表达式
    • 13.15 告知编译器某函数已定义
    • 13.16 函数安全调用
    • 13.17 有关函数的其他主题
  • 宏
    • Untitled
  • 自定义设置
  • 加载脚本
  • 字节码编译
  • 调试 Lisp 代码
  • 读取和打印
    • 19.1 读取与打印简介
    • 19.2 输入流
    • 19.3 输入函数
    • 19.4 输出流
    • 19.5 输出函数
    • 19.6 输出变量
  • Mini Buffer
  • Loop 循环
  • 按键绑定
  • Modes
  • 23.1 钩子
    • 23.1.1 运行钩子
    • 23.1.2 设置钩子
  • 23.2
  • Untitled
  • Untitled
  • Untitled
  • Untitled
  • 文档
    • Untitled
  • 文件访问
    • Untitled
  • 备份 及 自动保存
    • Untitled
  • Buffers
    • Untitled
  • 窗口
    • Untitled
  • 框架
    • Untitled
  • 位置
    • Untitled
  • 标记
    • Untitled
  • 文本
    • 32 文本
      • 32.1 位置点附近 (Near Point)
      • 32.2 缓冲区内容 (Buffer Contents)
  • 非 ASCII 字符
    • Untitled
  • 搜索 和 匹配
    • Untitled
  • 语法表
    • Untitled
  • 缩写 及 缩写拓展
    • 34 搜索 与 替换
      • 34.1 文本搜索
  • 进程
    • Untitled
  • 线程
    • Untitled
  • Emacs 显示
    • Untitled
  • 操作系统接口
    • Untitled
  • 标准错误
    • Untitled
  • 标准按键映射
    • Untitled
  • 标准 Hooks
    • Untitled
  • Tip & Conventions
    • Untitled
  • 索引
    • Untitled
  • 附录
    • Untitled
    • 附录 H: 标准钩子
由 GitBook 提供支持
在本页

这有帮助吗?

  1. 求值

10.4 Eval(求值)(DONE)

绝大多数情况下,在运行时,表达式会自动进行求值。但在少数情况下,你可能需要写运行时求值的表达式,比如在读取一段文本或从属性列表中获取文本后,你想将这段文本作为代码执行,此时,你使用函数 eval。通常的编码并不需要使用 eval,而应该使用其他函数。举个例子,获取某个变量的值,你应当使用 symbol-value,而不应该使用 eval,即便 eval 也可行。在举个例子,我们可以将表达式储存在属性列表中,然后使用 eval 调用,但是更好的做法是 将表达式转换成函数储存起来,然后使用 funcall 调用。

本节介绍的函数和变量都和表达式求值有关,它们有的指明了求值的限制,有些保存了最近一次的求值记录。加载文件同样设涉及求值(查阅 加载)。

通常将函数储存在数据结构中,使用 funcall 或 apply 调用 会比 将表达式储存在数据结构中然后直接求值 更加简洁灵活。函数提供了一种将信息作为参数传入的能力。

Function: eval form &optional lexical

这个函数是对表达式求值的最基础函数。它会在当前环境下,对表达式求值,然后返回求值结果。表达式的具体求值方式取决于表达式本身,详情查阅 表达式。

参数 lexical 指明了局部变量语法绑定的规则。如果该参数被省略,或为 nil,这意味着这个表达式使用默认的动态绑定规则。如果为 t,则使用词法绑定。参数 lexical 同样可以为一个非空alist,用来指明语法环境或语法绑定方式;不过这个特性仅在某些特定时候有用,比如在 Emacs Lisp 调试器里。详情查阅语法绑定。

由于 eval 是一个函数,因此其参数会被求值两次:第一次发生在 eval 调用前,参数求值中,第二次发生在 eval 的作用下。这里有个例子:

(setq foo 'bar)
     ⇒ bar
(setq bar 'baz)
     ⇒ baz
;; Here eval receives argument foo
(eval 'foo)
     ⇒ bar
;; Here eval receives argument bar, which is the value of foo
(eval foo)
     ⇒ baz

当前动作调用 eval 的最多次数由遍历 max-lisp-eval-depth 限制(见下文)

Command: eval-region start end &optional stream read-function

这个命令会在当前缓冲区中,从位置 start 读取文本,eval,直到 位置 end,或出现错误。

默认情况下,这个命令并不产生输出。如果参数 stream 为非nil,那么任何由输出函数(详情查阅输出函数)产生的输出,包括过程中的求值结果,都会使用 stream 打印出来。(详情查阅 输出流)

参数 read-function 应为 nil 或函数,用来取代默认的读取函数 read,来读取表达式。这个函数应当接受,读取的流作为其参数。你也可以通过设置 load-read-function 变量来改变输入(详情查阅 程序如何加载),不过使用 read-function 参数会更具鲁棒性。

eval-region 并不会改变位点,而且永远返回 nil。

Command: eval-buffer &optional buffer-or-name stream filename unibyte print

这个命令和 eval-region 很像,但是提供了一些不同的参数以实现不同特性。eval-buffer 作用在名称为 buffer-or-name 的缓冲区上(查阅 The GNU Emacs Manual中的变窄章节)。buffer-or-name 可以为一个缓冲区对象,也可以是缓冲区名称(字符串),也可以省略(nil),省略意味着传入当前缓冲区。参数 stream 和 eval-region 中很像。但 stream 为 nil,而 print 为 non-nil 时,求值会被丢弃,但由输出函数产生的输出会返回到回显区。filename 指明用于 load-history 的文件名(查阅 卸载),默认使用 buffer-file-name的值(查阅缓冲区文件名称)。如果参数 unibyte 为非nil,read 会将字符串转换为 unibyte。

eval-current-buffer 是该命令的一个别名。

User Option: max-lisp-eval-depth

这个变量定义了调用 eval,apply 以及 funcall 的最大深度。超过最大深度会抛出 “Lisp nesting exceeds max-lisp-eval-depth" 错误。

这个限制和一个错误联系在一起。这是 Emacs Lisp 检测由病态函数 造成的无限递归的一种手段。如果你讲这个变量的值设置的很大,那么代码可能会抛出 栈溢出 错误。在一些系统中,这种溢出错误可以被处理掉。这种情况下,通常求值器会终止,然后返回顶层命令循环(top-level)。注意,这种情况下没有办法进入 Emacs Lisp 调试器。查阅 错误调试。

这个深度限制与 eval ,apply,和funcall 的使用密切相关,比如 调用函数,递归求值,显式调用等等。

默认值为 800。如果你将这个变量设置为 100 以下的值,Lisp 会在达到数值时,重新将其设置为 100。进入 Lisp 调试器会增加这个值,以确保调试器可以正常运作。

max-specpdl-size 是提供了另一种限制,查阅 局部变量。

Variable: values

这个变量的值是一个列表,其内容为表达式历史:那些曾经由 Emacs 标准命令读取,求值,打印到缓冲区的表达式。(这里不包括 *ielm* 缓冲区,也不包括 C-j,C-x,C-e调用的函数,以及 lisp-interaction-mode 中的求值命令)这些记录会按照顺序排列。

(setq x 1)
     ⇒ 1
(list 'A (1+ 2) auto-save-default)
     ⇒ (A 3 t)
values
     ⇒ ((A 3 t) 1 …)

在查询最近使用的表达式时,这个变量很有用。不过打印这个变量通常不是个好主意,因为它太长了。相反的,你应该检查某些特定的元素,就像下面这样:

;; Refer to the most recent evaluation result.
(nth 0 values)
     ⇒ (A 3 t)
;; That put a new element on,
;;   so all elements move back one.
(nth 1 values)
     ⇒ (A 3 t)
;; This gets the element that was next-to-most-recent
;;   before this example.
(nth 3 values)
     ⇒ 1
上一页10.3 反引用(DONE)下一页10.5 延迟求值(DONE)

最后更新于2年前

这有帮助吗?