Common Lisp Loop宏变量绑定

Kar*_*rma 2 loops common-lisp

我在理解with关键字的工作原理时遇到了问题.特别是,我认为它与let声明相同但不遵循.

例如,这两个代码"应该"打印相同的值,但第一个给出,(nil nil)而后者工作正常.

(loop for c in clauses
    with p = (car c)
    collect p)

(loop for c in clauses
    collect (car c))
Run Code Online (Sandbox Code Playgroud)

Syl*_*ter 8

with是创建局部辅助变量.它们在循环开始之前初始化一次,因此与写这个相同:

(let ((p (car c))
  (loop for c in clauses
    collect p))
Run Code Online (Sandbox Code Playgroud)

除了它似乎与我同时c存在的事实.我认为这是因为我在这里创建了所有变量.nil(car c)loopp

您正在寻找for:

(loop 
  for c in clauses
  for p = (car c)
  collect p)
Run Code Online (Sandbox Code Playgroud)

为什么不用解构呢?:

(loop 
  for (p) in clauses
  collect p)
Run Code Online (Sandbox Code Playgroud)


Rai*_*wig 5

有助于理解LOOP更好的一件事是a LOOP有三个不同的子句部分

(loop

  ; first a single optional NAME clause

  ; then zero or more variable clauses with WITH, INITIAL, FINALLY and/or FOR

  ; then zero or more main clauses with DO, RETURN, COLLECT, APPEND, SUM, NCONC, ...
  )
Run Code Online (Sandbox Code Playgroud)

必须保持这些条款部分的顺序.

有两种方法可以引入变量:FORWITH.FOR在每次迭代中更新变量,并且WITH只执行一次.您可以在正确的部分中以任何顺序编写这些子句,但通常WITH会在FOR变量具有正确值之前创建绑定及其值 - 尽管并非总是如此.

LispWorks警告您的具体代码:

CL-USER 6 > (loop for c in '((1) (2) (3))
                  with p = (car c)
                  collect p)

Warning: Local Variable Initialization clause
  (the binding of P) follows iteration forms but will be evaluated before them.

(NIL NIL NIL)
Run Code Online (Sandbox Code Playgroud)

经常

(loop for c in clauses
    with p = (car c)
    collect p)
Run Code Online (Sandbox Code Playgroud)

将通过以下方式实现:

(...
   (let ((c nil) ...)
     (let ((p (car c)))   ; your (CAR ...)  form

        ; iteration code ...

     )))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,你有一些"运气",因为(car nil)恰好工作,只有结果不是你所期望的 - 默默地.

但这会产生错误:

(loop for c in '((1) (2) (3))
      with p = (1+ c)    ; note the 1+ instead of CAR
      collect p)
Run Code Online (Sandbox Code Playgroud)

这里(1+ nil)不起作用,将是一个错误,因为该函数1+只接受数字作为参数.您不会看到意外的结果,但会出现错误.

风格规则

  • 不要混合FORWITH条款.
  • WITH条款之前写FOR条款.
  • 不要依赖于特定于实现的行为和影响.