19.2 输入流
绝大多数用于读取文本的 Lisp 函数都可以接受一个 input stream 作为参数。输入流指明了,从什么地方,以及如何读取文本中字符。这里列举了一下可以作为输入流的对象类型:
buffer(缓冲区)
输入字符来自于缓冲区 buffer,从位点开始。其中位点处于待读取字符的前面一格。
marker(标记)
输入字符来自于标记 marker 所在缓冲区,从标记开始。曲中标记处于待读取字符的前面一格。将标记作为流并不会对标记的值产生副作用。
string(字符串)
输入字符来自于字符串 string,从字符串的第一个字符开始,并尽可能贪婪的读取字符。
function(函数)
输入字符由函数 function生产,这个函数必须满足以下两点:
该函数被无参调用时,应当返回下一个待读取的字符。
该函数被单参调用时(通常参数为单个字符),函数应该保存参数,并将其整理,用于下一次的调用。这个行为称为预读取(unreading)字符;预读取通常发生在这种情况:Lisp 读取器 多次读取单个字符,并想将其重新放回原流。这种情况下,函数返回值将不那么重要。
t
t 用于表示从 minibuffer 中读取。实际上,minibuffer 仅会被调用一次,将用户的输入处理为一个字符串,再将该字符串作为输入流。如果 Emacs 在 批处理模式(查阅 批处理模型) 下运行,那么将会使用标准输入,而不是minibuffer。例如在批处理模式下,
将会从标准输入读取 Lisp 表达式,然后将结果打印到标准输出。
nil
nil 表示使用变量 standart-input 的值作为输入流;这个值通常是默认的输入流,而且必须为 非nil 输入流。
symbol
当一个符号作为输入流时,Emacs 会检查其函数定义,并将该定义作为输入流。
这里有个例子,展示了将缓冲区 buffer 作为输入流时,对位点的副作用:
请注意,第一次读取时,跳过了一个空格。读取会跳过关键文本前的适量空格。
这里有一个将标记 marker 作为输入流的例子,其读取到的值为一个符号 This。
这里例子里,我们读取一个字符串:
下面这个例子,我们从 minibuffer 中读取内容。其中" Lisp expression:"是提示语。(当你从流 t 中读取时,总是会有提示语)用户的输入紧跟在提示语。
最后这个例子中,我们从将函数作为输入流。这个函数名称为 useless-stream。在读取前,我们需要初始化变量 useless-list。之后每一次对函数 useless-steam的调用,都会从该 变量 中获取下一个字符。
现在,让我们从流中读取数据:
请注意,开闭括号仍在 list 中。Lisp 读取器会对开括号进行计数,以此判断输入何时结束,并停止读取。你可以尝试另一个例子,读取"()"将会返回nil。
最后更新于
这有帮助吗?