`
iyuan
  • 浏览: 469877 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

lisp初体验-Practical Common Lisp笔记-9.标准宏

    博客分类:
  • lisp
阅读更多
一直在拖延,玩Lisp,终究绕不开这道坎啊。既然如此,抖擞下精神,开始了。

作者首先又是抱怨、比较了一番lisp的宏与其他语言的区别。从形式上来讲,其实所谓的标准宏就和c,java之类的类库一样,是事先已经被完成、验证过的东东封装在编译/虚拟环境 中供coder使用(省的重复造轮子)。当然,在lisp中,宏可不单单是如此简单,不过~管他呢(拜托,这只是初学者教程!)在这一章节主要给大伙介绍几个常用的宏。


条件宏
最常见的估计算是"if"了:
(if condition then-form [else-form])

(if (> 2 3) "Yup" "Nope") ==> "Nope"
(if (> 2 3) "Yup")        ==> NIL
(if (> 3 2) "Yup" "Nope") ==> "Yup"

真是简单易懂啊,不过if只支持单行动语句,也就是说,“无论条件是否成立,都只能做一件事,而不能做一组事”。而在真实环境中,自然会大大影响其使用面。为此就引入了特别造作符:PROGN
(if (spam-p current-message)
    (progn
      (file-in-spam-folder current-message)
      (update-spam-database current-message)))

恩,看起来还不错,不过,如果有更简洁的方案呢:
(when (spam-p current-message)
  (file-in-spam-folder current-message)
  (update-spam-database current-message))

when也是一个标准宏,即使不是,定义也不麻烦:
(defmacro when (condition &rest body)
  `(if ,condition (progn ,@body)))

