Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 为什么有一个=sign-in循环宏用于从文件中读取行?_Loops_Syntax_Common Lisp - Fatal编程技术网

Loops 为什么有一个=sign-in循环宏用于从文件中读取行?

Loops 为什么有一个=sign-in循环宏用于从文件中读取行?,loops,syntax,common-lisp,Loops,Syntax,Common Lisp,我一直在试图弄清楚如何用公共lisp处理读取文件,因为答案看起来总是完全一样的,我不理解lisp的循环宏语法或其他相关内容。 在下面的代码中(从您看到的代码中有一个“loop for line=(read line)…”我不明白numeric=符号在测试中的含义。为什么是数字等号?read line返回什么数字?是nil和t数字吗 (defun get-file (filename) (with-open-file (stream filename) (loop for line =

我一直在试图弄清楚如何用公共lisp处理读取文件,因为答案看起来总是完全一样的,我不理解lisp的循环宏语法或其他相关内容。 在下面的代码中(从您看到的代码中有一个“loop for line=(read line)…”我不明白numeric=符号在测试中的含义。为什么是数字等号?read line返回什么数字?是nil和t数字吗

(defun get-file (filename)
  (with-open-file (stream filename)
    (loop for line = (read-line stream nil)
          while line
          collect line)))
我总是直觉地认为“(行中的循环(读行)…”会起作用,因为读行返回一个字符串,但我猜它实际上返回nil的值,而字符串只是它放在终端上的一些垃圾…但我不明白。 有人对这种疯狂有见解或方法吗?

开始一个Lisp表单

循环

这是
循环

对于行=(读取行流nil)

我们定义一个局部变量
line
,在每次
循环
迭代中,它将被设置为
(读取行流nil)
的结果

(读取行流nil)
以字符串形式返回行,或者
nil
如果流处于eof

而行

每次迭代时检查此项,并在变量
line
不是
nil

如果是
nil
,则退出
循环
,并返回结果

收集行

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


Lisp表单的结尾

循环宏在普通Lisp中是唯一的,也就是说,它是唯一定义自己的完整小语法的宏。这种语法更像是在Algol、Pascal、C或Python语言规范中遇到的语法。循环宏对其进行解析,并将其转换为更标准的Lisp表单

因此,
循环的主体是一系列语句。在您的示例中,有三个分别以
for
with
collect
开头

所有这些都是初学者困惑的根源

例如,您可以看到标记=,然后在手册中查找它。您可以找到一个用于测试数值相等性的函数。但是在循环宏中,
For
语句中,它是循环宏使用的小语法的一部分

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

这里的另一个混乱来源是
READ-LINE
函数接受一个流以及一些可选参数。这里只提供了一个,即nil。该参数控制
READ-LINE
到达文件末尾时发生的情况。
nil
抑制它自然引发的错误,并要求它执行返回值NIL

这似乎有点奇怪,因为虽然大多数时候读取行返回一个
字符串
,但此可选参数允许它返回两种类型:
string
null

while
子句处理这个问题,当我们得到类型为
null
的值,即nil值时终止循环

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

在学习这门语言的过程中,经常会有这样的反应:“wtf?这看起来不像Lisp?!?”虽然这很公平,但是循环非常有用,有很多代码都在使用它


还有其他选择,例如
iterate
(这不是标准的一部分)和
series
(这是一个后期添加)。但两者都有点奇怪/聪明。

循环
宏是一个用于迭代的DSL。它的语法通常被认为不清晰,但我已经习惯了。
=
与数值无关,只是一个赋值运算符,它将
读取行
的返回值绑定到
。我想我这只是一个习惯的问题,或者尝试一个简单的“do”循环。除了Rainer的答案之外,你还可以找到一个很好的介绍@MartinBuchmann你的第一条评论实际上是我在页面上的问题的唯一正确答案。它消除了根本的误解。循环中的=关键字与普通Lisp中的=函数具有不同的语义。我误解了,以为它们是相同的(或相似的)。我希望我可以标记一条注释作为答案!(我回到这个问题,因为它仍然没有标记为已回答)系列没有添加到标准中,即使它在CLtL2中。