Common Lisp Loop 宏实例

Common Lisp Loop 宏教程

Loop 宏是Common lisp操作符中最有价值和文档最少的操作符之一。它的价值体现在它比lisp的其他构造,例如maping 操作符和递归操作符,更加强大,紧凑和具有更强的可读性。并且对于那些用传统语言工作的程序员来说,Loop宏使用的编程方式会更容易理解。这个教程将提供给你如何使用Loop宏的例子。

Loop宏和其他大多数的Lisp表达式不同的是它有着类似于其他编程语言例如C和Pascal格式的复杂的内部语法。所以当你读Loop表达式的时候,你脑中需要一半的Lisp模式,另一半是Pascal模式。

Loop表达式有四个部分组成:设置迭代的变量部分,结束迭代的条件部分,每次迭代的操作部分和在Loop结束前操作的部分表达式。除此之外,Loop表达式也可以返回一个值。通常情况下,很少在一个表达式里面使用所有的四个部分,但是你需要能以很多的方式组合它们。

;; 遍历一个list ,打印每一个元素
(loop for x in '(a b c d e)
     do (print x))
A 
B 
C 
D 
E 
NIL

;; 并行的遍历两个集合,组成一个结果返回

(loop for x in '( a b c d e)
         for y in '(1 2 3 4 5)
         collect ( list x y))

((A 1) (B 2) (C 3) (D 4) (E 5))

;; 使用一个计数器遍历,在每次遍历中计算变量的值

(loop for x  from 1 to 5 
        for  y = ( * x 2)
        collect y)
(2 4 6 8 10)
 
   
;;遍历一个list,并且并行有一个计数循环。 list的长度决定的循环何时终止
;; 定义了两个操作结果,其中一个是有条件的
(loop for x in '(a  b c d e)
           for y from 1
           when  (> y 1)
           do (format t ", ")
           do (format t "~A" x))
A, B, C, D, E

;; 我们也可以在在loop使用if结构
(loop for x in '(a b c d e)
           for y from 1
           
           if(> y 1)
           do (format t ", ")
           else do (format t "~A" x))
A, , , , 
NIL

