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 对var=`语法的公共LISP`loop感到困惑_Loops_Common Lisp - Fatal编程技术网

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)))