为什么在循环宏中有一个=符号,用于从文件中读取行?

时间:2019-07-16 04:14:13

标签: loops syntax common-lisp

我一直想弄清楚如何处理common-lisp中的文件读取问题,因为答案似乎总是完全相同,而且我不理解lisp的循环宏语法或类似内容。 在下面的代码中(从this stackexchange answer for example中,您看到有一个“ line =(read-line)的循环...”。我不明白数字=符号在测试中的含义。为什么它是数字等号吗?读行返回什么数字?Nil和T是数字吗?

(defun get-file (filename)
  (with-open-file (stream filename)
    (loop for line = (read-line stream nil)
          while line
          collect line)))

我总是凭直觉认为“((loop for line in(read-line)...)”会起作用,因为read-line返回一个字符串,但是我猜测”实际上返回了值零,字符串只是放在终端上的一些垃圾...但我不明白。 有人有见识吗?或这种疯狂的方法?

2 个答案:

答案 0 :(得分:3)

启动Lisp表单

循环

这是@override Widget build(BuildContext context) { switch (authStatus) { case AuthStatus.notSignedIn: return new LoginPage( auth: widget.auth, onSignedIn: _signedIn, ); case AuthStatus.signedIn: return new HomePage( auth: widget.auth, onSignedOut: _signedOut, ); } }

for line =(读取行流为零)

我们定义一个局部变量LOOP,在每次line迭代中,它将被设置为loop的结果。

(read-line stream nil)以字符串形式返回一行,如果流在eof处则返回(read-line stream nil)

边线

在每次迭代中都检查一下,并在变量nil不是line的情况下保持迭代

如果它是nil,则从nil退出并返回结果。

收集行

对于每次迭代,将变量loop的内容收集到一个列表中,然后可以作为结果返回。

Lisp表单的结尾

答案 1 :(得分:3)

循环宏在Common Lisp中是唯一的,即它是唯一定义它自己的宏-啊-整个小语法。这种语法更像您在Algol,Pascal,C或Python语言规范中遇到的东西。循环宏对此进行解析,并将其转换为更标准的Lisp形式。

loop的主体因此是一系列语句。在您的示例中,有三个分别以forwithcollect开头。

所有这些对于初学者来说都是一个困惑。

例如,您看到令牌=,然后在手册中进行查找。您会找到一个用于测试数值相等性的函数。但是在循环宏内部,在for语句内部,它是循环宏正在使用的小语法的一部分

该FOR子句将安排将词法变量line绑定到每次在循环中调用(read-line stream nil)的结果。

这里的另一个混乱之处是READ-LINE函数将流与一些可选参数一起使用。这里仅提供一个,即无。该参数控制read-line到达文件末尾时发生的情况。 Nil抑制了自然会引起的错误,而是要求它返回值NIL。

这似乎有点奇怪,因为在大多数情况下,读取行返回一个string时,此可选参数已授权它返回两种类型:stringnull

while子句对此进行处理,当我们得到类型为null的值,即nil值时,终止循环。

collect子句很有趣,因为它为循环的作者做了很多工作。它神奇地在循环中创建状态以将单个行累积到列表中,然后在循环退出时返回该列表。循环宏的典型实现将非常有效地完成此操作。

这时,学习语言喃喃地说“ wtf?这似乎不太像Lisp吗?!?”是一种普遍的反应。尽管很公平,loop非常有用,并且有很多使用它的代码。

还有其他选择,例如iterate(这不是标准的一部分)和series(这是后来的增加)。但是两者在各自的方式上都有些奇怪/聪明。