Loops 对var=`语法的公共LISP`loop感到困惑
我查看了关于如何循环文件的帖子。我在网上查看了几个地方,试图了解这里再次发布的代码中发生了什么:Loops 对var=`语法的公共LISP`loop感到困惑,loops,common-lisp,Loops,Common Lisp,我查看了关于如何循环文件的帖子。我在网上查看了几个地方,试图了解这里再次发布的代码中发生了什么: (defun get-file (filename) (with-open-file (stream filename) (loop for line = (read-line stream nil) while line collect line))) 这种语法似乎很晦涩难懂,参考文献也不容易理解。根据参考文献“七个语法中的第四个用于/作为语法
(defun get-file (filename)
(with-open-file (stream filename)
(loop for line = (read-line stream nil)
while line
collect line)))
这种语法似乎很晦涩难懂,参考文献也不容易理解。根据参考文献“七个语法中的第四个用于/作为语法”,语法为:
对于var[type spec]=expr1[then expr2]
如果没有expr2,则使用expr1
什么让我困惑:
我听不懂台词,不知道该问什么,除了它是如何工作的:
while line
collect line
我不知道如何用其他代码替换它。它看起来根本不像一个列表。我的直觉告诉我,它应该看起来像:
(while line (collect line))
还有,这不也和:
while line collect line
expr1是什么
或
如果我有更多的代码而不是收集行
?没有名单吗?我看不到结构
我知道这些问题不止一个,但我可能遗漏了一些大问题,使我无法提出一个好问题。这是一个循环。运行多次的东西 循环基本上有两个部分:
line
,以及它会发生什么:在每个循环迭代中line
被设置为表达式(read line stream nil)
的求值结果。这意味着一行一行地读line
不是nil
就将line
的值收集到一个列表中(读取行流nil)
表单返回nil
,而则看到行
为nil
nil
为false,因此循环终止。然后,到目前为止收集的行将作为结果返回
整个循环
表单返回收集的行列表
这里的循环
很方便,因为:
- 它有条件地收集一个值
- 我们不需要给结果列表一个变量名,因为只有一个累加:单个
collect…
子句
- 结果列表按正确的顺序返回:第一个收集的项是返回列表中的第一个元素
背景
一般来说,LOOP
是一个宏,它基于70年代早期Interlisp的类似FOR
宏。在那里引入了一个想法,使程序结构可以像普通英语一样使用:用于列表中的项收集项。这被称为会话Lisp。例如,苹果公司的简单脚本语言Applescript也使用了类似的思想。这种风格在Lisp中从来都不是很流行(尽管还有其他宏使用它),但是循环
宏仍然存在,因为它被证明是有用的
我的直觉告诉我,它应该看起来像:
(while line (collect line))
(当线路(收集线路))
因此,您可能会喜欢Shinmera的宏:
至少需要知道的是,for…over
,其中over是泛型的,它适用于许多数据类型
(for:for ((a over '(1 2 3))
(b over #(a b c))
(c over (for:for ((table as (make-hash-table)))
(setf (gethash (random 10) table) (random 10)) (repeat 3)))
(d over *package*)
(e over *random-state*)
(f over (directory (merge-pathnames "*.*" (user-homedir-pathname))))
(g over (make-string-input-stream "Hi!")))
(print (list a b c d e f g)))
扩展的循环
宏为编写循环定义了自己的特定于域的语言,因此语法不同于常规的公共Lisp。试着读一下,特别是这一章,我已经查过了。这篇文章没有详细说明表格。你读了整个章节了吗?“等于然后迭代”、“终止测试”和“值累积”部分应解释
,分别在和收集时。:收集行:和:do表达式…
。循环是它自己的语言,非常非lispy语法。了解所有这些是非常复杂的,所以喜怒无常的人知道其中的一个子集。它是CL独有的,所以其他Lisp中类似的代码看起来非常不同。是的,我读过。我对收集一点也不感兴趣,我发现它缺乏对某些理论的解释,这是有充分理由的。毕竟它是“实用的”。请看雷纳回答中的评论。我们得到了一些信息,谢谢你的背景信息。我现在明白了collect和while是特定于循环的。为什么我不能这样做:例如,whileline(格式t“找到一行”)。我不知道如何在读取行上操作。@Makketronix如果您不想收集
某些内容,您可以执行
某些内容:而行执行(打印“找到一行”)
啊哈。那么为什么(格式t“找到一行”)不起作用呢?使用collect这个词,把我搞糊涂了。@Makketronix:它确实管用。正如我说的,你需要在它前面写do
。子句是由while、until、when、除非、collect、sum、do、maximize和其他词引入的……的确,在我重新启动环境之后。。。谢谢。这就是为什么我越来越喜欢口齿不清,而不一定是“口齿不清”的原因。
(for:for ((a over '(1 2 3))
(b over #(a b c))
(c over (for:for ((table as (make-hash-table)))
(setf (gethash (random 10) table) (random 10)) (repeat 3)))
(d over *package*)
(e over *random-state*)
(f over (directory (merge-pathnames "*.*" (user-homedir-pathname))))
(g over (make-string-input-stream "Hi!")))
(print (list a b c d e f g)))