;; 使用test结束循环,动作可以由多行代码组成,也可以使用定义在loop之外的词法变量
  (loop for x in '(a b c d e 1 2 3 4)
        until (numberp x)
        do
        collect (list x 'foo))

((A FOO) (B FOO) (C FOO) (D FOO) (E FOO))

;; while 语句同样可以作为结束条件。do和collect可组合在一个表达式里面
(loop for x from 1
      for y = (* x 10)
      while (< y 100)

      do (print (* x 5))

      collect y)

5 
10 
15 
20 
25 
30 
35 
40 
45 
(10 20 30 40 50 60 70 80 90)

;; Loop 也可以嵌套  

(loop for x from 1 to 10
      collect (loop for y from 1 to x 
                    collect y) )

((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5) (1 2 3 4 5 6) (1 2 3 4 5 6 7)
 (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8 9) (1 2 3 4 5 6 7 8 9 10))


;; Several variables can loop through the components of a complex
;; list to destructure it.

(loop for (a b) in '((x 1) (y 2) (z 3))
      collect (list b a) )

((1 X) (2 Y) (3 Z))

;; Destructuring works for dotted pairs too.

(loop for (x . y) in '((1 . 1) (2 . 4) (3 . 9)) collect y)

(1 4 9)


;; return 动作不但终止循环并且返回一个值,这个例子我们返回这个字符串s的第一个数字字符

(let ((s "alpha45"))
  (loop for i from 0 below (length s)
        for ch =  (char s i)
        when (find ch "0123456789" :test #'eql)
        return ch) )
#\4


;; 组合了 when/return的动作
(loop for x in '(foo 2) 
      thereis (numberp x))
T

(loop for x in '(foo 2) 
      never (numberp x))
NIL

(loop for x in '(foo 2) 
      always (numberp x))
NIL
 
   
英文原文:

Tutorial for the Common Lisp Loop Macro

Peter D. Karp
SRI International
pkarp @ ai.sri.com

The Loop Macro is one of the most valuable, and least-well documented of the operations in Common Lisp. It is valuable because it is more powerful, more compact, and more readable than comparable Common Lisp constructs such as mapping operations and recursion. It also uses a programming style that will be familiar to programmers who have worked with other more traditional languages. This short guide provides examples of how to use the Loop Macro.

The Loop macro is different than most Lisp expressions in having a complex internal syntax that is more similar to programming languages like C or Pascal. So you need to read Loop expressions with half of your brain in Lisp mode, and the other half in Pascal mode.

Think of Loop expressions as having four parts: expressions that set up variables that will be iterated, expressions that conditionally terminate the iteration, expressions that do something on each iteration, and expressions that do something right before the Loop exits. In addition, Loop expressions can return a value. It is very rare to use all of these parts in a given Loop expression, but you can combine them in many ways.

;; Iterate through a list, and print each element.

(loop for x in '(a b c d e)
      do (print x) )

A 
B 
C 
D 
E 
NIL

;; Iterate through two lists in parallel, and cons
;; up a result that is returned as a value by Loop.


(loop for x in '(a b c d e)
      for y in '(1 2 3 4 5)
      collect (list x y) )

((A 1) (B 2) (C 3) (D 4) (E 5))


;; Iterate using a counter, and a variable whose value
;; is computed from an expression on each iteration.

(loop for x from 1 to 5
      for y = (* x 2)
      collect y)

(2 4 6 8 10)


;; Iterate through a list, and have a counter iterate
;; in parallel.  The length of the list determines when
;; the iteration ends.  Two sets of actions are defined,
;; one of which is executed conditionally.

(loop for x in '(a b c d e)
      for y from 1

      when (> y 1)
      do (format t ", ")

      do (format t "~A" x)
      )
      
A, B, C, D, E
NIL


;; We could also write the preceding loop using the IF construct.

(loop for x in '(a b c d e)
      for y from 1

      if (> y 1)
      do (format t ", ~A" x)
      else do (format t "~A" x)
      )
      
A, B, C, D, E
NIL


;; Terminate the loop early using a test.  Actions can
;; consist of arbitrarily many lines and can refer to
;; variables defined outside the lexical scope of the loop.

  (loop for x in '(a b c d e 1 2 3 4)
        until (numberp x)
        do
        collect (list x 'foo))

((A FOO) (B FOO) (C FOO) (D FOO) (E FOO))


;; "While" can also serve as a termination check.  Both
;; "do" and "collect" can be combined in one expression.

(loop for x from 1
      for y = (* x 10)
      while (< y 100)

      do (print (* x 5))

      collect y)

5 
10 
15 
20 
25 
30 
35 
40 
45 
(10 20 30 40 50 60 70 80 90)


;; Loops can be nested in various ways

(loop for x from 1 to 10
      collect (loop for y from 1 to x 
                    collect y) )

((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5) (1 2 3 4 5 6) (1 2 3 4 5 6 7)
 (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8 9) (1 2 3 4 5 6 7 8 9 10))


;; Several variables can loop through the components of a complex
;; list to destructure it.

(loop for (a b) in '((x 1) (y 2) (z 3))
      collect (list b a) )

((1 X) (2 Y) (3 Z))

;; Destructuring works for dotted pairs too.

(loop for (x . y) in '((1 . 1) (2 . 4) (3 . 9)) collect y)

(1 4 9)


;; The "return" action both stops the loop and returns a result.
;; Here we return the first numeric character in the string s.

(let ((s "alpha45"))
  (loop for i from 0 below (length s)
        for ch =  (char s i)
        when (find ch "0123456789" :test #'eql)
        return ch) )
#\4


;; Several actions provide shorthands for combinations of when/return

(loop for x in '(foo 2) 
      thereis (numberp x))
T

(loop for x in '(foo 2) 
      never (numberp x))
NIL

(loop for x in '(foo 2) 
      always (numberp x))
NIL
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值