它的共生兄弟unless则是对条件作了逆判断:
(defmacro unless (condition &rest body)
  `(if (not ,condition) (progn ,@body)))

似乎没什么神奇的啊,即没有神秘的魔法也没有晕人的逻辑。对头!或许"大道至简"可以用作解释吧。
如果说when解决了执行条目的问题,那么宏cond则是解决了条件条目的问题:
(cond
  (test-1 form*)
      .
      .
  (test-N form*))

(cond (a (do-x))
      (b (do-y))
      (t (do-z))) '理论上来说最后一条是default

在做条件运算时,通常都会搭配些基本的运算符:and,or,not(not其实算是函数)。
(not nil)             ==> T
(not (= 1 1))         ==> NIL
(and (= 1 2) (= 3 3)) ==> NIL   '遇到第一个nil即返回,没有则t
(or (= 1 2) (= 3 3))  ==> T     '遇到第一个t即返回,没有则nil


循环宏
最简单的两个循环宏莫过于dolist和dotimes了:
(dolist (var list-form)
  body-form*)

(dolist (x '(1 2 3)) (print x))
1
2
3
NIL

CL-USER> (dolist (x '(1 2 3)) (print x) (if (evenp x) (return)))
1
2
NIL          '通过return截断了循环

-----------------------------
(dotimes (var count-form)
  body-form*)

(dotimes (i 4) (print i))
0
1
2
3
NIL

一个循环列表,一个根据数值递进循环,都算定制型的循环宏。而他们都有一个"父宏"(可以这么叫么)--do,这玩意由于超级灵活(万金油啊),那么也造成了易用度的降低:
(do (variable-definition*)
    (end-test-form result-form*)
  statement*)

variable-definition-->(var init-form step-form)

简单看来,需要在veriable-definition中定义循环初值,跳步幅度(没有则默认一步),当达到end-test-form时,执行result-form,他的返回值将作为整个循环的返回值。而statement则是循环体。这里给出了一个例子来证明do的灵活性:
(do ((n 0 (1+ n))
     (cur 0 next)
     (next 1 (+ cur next)))
    ((= 10 n) cur))

其实就是传说中的“斐波纳契数列”。在这个例子中循环体似乎并不重要,重要的是构造本身。正如前面所说,灵活的同时易用性正在丧失,例子中的括弧实在令人印象深刻啊。咱们来看个对比:
(do ((i 0 (1+ i)))
    ((>= i 4))
  (print i))

(dotimes (i 4) (print i))

果然是“红花需要绿叶衬”~
在某些情况下,循环条件都是非必需的:
(do ()   '虽然没有条件,位置还得留着
    ((> (get-universal-time) *some-future-date*))
  (format t "Waiting~%")
  (sleep 60)) 

接下来要介绍的算是在lisp界颇具争议的"强力"循环宏:loop.
dolist,dotimes虽然简单,覆盖面却不广,而do又过于灵活(=复杂?),那么看似更趋向于中间的loop便有了出现的理由,纵然有不少人反对他(支持的也不少)。
看起来很简洁:
(loop
  body-form*)

用起来也不赖:
(loop
  (when (> (get-universal-time) *some-future-date*)
    (return))
  (format t "Waiting~%")
  (sleep 60))

与do比较下:
(do ((nums nil) (i 1 (1+ i)))
    ((> i 10) (nreverse nums))
  (push i nums)) ==> (1 2 3 4 5 6 7 8 9 10

(loop for i from 1 to 10 collecting i) ==> (1 2 3 4 5 6 7 8 9 10)

也来实现个“斐波纳契数列”:
(loop for i below 10
      and a = 0 then b
      and b = 1 then (+ b a)
      finally (return  a))

虽然其中用到了类似for,below什么的loop专用符号,但的确看着清爽多了,也更符合自然语言。这是loop簇拥们的理由,也是反对者腹诽的地方"一点都不lisp".个人观点就是,你觉着哪个爽就用哪个呗,正是"条条大路通罗马"~当然,这里的loop使用还只是冰山一角,后面的章节还会详述。

lisp编译器自带的标准宏自然不光这么几个,仅仅是摘出几个常用的,以简单一窥其中奥妙。那么,在接下来的章节中,即将深入介绍--自定义宏。你准备好了么?

(未完待续)
1
0
分享到:
评论

相关推荐

    Practical Common Lisp-1st-2005

    《Practical Common Lisp-1st-2005》是一本专注于Common Lisp编程语言的实用书籍,作者Peter Seibel通过这本书向读者展示了如何使用Common Lisp来解决真实世界中的问题,强调程序员作为工程师和艺术家的双重身份,而...

    Practical Common Lisp笔记

    《Practical Common Lisp笔记》是一本深入探讨Common Lisp编程语言的实用教程。Common Lisp是一种功能强大的多范式编程语言,以其动态类型、宏系统和丰富的内置数据结构而闻名。这篇笔记详细记录了作者在学习过程中...

    common-lisp-the-language-second-edition.PDF

    common-lisp-the-language-second-edition.PDF

    cad-lisp-3-表操作.LSP.lsp

    cad-lisp-3-表操作.LSP.lsp

    Lisp - 1990 - Common Lisp the Language, 2nd Edition - Steele, Guy L..pdf

    《Common Lisp the Language, 2nd Edition》是Guy L. Steele所著的一本关于Common Lisp编程语言的权威...这本书作为Common Lisp标准的详细参考资料,对于所有想要深入学习和使用这门语言的开发者来说都是不可或缺的。

    实用Common.Lisp编程.pdf

    Common Lisp作为Lisp语言的一个标准化版本,旨在为开发者提供一个稳定且功能强大的编程平台。 ### Common Lisp的特点与优势 #### 1. 动态类型和垃圾回收机制 Common Lisp支持动态类型,这意味着变量可以在运行时...

    emacs-lisp-intro-2.04.tar.gz

    标题中的"emacs-lisp-intro-2.04.tar.gz"是一个典型的压缩文件名,它表明这个文件是一个关于Emacs Lisp的介绍性资料,并且版本号是2.04,格式为tar.gz。tar.gz是一种在Linux和Unix系统中常用的文件压缩格式,它先用...

    Practical Common Lisp pdf

    Common Lisp是Lisp家族中的一个广泛使用的标准版本,它集成了多种子语言,提供了丰富的库支持,包括面向对象编程、函数式编程和元编程等特性。 本书《实用Common Lisp》深入浅出地介绍了Lisp的基本概念,包括符号、...

    Successful Lisp How to Understand and Use Common Lisp - David B. Lamkins

    Provides practical advice for the construction of Common Lisp programs. Shows examples of how Common Lisp is best used. Illustrates and compares features of the most popular Common Lisp systems on ...

    AutoLisp源文件--标注高程.LSP

    AutoLisp源文件--标注高程.LSP

    ANSI Common Lisp 中文翻译版.pdf

    该资源包含了 17 章节,从基础的列表、特殊数据结构、控制流程、函数、输入与输出、符号、数字、宏、Common Lisp 对象系统、结构、速度、进阶议题到高级主题的推论、生成 HTML、对象等。 ANSI Common Lisp 是一种...

    实用Common.Lisp编程

    这本《Practical Common Lisp》之所以号称Practical,正是因为这本书大量介绍Common Lisp在现实世界中的各种应用方式,算是第一本「入世传教」的Common Lisp著作。《Practical Common Lisp》是目前最畅销的Common ...

    Practical Common Lisp

    Practical Common Lisp 学习lisp的入门书籍

    practical common lisp.pdf

    ### 实用Common Lisp编程知识点概览 #### 一、书籍简介与评价 《实用Common Lisp》是一本面向实际程序员的Lisp语言入门书籍。作者Peter Seibel通过一系列真实世界的问题来展示Common Lisp的强大之处,强调工程性和...

    lisp小工具-fx.zip

    计算多个数字之和、计算多条线段长度之和、插入墙高标注、查询多段线顶点坐标并绘制、自动生成页码、绘制示坡线、插入排水箭头 https://blog.csdn.net/qq_24141055/article/details/121446354

    Lisp-music-player.rar_autolisp_autolisp程序_lisp_player

    标题中的“Lisp-music-player.rar”表明这是一个基于Lisp语言开发的音乐播放器软件,其源代码或可执行文件被压缩在RAR格式的文件中。RAR是一种流行的压缩格式,通常用于存储和分发多个文件,它允许用户将多个文件...

    Common-Lisp-Actors, 通用Lisp的actor系统.zip

    Common-Lisp-Actors, 通用Lisp的actor系统 这是一个简单且易于使用的Actor系统,在。设置需要波尔多螺纹。http://common-lisp.net/project/bordeaux-threads/ 2. 加载 actors.lisp 并开始使用它。 如果你有 Quick

    Practical Common LISP(Apress,2012)

    If you’re interested in Lisp as it relates to Python or Perl, and want to learn through doing rather than watching, Practical Common Lisp is an excellent entry point. — Chris McAvoy, Chicago Python ...

    Practical Common lisp

    1. **标准控制结构**:书中详细介绍了Common Lisp中的宏(Macros)及其在标准控制结构中的应用,例如条件语句、循环语句等。 2. **自定义宏**:更进一步地,书中还讲解了如何定义自己的宏来扩展Common Lisp的功能,...

Global site tag (gtag.js) - Google Analytics