我一直想弄清楚如何处理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返回一个字符串,但是我猜测”实际上返回了值零,字符串只是放在终端上的一些垃圾...但我不明白。 有人有见识吗?或这种疯狂的方法?
答案 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
的主体因此是一系列语句。在您的示例中,有三个分别以for
,with
和collect
开头。
所有这些对于初学者来说都是一个困惑。
例如,您看到令牌=,然后在手册中进行查找。您会找到一个用于测试数值相等性的函数。但是在循环宏内部,在for
语句内部,它是循环宏正在使用的小语法的一部分
该FOR子句将安排将词法变量line
绑定到每次在循环中调用(read-line stream nil)
的结果。
这里的另一个混乱之处是READ-LINE
函数将流与一些可选参数一起使用。这里仅提供一个,即无。该参数控制read-line
到达文件末尾时发生的情况。 Nil
抑制了自然会引起的错误,而是要求它返回值NIL。
这似乎有点奇怪,因为在大多数情况下,读取行返回一个string
时,此可选参数已授权它返回两种类型:string
或null
。
while
子句对此进行处理,当我们得到类型为null
的值,即nil值时,终止循环。
collect
子句很有趣,因为它为循环的作者做了很多工作。它神奇地在循环中创建状态以将单个行累积到列表中,然后在循环退出时返回该列表。循环宏的典型实现将非常有效地完成此操作。
这时,学习语言喃喃地说“ wtf?这似乎不太像Lisp吗?!?”是一种普遍的反应。尽管很公平,loop
非常有用,并且有很多使用它的代码。
还有其他选择,例如iterate
(这不是标准的一部分)和series
(这是后来的增加)。但是两者在各自的方式上都有些奇怪/聪明。