LISP语言教程
LISP语言教程

LISP语言教程作者:牛魔王—上次修改时间: 2007-03-22 13:13Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
Scheme 语言概要Author: 宋国伟吉林省德惠市信息中心Date: 2003 年 12 月 01 日Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
作为Lisp 变体,Scheme 是一门非常简洁的计算语言,使用它的编程人员可以摆脱语言本身的复杂性,把注意力集中到更重要的问题上,从而使语言真正成为解决问题的工具。
本文分为上、下两部分来介绍 scheme 语言。
一.Scheme语言的特点Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
它是一个小巧而又强大的语言,作为一个多用途的编程语言,它可以作为脚本语言使用,也可以作为应用软件的扩展语言来使用,它具有元语言特性,还有很多独到的特色,以致于它被称为编程语言中的"皇后"。
下面是洪峰对Scheme语言的编程特色的归纳:∙词法定界(Lexical Scoping)∙动态类型(Dynamic Typing)∙良好的可扩展性∙尾递归(Tail Recursive)∙函数可以作为值返回∙支持一流的计算连续∙传值调用(passing-by-value)∙算术运算相对独立本文的目的是让有编程基础(那怕是一点点)的朋友能尽快的掌握Scheme语言的语法规则,如果您在读完本文后,发现自己已经会用Scheme语言了,那么我的目的就达到了。
用Python编写一个简单的Lisp解释器的教程

⽤Python编写⼀个简单的Lisp解释器的教程本⽂有两个⽬的: ⼀是讲述实现计算机语⾔解释器的通⽤⽅法,另外⼀点,着重展⽰如何使⽤来实现Lisp⽅⾔的⼀个⼦集。
我将我的解释器称之为Lispy ()。
⼏年前,我介绍过如何,同时我还使⽤Common Lisp语⾔编写过⼀个版本。
这⼀次,我的⽬的是尽可能简单明了地演⽰⼀下所说的“软件的麦克斯韦⽅程组” (Maxwell's Equations of Software)。
Lispy⽀持的Scheme⼦集的语法和语义⼤多数计算机语⾔都有许多语法规约 (例如关键字、中缀操作符、括号、操作符优先级、点标记、分号等等),但是,作为Lisp 语⾔家族中的⼀员,Scheme所有的语法都是基于包含在括号中的、采⽤前缀表⽰的列表的。
这种表⽰看起来似乎有些陌⽣,但是它具有简单⼀致的优点。
(⼀些⼈戏称”Lisp”是”Lots of Irritating Silly Parentheses“——“⼤量恼⼈、愚蠢的括号“——的缩写;我认为它是”Lisp Is Syntactically Pure“——“Lisp语法纯粹”的缩写。
) 考虑下⾯这个例⼦:/* Java */if(x.val() > 0) {z = f(a*x.val() + b);}/* Scheme */(if (> (val x) 0)(set! z (f (+ (* a (val x)) b))))注意上⾯的惊叹号在Scheme中并不是⼀个特殊字符;它只是”set!“这个名字的⼀部分。
(在Scheme中)只有括号是特殊字符。
类似于(set! x y)这样以特殊关键字开头的列表在Scheme中被称为⼀个特殊形式 (special form);Scheme的优美之处就在于我们只需要六种特殊形式,以及另外的三种语法构造——变量、常量和过程调⽤。
在该表中,var必须是⼀个符号——⼀个类似于x或者square这样的标识符——number必须是⼀个整型或者浮点型数字,其余⽤斜体标识的单词可以是任何表达式。
CAD二次开发lisp教程《第一章》

集成环境下可以便捷, 程序, 在VLISP集成环境下可以便捷,高效地开发 集成环境下可以便捷 高效地开发AutoLISP程序, 程序 可以经过编译得到运行效率更高,代码更加紧凑, 可以经过编译得到运行效率更高 ,ual LISP是新一代 是新一代AutoLISP语言,它对 语言, 是新一代 语言 它对AutoLISP语言进行 语言进行 了 扩 展 , 可 以 通 过 Microsoft ActiveX Automation 接 口 与 AutoCAD对象交互,可以通过反应器函数扩展 对象交互,可以通过反应器函数扩展AutoLISP响应事 对象交互 响应事 件的能力. 件的能力. 如果使用Visual LISP对AutoLISP扩展功能的部份,必须调用 扩展功能的部份, 如果使用 对 扩展功能的部份 vl-load-com 函 数 , 或 者 将 调 用 该 函 数 的 表 达 式 写 在 acad2006doc.lsp 文件内. 文件内.
第1章 章
AutoLISP和Visual LISP 和
1.1 关于 关于LISP
LISP是人工智能领域中广泛采用的一种程序设计语言.主要用于人工智 是人工智能领域中广泛采用的一种程序设计语言. 是人工智能领域中广泛采用的一种程序设计语言 机器人,专家系统,博奕,定理证明等领域. 能,机器人,专家系统,博奕,定理证明等领域. LISP也被称为符号式语言,因为它处理的对象是符号表达式.LISP语言 也被称为符号式语言,因为它处理的对象是符号表达式. 语言 也被称为符号式语言 的程序和数据都是以符号表达式的形式来表示,因此,一个LISP程序可以把 的程序和数据都是以符号表达式的形式来表示,因此,一个 程序可以把 另一个LISP程序作为它的数据来处理. 程序作为它的数据来处理. 另一个 程序作为它的数据来处理 LISP语言语法简单,编写程序便捷,灵活,数据类型丰富.利用 语言语法简单,编写程序便捷,灵活,数据类型丰富.利用LISP语 语言语法简单 语 言可以很容易地定义或调用新的函数.这就是Autodesk公司早在 公司早在1985年的 年的2.1 言可以很容易地定义或调用新的函数.这就是 公司早在 年的 版本就引用了LISP语言的宏操作, 在 1986年的 版本就推出了比较完整的 版本就引用了 语言的宏操作, 年的2.5版本就推出了比较完整的 语言的宏操作 年的 AutoLISP语言的原因. 语言的原因. 语言的原因 LISP在它几十年的发展过程中产生了多种版本,如MacLISP,InterLISP 在它几十年的发展过程中产生了多种版本, 在它几十年的发展过程中产生了多种版本 , ,ZetaLISP,和CommonLISP等.其中 , 等 其中CommonLISP是近几年美国的几所大 是近几年美国的几所大 如麻省理工,斯坦福等)和工业界( 实验室, 公司, 公司 学(如麻省理工,斯坦福等)和工业界(如Bell实验室,DEC公司,HP公司 实验室 公司 等 ) 的人工智能研究人员协同推出的 , 它概括了MacLISP, InterLISP, 它概括了 , , ZetaLISP等版本的特点,因而功能较强且拥有其它版本的一些优点,是目前 等版本的特点, 等版本的特点 因而功能较强且拥有其它版本的一些优点, LISP语言较完整的版本. 语言较完整的版本. 语言较完整的版本
Lisp 入门教程

Lisp 入门教程作者:Geoffrey J. Gordon <ggordon@> 1993/02/05 星期五修订:Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>翻译:刘鑫 <March.Liu@>整理:张泽鹏 <redraiment@> 2011/06/24 星期五注意:这份 Common Lisp 入门教程是针对 CMU 环境编写,所以在其它环境运行 Lisp 时可能会有细节上的区别。
附:据我所知最好的 Lisp 书籍是:Guy L. Steele Jr. 《Common LISP: the Language》 Digital Press. 1984.第一版很容易阅读,第二版介绍了更新的标准。
(两个标准的差异很小,对于粗心的程序员没有什么区别。
)我还记得 Dave Touretsky 写了一本,不过我从来没读过,所以不能对那本书发表评论。
Symbols符号仅仅是字符串。
你可以在符号中包含字母、数字、连接符等等,唯一的限制就是要以字母开头。
(如果你只输入数字,最多再以一个连接符开头的话,LISP会认为你输入了一个整数而不是符号。
)例如:接下来我们可以做些事情。
(">"标记表示你向LISP输入的东西,其它的是LISP 打印返回给你的。
";"是LISP的注释符:";"后面的整行都会被忽略。
)有两个特殊的符号, t 和 nil 。
t 的值总是定义为 t,nil 的值总是定义为 nil 。
LISP用 t 和 nil 代表 true 和false。
以下是使用这个功能的 if 语句,后面再做详细说明:最后一个例子看起来很怪,但是没有错:nil 代表 false ,其它任意值代表 true。
(为了代码清晰,在没有什么特别原因的情况下,我们用t代表true。
LISP语言教程(1)

(quote x)返回x.为了可读性我们把(quote x)简记为'x.
> (quote a)
a
> 'a
a
> (quote (a b c))
(a b c)
atom
(atom x)返回原子t如果x的值是一个原子或是空表,否则返回().在Lisp中我们按惯例用原子t表示真,而用空表表示假.
> (atom 'a)
(cond ((atom z)
(cond ((eq z y) x)
('t z)))
('t (cons (subst x y (car z))
(subst x y (cdr z))))))
偶然地我们在这儿看到如何写cond表达式的缺省子句.第一个元素是't的子句总是会成功的.于是
(cond (x y) ('t z))
等同于我们在某些语言中写的
if x then y else z
一些函数
既然我们有了表示函数的方法,我们根据七个原始操作符来定义一些新的函数.为了方便我们引进一些常见模式的简记法.我们用cxr,其中x是a或d的序列,来简记相应的car和cdr的组合.比如(cadr e)是(car(cdr e))的简记,它返回e的第二个元素.
示例
假设我们要定义函数(subst x y z),它取表达式x,原子y和表z做参数,返回一个象z那样的表,不过z中出现的y(在任何嵌套层次上)被x代替.
> (subst 'm 'b '(a b (a b c) d))
(a m (a m c) d)
我们可以这样表示此函数
(label subst (lambda (x y z)
lisp教程

一.Lisp基础知识二.对话框基础一.基本知识第1节--------------------------------------------------------------------------------基本知识AutoLISP是一种针对扩充及自订AutoCAD函数机能而产生,以LISP为基础的程序设计语言.LISP本身于50年代末期出现,是一种擅于处理串行文字(List of Processing),属第四代「人工智能(Artificial Intelligence)」的计算机语言.目的是令使用者充份利用AutoCAD进行开发,直接增加及修改AutoCAD指令.AutoLisp语言建基于普通的LISP语言上,并扩充了许多适用于CAD的特殊功能而形成.是一种能以直译方式(不须先行编译)亦可于AutoCAD内部执行的直译性程序语言.程序容易学习及撰写,程序即使出错亦不会对操作系统(如DOS,WINDOWS)有不良影响.数据及程序均统一以串行 (List)结构表示.可直接调用几乎全部的AutoCAD命令.既具备一般高级语言的基本结构和功能,亦有一般高级语言没有的强大图形处理能力.内建于AutoCAD应用程序,不须另行购买;亦不须使用特定的编辑器或开发环境.可配合AutoCAD提供的PDB,建立DCL(Dialog Control Language)文件创建对话框.缺点 : 执行速度较ObjectArx(旧称ARX,以C或C++程序开发,取代以前的ADS)程序慢;原程序不易保护;对低阶的硬件数据不易存取.第2节--------------------------------------------------------------------------------函数 (Function)在AutoLISP程序语言中所有的成份都是以函数的形式出现,AutoLISP程序就是顺序执行连串的函数.函数的运行过程就是对函数的求值(结果)过程;函数的基本语法如下:(函数名称参数1 参数2....)e.g. (PRINC "AutoLISP Programming")每一个完整的函数必须包在一对小括号( )内,左边为开括号,右边为关括号;如有若干数量的开括号,则一定有同等数量的关括号对应.左边开括号后紧随函数名称.函数名称与参数之间,或参数与参数之间须最少留一个空格.第3节--------------------------------------------------------------------------------数据型态 (Data Type)整数 (INT)没有小数字的数值,32位有号数,范围从+2,147,483,647到-2,147,483,648实数 (REAL)带小数字的数值,以倍精度浮点格式储存(最少14位小数) e.g. 12.5当数值在1与-1之间时,必须加上前导零 e.g. 0.05可以科学记号表示 : 在E或e后加上次方值 e.g. 4.1e-6字符串 (STR)一般文字,其前后必须加上双引号" e.g. "AutoCAD"控制字符或脱逸码必须为小写,且须在字符前加上反斜线 \ e.g. "\AutoCAD"像素名称 (ENAME)是指定给图文件内对象的指针(Pointer,为16进位的数字卷标)e.g. <Entity name:14e5180>像素名称在图文件内是唯一的,不会重复对象的像素名称只在目前作业中有效,再开启图档时,会指定新的像素名称予该对象档案 (FILE)以OPEN函数所开启档案的指针,作为其它函数(读写该档案)的自变量选集 (PICKSET)用SSGET等函数建立的一个或多个对象的集合或群组转化 (V ARIANT)可将像素名称转换为可与ActiveX配搭使用的VLA-Object对象符号 (SYM)用以储存静态数据的名称;例如内建或使用者定义的函数符号名称不分大小写,可由任意长度的可打印字符组成;但下列的字符除外:左括号( 右括号 ) 句点 . 单引号' 双引号 " 分号 ;表 (LIST)亦称为串行,是放在一对小括号 ( ) 内,一个或多个元素的有序集合e.g. (1.0 "Lisp" ( ) (5.6 7))元素可以是字符串,符号,整数或实数;也可以是另一个表元素与元素之间要用空格隔开,但元素与小括号之间则可以不隔空格为便于存取表内各元素,每个元素均有其序号;从表的左边开始,第一个元素序号为0,依此类推表的大小即为其顶层元素的数量(内层嵌套式的表,视为单一元素)点对(Dotted Pair)亦是表的一种;表内有2个元素,中间以一圆点分隔,且元素与圆点之间亦须以空格分开若表内没有任何元素,称为空串行或空表;以 ( ) 或 (NIL) 表示第4节--------------------------------------------------------------------------------变数 (Variable)为程序执行中动态储存数据的符号名称;主要分为2类:变量名称与符号的限制相同,使用时宜采用有意义及易于辨别的名称变量在赋值或使用前无须先行设定相同的变量可以储存不同型态的数据(但同一时间内只可储存一种型态)在指定新的数据之前,变量储存的内容会保持不变赋值将数据给予指定的变量储存以内建函数SETQ进行(可用于绘图模式的指令行或AutoLISP程序),其语法如下:(SETQ 变量名称1 资料1 [变量名称2 资料2 ....] )e.g. (SETQ NAME "David" AGE 37 WEIGHT 72.5 POINT (LIST 10 20))在函数名称之后,各参数以两个一组,每组左边为变量名称,右边为存入变量的数据亦可将变量名称赋以空值(NIL) :e.g. (SETQ OCCUPATION NIL)要显示变量所储存的数据,可以使用内建函数PRINC(可用于绘图模式的指令行或AutoLISP程序),其语法如下 : (PRINC 变量名称 )e.g. COMMAND : (PRINC NAME) Result : David"David"在绘图模式中,亦可于指令行中使用感叹号 ! 来显示变量内容,或作为指令选项的输入值;语法如下 : !变量名称e.g. COMMAND : !NAME Result : "David"在Visual LISP的主控台窗口中,于提示符号 _$ 后键入要显示的变量名称_$变量名称e.g. _$NAME要检查变量所储存的数据型态,可使用内建函数TYPE;语法如下:(TYPE 变量名称)e.g. COMMAND : (TYPE NAME) Result : STR若检查的变量没有储存数据,则会传回NIL第5节--------------------------------------------------------------------------------练习 (Exercises)将四个坐标分别存入四个变量中,并以LINE或PLINE指令,配合四个坐标变量,画出正四边形.COMMAND : (SETQ POINT1 (LIST 0 0) POINT2 (LIST 0 10) POINT3 (LIST 10 10) POINT4 (LIST 10 0)) COMMAND : LINE ;直线段指令COMMAND : !POINT1 ;第一点(左下角起点)COMMAND : !POINT2 ;第二点(左上角)COMMAND : !POINT3 ;第三点(右上角)COMMAND : !POINT4 ;第四点(右下角)COMMAND : C ;自动联机至起点以关闭四边形画圆 : 将圆心坐标及半径长度分别存入两个变量中(变量名称及数据型态自订)COMMAND : (SETQ CEN (LIST 0 0) RAD 20) ;将圆心点设为坐标0,0;半径为20COMMAND : CIRCLE ;执行划圆指令Specify center.... : !CEN ;在提示后以变量CEN响应输入Specify radius.... : !RAD ;在提示后以变量RAD响应输入将不同型态的数据,分多次存入相同的变数内;每次均以PRINC及TYPE函数显示变量内容及其数据型态COMMAND : (SETQ TEMP 1.2) ;将实数1.2存入变数TEMPCOMMAND : !TEMP Result : 1.2COMMAND : (TYPE TEMP) Result : REALCOMMAND : (TYPE TEMP) Result : STR二数值资料第1节--------------------------------------------------------------------------------基本运算加函数(+ [数值参数1 数值参数2 ....] )e.g. (+ 2.5 4 6) Result : 12.5函数的结果为各参数之总和若仅提供一个参数,则以0加上此参数的结果为返回值若没有提供任何参数则传回0;各参数须为整数或实数型态若所有参数均为整数,结果亦为整数;若其中一个参数为实数型态,结果会转换为实数减函数(- [数值参数1 数值参数2 ....] )e.g. (- 10 2 3) Result : 5结果为第一个(最左边)参数减去其右边各参数的总和若只提供一个参数,返回值为0减去该参数的结果若没有提供任何参数则传回0;各参数须为整数或实数型态若所有参数均为整数,结果亦为整数;若其中一个参数为实数型态,结果会转换为实数乘函数(* [数值参数1 数值参数2 ....] )e.g. (* 2 3 4) Result : 24结果为所有参数的乘积若只提供一个参数,则返回值为该参数乘以1的结果若没有提供任何参数则传回0;各参数须为整数或实数型态若所有参数均为整数,结果亦为整数;若其中一个参数为实数型态,结果会转换为实数除函数(/ [数值参数1 数值参数2 ....] )e.g. (/ 24 2 3) Result : 4结果为第一个(最左边)参数除以其右边各参数的乘积若仅提供一个参数,则返回值为该参数除以1的结果若没有提供任何参数则传回0;各参数须为整数或实数型态若所有参数均为整数,结果亦为整数;若其中一个参数为实数型态,结果会转换为实数注意 : 在本篇教程中,各函数的数值参数,均可以变量(储存值只可以是整数或实数,且不可以是空值 nil)取代第2节--------------------------------------------------------------------------------练习 (Exercises)计算式 (2+4)*3COMMAND : (* 3 (+ 2 4)) Result : 18计算式 (50-8*5)/4COMMAND : (/ (- 50 (* 8 5)) 4) Result : 2注意 : 上式的正确答案应是2.5,因为函数中的各参数均为整数,所以传回的结果亦为整数递增及递减递增(1+ 数值参数 )e.g. (1+ 2) Result : 3递减三角函数 (Trinagular Function)正弦值(SIN 弧度参数)e.g. (SIN 1) Result : 0.841471余弦值(COS 弧度参数)e.g. (COS 1) Result : 0.540302反正切值(ATAN 弧度参数)e.g. (ATAN 1) Result : 0.785398第3节--------------------------------------------------------------------------------其它数值处理次方值(EXPT 数值参数次方值 )e.g. (EXPT 2 4) Result : 16若参数及次方值两个均为整数,返回值亦是整数;若其中一个为实数,结果为实数开方根(SQRT 数值参数 )e.g. (SQRT 30) Result : 5.47723绝对值(ABS 数值参数 )e.g. (ABS -123) Result : 123余数(REM [数值参数1 数值参数2 ....] )e.g. (REM 50 26 5) = (REM (REM 50 26) 5) Result : 4将参数1整除参数2的余数若参数多于2个时,则会将余数再整除下一个参数,再得出余数;依此类推若其中一个参数为实数时,则结果为实数;否则为整数最大公约数(GCD 数值参数1 数值参数2 )e.g. (GCD 81 57) Result : 3两个参数均必须为整数值型态自然对数(LOG 数值参数 )e.g. (LOG 3.5) Result : 1.25276是EXP函数的反函数;传回值为实数型态自然反对数(EXP 数值参数 )e.g. (EXP 1.25276) Result : 3.49999是LOG函数的反函数;传回值为实数型态第4节--------------------------------------------------------------------------------数值资料转型实数转整数只会截去小数部份(小数字不会4舍5入)整数转实数(FLOAT 数值参数 )e.g. (FLOAT 12) Result : 12.0整数转字符串(ITOA 数值参数 )e.g. (ITOA -17) Result : "-17"数值转字符串(RTOS 数值参数[模式[小数字] ] )e.g. (RTOS 17.23333 2 3) Result : 12.266若不设定模式,则依系统变量 LUNITS 的设定值转换数值为字符串若不设定小数字,则依系统变量 LUPREC 的设定值转换模式设定值可以是下列数值之一 :1 = 科学记号2 = 十进制3 = 英呎及十进制英吋4 = 英呎及分数位英吋5 = 分数当选用的模式为3,4或5,则传回的字符串受系统变量UNITMODE影响弪度转字符串(ANGTOS 角度参数[模式[小数字] ] )e.g. (ANGTOS 0.785398 0) Result : "45"e.g. (ANGTOS 0.785398 4) Result : "N 45d E"若不设定模式,则依系统变量AUNITS的设定值转换数值为字符串若不设定小数字,则依系统变量AUPREC的设定值转换模式设定值可以是下列数值之一 :0 = 度1 = 度/分/秒2 = 分度量3 = 弪度4 = 土地测量单位当选用的模式为4,则传回的字符串受系统变量UNITMODE影响反函数为ANGTOF;参阅第5篇教程第5节--------------------------------------------------------------------------------数值资料检查数值(NUMBERP 数值参数 )e.g. (NUMBERP -3.45) Result : Te.g. (NUMBERP "AutoLISP") Result : nil注意 : 在范例的传回值中,T表示函数的结果为真(成立),nil表示结果为假(不成立) 负数值(MINUSP 数值参数 )e.g. (MINUSP -3.45) Result : Te.g. (MINUSP 0) Result : nile.g. (MINUSP 3.45) Result : nil零值e.g. (ZEROP 3.45) Result : nil其它应用最大值(MAX [数值参数1 数值参数2 ....] )e.g. (MAX -88 5 2) Result : 5若没有提供任何参数,则传回值为0最小值(MIN [数值参数1 数值参数2 ....] )e.g. (MIN -88 5 2) Result : -88若没有提供任何参数,则传回值为0第6节--------------------------------------------------------------------------------练习 (Exercises)计算下列算式 :(+ 1234567890 1234567890) Result : -1825831516上式中两个数值参数均为整数,而结果值大于整数型态所能容许之范围;固导致发生溢位问题,产生无效的结果.修正算式如下 : 只要将其中一个参数改为实数型态即可.(+ 1234567890.0 1234567890) Result : 2.46914e+009计算下列算式 :(+ 9876543210 1234567890) Result : 1.11111e+010上式中两个数值参数均为整数,但其中一个(第一个)参数巳大于整数型态所能容许之范围;系统会自动将此参数先行转为实数型态才计算.计算下列算式 :(FIX (SQRT (+ 1 (MAX 20 10 40 30)))) Result : 6---- 最先执行的是最内层的算式(MAX 20 10 40 30) ,求出最大值为40---- 其次执行加函数,将MAX函数所得的最大值加1,结果为41---- 再利函数SQRT,将41开方根,结果为6.4031---- 最后使用FIX函数,截去其小数字,得到最后的结果为6三程序设计第1节--------------------------------------------------------------------------------使用者定义函数是将一群表示式组合成一个函数或指令可应用于绘图模式的指令行提示,Visual LISP主控台,或供其它自定义函数内的表示式呼叫使用AutoLISP原始程序代码均以纯文字格式存盘,扩展名为LSP(2000版可编译成扩展名为FAS的档案可以一般文字编辑器进行开发,如DOS的EDIT,WINDOWS的WORD或WORDPAD等一个自定函数内最少要有一个表达式在原程序文件(LSP)里,自定义函数以DEFUN函数开始;其语法如下 :(DEFUN [C:] 函数名称 ( [自变量串行 ...] [/ 局部变数串行 ...] ) 表达式 ...)在呼叫带有自变量的自定函数时,必须同时提供与定义函数时,同等数量的参数,使各参数传入自定函数的各自变量中自变量被视为一种特殊类型的局部变量,无法用于该自定函数以外的其它函数若自定函数中无须设定任何自变量,亦必须以空串行 ( )加在函数名称之后若有提供局部变量,必须以斜线 / 加在局部变量的开头(即使前面没有自变量串行)各自变量,斜线,局部变量之间要以空格分隔;但与左右小括号之间则不须以空格分开若自变量串行中有相同名称的自变量出现,则会忽略第一个以后的相同自变量;变数亦是一样若在函数名称前没有加上C:,在指令行提示下,必须将函数名称包在一对小括号中才可执行不可以在执行一自定函数时,以通透方式执行另一自定函数第2节--------------------------------------------------------------------------------加载程序自定函数在使用前,都要将其所在的程序文件(扩展名为LSP)加载才可执行ACAD.LSP程序文件(预设在SUPPORT子目录内)会在启动AutoCAD时自动加载(LOAD "程序文件名称" [加载失败] )e.g. (LOAD "TEST")若程序文件之文件名为LSP,则在程序文件名称之后,可以不加上扩展名若有需要,系统会顺序尝试其它的扩展名 : VLX FAS LSP若程序文件不在系统的支持目录下,则需在文件名前加上目录路径注意 : 必须以正斜线 / 或两个反斜线 \\ 作为目录的分隔符可以在加载失败的参数中提供字符串,以供加载失败时显示;亦可提供有效的自定函数,该函数在加载程序文件失败时会被执行e.g. (LOAD "TEST" "Load Fail") 或 (LOAD "TEST" (DOERROR))注意 :在程序文件加载后,在提示行显示的返回值,一般是该程序文件中,最后被定义的函数名称或是在程序文件内没有包含在自定函数中,最后一个表达式的执行结果第3节--------------------------------------------------------------------------------练习 (Exercises)启动文字编辑器,编写一AutoLISP程序作两个同心圆(第1个圆半径为50,第2个圆半径为80),程序代码如下所示 : (DEFUN C: 2CIRCLE () (SETQ CEN (LIST 0 0) RAD 50)(COMMAND CIRCLE CEN RAD)(COMMAND CIRCLE CEN (+ RAD 30)))---- 输入后以纯文字格式存盘(C:\TEST.LSP)---- 在AutoCAD绘图模式的指令行提示后,用LOAD函数将程序文件加载COMMAND : (LOAD "C:/TEST")---- 在指令行提示后,输入程序(函数)名称执行COMMAND : 2CIRCLE程序说明1 使用DEFUN建立自定函数的名称,并用SETQ函数将中心点(LIST 0 0)存入变数CEN,半径(50)存入变数RAD中2 使用COMMAND函数执行AutoCAD内建指令CIRCLE,并以变量CEN(圆的中心点)及变数RAD(圆的半径)回应3 与第2行大致相同,但在指定其半径时,先将储存半径的变量加30,使划出半径为80的圆;注意最右边的关括号,与第1行DEFUN左边的开括号是一对的启动文字编辑器,开启TEST.LSP程序文件,复制2CIRCLE至新程序2C,并改为传入自变量方式执行;程序代码如下 : (DEFUN 2C (CEN RAD) (COMMAND CIRCLE CEN RAD)(COMMAND CIRCLE CEN (+ RAD 30)))---- 输入后以纯文字格式存盘---- 在AutoCAD绘图模式的指令行提示后,用LOAD函数将程序文件重新加载---- 在指令行提示后,输入程序(函数)名称执行COMMAND : (2C (LIST 0 0) 50)第4节--------------------------------------------------------------------------------表示在分号右边(同一行)的字符均为批注,程序执行时会将其忽略多行批注;| |;表示在两个批注符号中间所有字符皆为批注,即使字符跨越多行关系运算在各个关系运算中,都会传回一逻辑值;若关系成立,传回 T,否则会传回 nil各参数可以是字符串,整数或实数型态;若以字符串进行比较,则会以字符串的ASCII码为准若函数中只有一个参数,传回值恒为 T等于函数(= 参数1 [参数2 ....] )会将参数1与其后各个参数比较,若全部相等则传回 T,否则传回 nil e.g. (= 2 2.0) Result : Te.g. (= "A" CHR(65)) Result : T不等于函数(/= 参数1 [参数2 ....] )若参数1不等于其后任何一个参数,即传回T e.g. (/= 1 2.0) Result : Te.g. (/= "a" CHR(65)) Result : Te.g. (/= 10 30 40 10 20) Result : T小于函数(< 参数1 [参数2 ....] )各参数顺序以2个为一组比较,若各组左边的参数均小于右边的参数,即传回 Te.g. (< 1 2) Result : Te.g. (< "a" CHR(65)) Result : T大于函数(> 参数1 [参数2 ....] )各参数顺序以2个为一组比较,若各组左边的参数均大于右边的参数,即传回 Te.g. (> 1 2) Result : nile.g. (> "a" CHR(65)) Result : nil小于或等于函数(<= 参数1 [参数2 ....] )各参数顺序以2个为一组比较,若各组左边的参数均小于或等于右边的参数,即传回 Te.g. (<= 1 2) Result : Te.g. (<= 2 2) Result : Te.g. (<= "a" CHR(65)) Result : T大于或等于函数(>= 参数1 [参数2 ....] )各参数顺序以2个为一组比较,若各组左边的参数均大于或等于右边的参数,即传回 Te.g. (>= 1 2) Result : nile.g. (>= 2 2) Result : Te.g. (>= "a" CHR(65)) Result : nil第5节--------------------------------------------------------------------------------逻辑运算且运算(AND [表达式 ....] )若各表达式的传回值均为 T,函数即返回 T 值;若其中一个传回值为 nil,函数传回 nil(OR [表达式 ....] )若各表达式的传回值均为 nil,函数即返回 nil 值;若其中一个传回值为 T,函数传回 Te.g. (OR (> 1 2) (> 8 5)) Result : T否定运算(NOT 表达式 )若表达式的传回值为 T,函数即返回 nil 值;相反若表达式传回值为 nil,函数传回 T可用于检查传回值是否为 nil另有一NULL函数与NOT函数功能相似e.g. (NOT (< 1 2)) Result : nil练习 (Exercises)试求出50减25,与625的开方根值是否相等COMMAND : (= (- 50 25) (SQRT 625)) Result : T设计一简单程序(名称为AIR),在呼叫程序时,检查传入的数值自变量(为空气污染指数)是否大于200(即严重空气污染)---- 启动文字编辑器,开启TEST.LSP程序文件,输入下列程序代码 :(DEFUN AIR (NUM) (> NUM 200))---- 输入后存盘(纯文字格式)---- 在AutoCAD绘图模式的指令行提示符号后,使用LOAD函数重新加载程序文件COMMAND : (LOAD "C:/TEST")---- 在AutoCAD绘图模式的指令行提示符号后,输入自定函数名称及参数执行COMMAND : (AIR 175) Result : nilCOMMAND : (AIR 215) Result : T四流程控制第1节--------------------------------------------------------------------------------条件判断是利用条件函数,配合关系及逻辑运算所设定的一些准则,令程序自行分析,因应情况作出适当行动.单一条件(IF 条件表达式是表达式[否表达式] )函数先检查条件表达式,若其传回值为 T,便会执行其后的是表达式若有提供否表达式,且条件表达式的传回值为 nil,函数将不会执行(跳过)是表达式而执行否表达式若没有提供否表达式,且条件表达式的传回值为 nil时,函数将不作任何事情IF函数可以巢状方式嵌套,即在是或否的表达式中加入另一个IF函数练习 (Exercises)判断空气污染指数 : 大于100 = Very High, 51至100 = High, 26至50 = Medium, 25或以下 = Low---- 启动编辑器,开启C:/TEST.LSP程序文件;新增AIR-1自定函数,程序代码如下 :(DEFUN AIR-1 (NUM) (IF (> NUM 100) (PRINC "Very High"))(IF (AND (> NUM 50) (<= NUM 100)) (PRINC "High"))(IF (AND (> NUM 25) (<= NUM 50)) (PRINC "Medium"))(IF (<= NUM 25)) (PRINC "Low"))程序说明1 设定函数名称,并将数据存入自变量NUM内;用IF函数判断变量NUM是否大于100;若是则显示字符串Very High 响应2 用IF函数判断变量NUM是否大于50且(AND)小于或等于100;若是则显示High响应3 用IF函数判断变量NUM是否大于25且(AND)小于或等于50;若是则显示Medium4 用IF函数判断变量NUM是否小于或等于25;若是则显示Low5 是一个没有提供任何自变量的PRINC函数;用以抑制显示答案时尾部符加的 nil 或重复的传回值;而最右一个关括号,是用以对应第1行最左边的开括号IF函数的巢状练习 : 修改上一课的程序练习,将多个IF函数合并成巢状嵌套---- 启动文字编辑器,开启C:/TEST.LSP程序文件---- 新增程序AIR-2,其程序代码如下 :(DEFUN AIR-2 (NUM) (IF (> NUM 50) (PRINC (IF (> NUM 100) "Very high" "High"))(PRINC (IF (> NUM 25) "Medium" "Low")))(PRINC))程序说明1 设定函数名称,并将数据存入自变量NUM内;用IF函数判断变量NUM是否大于50;若条件成立(变量NUM大于50)时,再用另一个IF函数判断变量是否大于100;若条件成立(变量NUM大于100)时,使用PRINC函数显示字符串Very High,否则显示High2 若在第1个IF函数判断中,条件不成立(变量NUM不大于50)时;再用另一个IF函数判断变量是否大于25;若条件成立(NUM大于25)时,显示字符串Medium,否则显示字符串Low3 是一个没有提供任何自变量的PRINC函数;用以抑制显示答案时尾部符加的 nil 或重复的传回值;而最右一个关括号,是用以对应第1行最左边的开括号注意 :第1行最后一个关括号是对应前面的PRINC函数,尾2的关括号则是对应IF函数(判断NUM是否大于100) 第2行最后一个关括号是对应第1行的IF函数(判断NUM是否大于50),尾2的关括号则是对应PRINC函数,尾3的关括号则是对应IF函数(判断NUM是否大于25)最右边的关括号是对应第1行最左边的开括号PROGN 函数在以上各范例中,执行的表达式均为单一的函数运算;若要在表达式中顺序执行一连串的函数,便要将各函数包含在一个PROGN函数内;函数的传回值会是该PROGN函数中,最后一个表达式的运算结果---- 修改TEST.LSP程序文件的AIR-1程序,第1个IF函数如下,其余的IF函数请自行修改e.g. (IF (> NUM 100) (PROGN (SETQ DISP "Very High") (PRINC DISP)))注意 : 最后一个关括号是对应前面的IF函数(判断变量NUM是否大于100)尾2的关括号是对应PROGN函数(用以包含SETQ及PRINC函数)尾3的关括号是对应PRINC函数的第2节--------------------------------------------------------------------------------条件判断多重条件(COND [ (条件表达式是表达式) ....] )函数会顺序检查各条件表达式;直到其中一个条件成立(传回 T),即执行该条件式所对应的是表达式每个条件表达式只对应一个是表达式,而没有否表达式若条件式成立且执行对应的是表达式后,则不会再对余下的其它条件表达式进行检查若只有条件表达式而没有对应之是表达式,则只会传回条件表达式的逻辑值若没有提供任何条件表达式及是表达式,函数传回值恒为 nil练习 (Exercises)新增程序AIR-3,以改善上一课AIR-1程序;用一个COND函数判断多个条件表达式DEFUN AIR-3 (NUM) (COND((> NUM 200) (PRINC "Severe"))((> NUM 100) (PRINC "Very High"))((> NUM 50) (PRINC "High"))((> NUM 25) (PRINC "Medium"))((> NUM 0) (PRINC "Low"))(T (PRINC "Cannot Check")))(PRINC))程序说明1 设定函数名称,并将数据存入自变量NUM内;用COND函数进行多重判断2 判断变量NUM是否大于200,若条件成立,则显示 Severe 讯息;第3至6行依此类推7 注意条件式为一个 T 字母,表示条件式恒为真(成立),显示讯息 Cannot Check作用是当以上各条件式均不成立时(变量小于或等于0),即执行此一表达式第3节--------------------------------------------------------------------------------循环 (Loop)配合条件判断,关系及逻辑运算,令程序不断重复一些动作,以提高效率及减少重复动作时的人为错误可以多个循环形成巢状(嵌套式)循环,即在一个循环内嵌套另一个(或多个)循环指定的重复次数必须为正整数,亦可以是储存正整数的变量名称重复指定次数(REPEAT 重复次数[表达式 ....] )e.g. (REPEAT 10 (PRINC "David")) ;重复显示David字符串10次重复(WHILE 条件表达式[是表达式 ....] )若条件表达式的传回值为 T,即会顺序执行函数内各表达式各表达式顺序执行完后,程序会返回函数的开头,重新检查条件表达式的传回值若条件表达式的传回值为 nil,函数内各表达式将不会被执行e.g. (SETQ COUNT 1) ;将1存入变数COUNT(WHILE (<= COUNT 10) ;WHILE函数并检查变量COUNT是否<=10(PRINC "David") ;若条件成立则以PRINC函数显示David字符串(SETQ COUNT (1+ COUNT))) ;变量COUNT递增1,并将新值重新存入变量COUNT中取代原值注意 : 第4行最右边的关括号,是对应第2行WHILE函数的开括号无限循环又称为死循环,即循环的条件判断式传回值恒为 T,令循环不断重复而无法结束;在上例中 :---- 若WHILE函数的条件表达式设定为 (T) ;即条件永远成立---- 不作SETQ函数,或不将变量COUNT递增;变量COUNT储存值恒久不变,导致条件式永远成立第4节--------------------------------------------------------------------------------练习 (Exercises)编写一程序SUM并将自变量存在NUM变量内,计算1+2+3+4 ....至变数NUM的总和(DEFUN SUM (NUM) (SETQ COUNT 1 TOTAL 0)(WHILE (<= COUNT NUM)(SETQ TOTAL (+ TOTAL COUNT)COUNT (1+ COUNT)))(PRINC TOTAL) (PRINC))程序说明1 设定函数SUM并将自变量存入变量NUM,设定变量COUNT以将数目由1开始递增,变量TOTAL(储存总和)初始值为02 WHILE循环函数,并设定进入循环的条件式(变量COUNT小于或等于变量NUM)3 若条件成立即进入循环内部,先将变量TOTAL加上变量COUNT,再用SETQ函数存回变量TOTAL中,覆盖原值4 将变量COUNT递增1,存回变数COUNT并覆盖原值5 关括号与第2行的WHILE函数左边的开括号对应6 循环结束后,用PRINC函数显示变量TOTAL(总和)的内容程序流程假设执行程序时传入变量NUM的数值为10---- 变数初始值 COUNT = 1 TOTAL = 0---- 判断变量COUNT是否<=变量NUM COUNT = 1 TOTAL = 0---- 变量COUNT(现值1)小于NUM,进入循环;将TOTAL(现值0)加上COUNT,存回变数TOTAL COUNT = 1 TOTAL = 1---- 变数COUNT(现值1)递增1变为2,存回变数COUNT COUNT = 2 TOTAL = 1---- 返回WHILE函数的开头,重新判断条件式---- 变量COUNT(现值2)小于NUM,进入循环;将TOTAL(现值1)加上COUNT,存回变数TOTAL COUNT = 2 TOTAL = 3---- 变数COUNT(现值2)递增1变为3,存回变数COUNT COUNT = 3 TOTAL = 3---- 返回WHILE函数的开头,重新判断条件式---- 变量COUNT(现值3)小于NUM,进入循环;将TOTAL(现值3)加上COUNT,存回变数TOTAL COUNT = 3 TOTAL = 6部份过程省略---- 返回WHILE函数的开头,重新判断条件式---- 变量COUNT(现值10)仍等于NUM,进入循环;将TOTAL(现值45)加上COUNT,存回变数TOTAL COUNT = 10 TOTAL = 55---- 变数COUNT(现值10)递增1变为11,存回变数COUNT COUNT = 11 TOTAL = 55---- 返回WHILE函数的开头,重新判断条件式---- 变量COUNT(现值11)巳大于NUM(本范例假设为10),条件判断不成立,循环结束 COUNT = 11 TOTAL = 55---- 显示变量TOTAL的现存值,程序结束尝试用IF函数检查输入的自变量是否小于或等于0;若条件成立则不执行余下的程序(DEFUN SUM (NUM) (IF (<= NIM 0) (PRINC "Input Error")(PROGN略过 WHILE 及 PRINC 函数))(PRINC))程序说明。
Lisp语言的基本语法与应用

Lisp语言的基本语法与应用Lisp(List Processing)是一种函数式编程语言,它以列表为基础数据结构并使用S表达式(S-expression)进行编程。
本文将介绍Lisp语言的基本语法和应用。
一、基本语法1. 原子(Atom):Lisp的基本数据单位,可以是数字、字符串或符号。
例如,数字1、字符串"Hello, World!"和符号'hello都是Lisp的原子。
2. 列表(List):Lisp的核心数据结构,由左括号、元素列表和右括号组成。
列表中的元素可以是原子,也可以是嵌套的列表。
例如,(12 3)和('a ('b 'c))都是合法的Lisp列表。
3. 函数调用:Lisp通过括号表示函数调用,函数名位于第一个元素位置,后跟参数列表。
例如,(+ 1 2)表示调用加法函数,将1和2相加。
4. 定义变量:Lisp使用defvar或setq关键字用于定义变量。
defvar用于定义全局变量,setq用于定义局部变量。
例如,(defvar *pi* 3.14)定义了一个全局变量*pi*,(setq x 10)定义了一个局部变量x并赋值为10。
二、基本应用1. 计算器:Lisp提供了基本的数学运算函数,例如加法(+),减法(-),乘法(*)和除法(/)等。
可以通过使用这些函数进行算术计算。
2. 条件判断:Lisp中的条件判断使用if函数,语法形式为(if condition then else)。
当condition为真时,执行then部分的代码,否则执行else部分的代码。
例如,(if (> x 0) (print "x is positive") (print "x is negative"))根据变量x的值输出不同的结果。
3. 循环:Lisp的循环结构通过使用循环宏(loop macro)实现。
LISP编程语言教学手册说明书

1About the T utorialLISP is the second-oldest high-level programming language after Fortran and has changed a great deal since its early days, and a number of dialects have existed over its history. Today, the most widely known general-purpose LISP dialects are Common LISP and Scheme.This tutorial takes you through features of LISP Programming language by simple and practical approach of learning.AudienceThis reference has been prepared for the beginners to help them understand the basic to advanced concepts related to LISP Programming language.PrerequisitesBefore you start doing practice with various types of examples given in this reference, we assume that you are already aware of the fundamentals of computer programming and programming languages.Copyright & DisclaimerCopyright 2014 by Tutorials Point (I) Pvt. Ltd.All the content and graphics published in this e-book are the property of Tutorials Point (I) Pvt. Ltd. The user of this e-book is prohibited to reuse, retain, copy, distribute or republish any contents or a part of contents of this e-book in any manner without written consent of the publisher.You strive to update the contents of our website and tutorials as timely and as precisely as possible, however, the contents may contain inaccuracies or errors. Tutorials Point (I) Pvt. Ltd. provides no guarantee regarding the accuracy, timeliness or completeness of our website or its contents including this tutorial. If you discover any errors on our website or in this tutorial, please notify us at **************************iT able of ContentsAbout the Tutorial (i)Audience (i)Prerequisites (i)Copyright & Disclaimer (i)Table of Contents (ii)1.OVERVIEW (1)Features of Common LISP (1)Applications Developed in LISP (1)2.ENVIRONMENT SETUP (3)How to Use CLISP (3)3.PROGRAM STRUCTURE (4)A Simple LISP Program (4)LISP Uses Prefix Notation (5)Evaluation of LISP Programs (5)The 'Hello World' Program (6)4.BASIC SYNTAX (7)Basic Elements in LISP (7)Adding Comments (8)Notable Points (8)LISP Forms (8)Naming Conventions in LISP (9)Use of Single Quotation Mark (9)5.DATA TYPES (11)Type Specifiers in LISP (11)6.MACROS (14)Defining a Macro (14)7.VARIABLES (15)Global Variables (15)Local Variables (16)8.CONSTANTS (18)9.OPERATORS (19)Arithmetic Operations (19)Comparison Operations (20)Logical Operations on Boolean Values (22)Bitwise Operations on Numbers (24)10.DECISION MAKING (27)The cond Construct in LISP (28)The if Construct (29)The when Construct (30)The case Construct (31)11.LOOPS (32)The loop Construct (33)The loop for Construct (33)The do Construct (35)The dotimes Construct (36)The dolist Construct (37)Exiting Gracefully from a Block (38)12.FUNCTIONS (40)Defining Functions in LISP (40)Optional Parameters (41)Keyword Parameters (43)Returning Values from a Function (43)Lambda Functions (45)Mapping Functions (45)13.PREDICATES (47)14.NUMBERS (51)Various Numeric Types in LISP (52)Number Functions (53)15.CHARACTERS (56)Special Characters (56)Character Comparison Functions (57)16.ARRAYS (59)17.STRINGS (66)String Comparison Functions (66)Case Controlling Functions (68)Trimming Strings (69)Other String Functions (70)18.SEQUENCES (73)Creating a Sequence (73)Generic Functions on Sequences (73)Standard Sequence Function Keyword Arguments (76)Finding Length and Element (76)Modifying Sequences (77)Sorting and Merging Sequences (78)Sequence Predicates (79)19.LISTS (81)The Cons Record Structure (81)Creating Lists with list Function in LISP (82)List Manipulating Functions (83)Concatenation of car and cdr Functions (85)20.SYMBOLS (86)Property Lists (86)21.VECTORS (89)Creating Vectors (89)Fill Pointer Argument (90)22.SET (92)Implementing Sets in LISP (92)Checking Membership (93)Set Union (94)Set Intersection (95)Set Difference (96)23.TREE (98)Tree as List of Lists (98)Tree Functions in LISP (98)Building Your Own Tree (100)Adding a Child Node into a Tree (100)24.HASH TABLE (103)Creating Hash Table in LISP (103)Retrieving Items from Hash Table (104)Adding Items into Hash Table (104)Applying a Specified Function on Hash Table (106)25.INPUT & OUTPUT (107)Input Functions (107)Reading Input from Keyboard (108)Output Functions (110)Formatted Output (113)26.FILE I/O (115)Opening Files (115)Writing to and Reading from Files (116)Closing a File (118)27.STRUCTURES (119)Defining a Structure (119)28.PACKAGES (122)Package Functions in LISP (122)Creating a Package (123)Using a Package (123)Deleting a Package (125)29.ERROR HANDLING (127)Signaling a Condition (127)Handling a Condition (127)Restarting or Continuing the Program Execution (128)Error Signaling Functions in LISP (131)MON LISP OBJECT SYSTEMS (133)Defining Classes (133)Providing Access and Read/Write Control to a Slot (133)Defining a Class Method (135)Inheritance (136)LISP8LISP stands for LIS t P rogramming. John McCarthy invented LISP in 1958, shortly after the development of FORTRAN. It was first implemented by Steve Russell on an IBM 704 computer. It is particularly suitable for Artificial Intelligence programs, as it processes symbolic information efficiently.Common LISP originated during the decade of 1980 to 1990, in an attempt to unify the work of several implementation groups, as a successor of Maclisp like ZetaLisp and New Implementation of LISP (NIL) etc.It serves as a common language, which can be easily extended for specific implementation. Programs written in Common LISP do not depend on machine-specific characteristics, such as word length etc.Features of Common LISP∙ It is machine-independent∙ It uses iterative design methodology∙ It has easy extensibility∙ It allows to update the programs dynamically∙ It provides high level debugging.∙ It provides advanced object-oriented programming.∙ It provides convenient macro system.∙ It provides wide-ranging data types like, objects, structures, lists, vectors, adjustable arrays, hash-tables, and symbols.∙ It is expression-based.∙ It provides an object-oriented condition system.∙ It provides complete I/O library.∙ It provides extensive control structures.1. OVERVIEWLISPApplications Developed in LISPThe following applications are developed in LISP: Large successful applications built in LISP.∙Emacs: It is a cross platform editor with the features of extensibility, customizability, self-document ability, and real-time display.∙G2∙AutoCad∙Igor Engraver∙Yahoo Store9LISP10CLISP is the GNU Common LISP multi-architechtural compiler used for setting up LISP in Windows. The Windows version emulates Unix environment using MingW under Windows. The installer takes care of this and automatically adds CLISP to the Windows PATH variable.You can get the latest CLISP for Windows at:/projects/clisp/files/latest/downloadIt creates a shortcut in the Start Menu by default, for the line-by-line interpreter.How to Use CLISPDuring installation, CLISP is automatically added to your PATH variable if you select the option (RECOMMENDED). It means that you can simply open a new Command window and type "clisp" to bring up the compiler. To run a *.lisp or *.lsp file, simply use: clisp hello.lisp2. ENVIRONMENT SETUPLISP11LISP expressions are called symbolic expressions or S-expressions. The S-expressions are composed of three valid objects:∙ Atoms ∙ Lists ∙StringsAny S-expression is a valid program. LISP programs run either on an interpreter or as compiled code.The interpreter checks the source code in a repeated loop, which is also called the Read-Evaluate-Print Loop (REPL). It reads the program code, evaluates it, and prints the values returned by the program.A Simple LISP ProgramLet us write an s-expression to find the sum of three numbers 7, 9 and 11. To do this, we can type at the interpreter prompt ->: (+7911)LISP returns the following result: 27If you would like to execute the same program as a compiled code, then create a LISP source code file named myprog.lisp and type the following code in it: (write(+7911))When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is: 273. PROGRAM STRUCTURELISP Uses Prefix NotationIn prefix notation, operators are written before their operands. You might have noted that LISP uses prefix notation. In the above program, the ‘+’ symbol works as a function name for the process of summation of the numbers.For example, the following expression,a * (b +c ) / dis written in LISP as:(/ (* a (+ b c) ) d)Let us take another example. Let us write code for converting Fahrenheit temperature of 60o F to the centigrade scale:The mathematical expression for this conversion is:(60 * 9 / 5) + 32Create a source code file named main.lisp and type the following code in it:(write(+ (* (/ 9 5) 60) 32))When you click the Execute button, or type Ctrl+E, MATLAB executes it immediately and the result is:140Evaluation of LISP ProgramsThe LISP program has two parts:∙Translation of program text into LISP objects by a reader program.∙Implementation of the semantics of the language in terms of LSIP objects by an evaluator program.The evaluation program takes the following steps:∙The reader translates the strings of characters to LISP objects or s-expressions.12∙The evaluator defines syntax of LISP forms that are built from s-expressions.∙This second level of evaluation defines a syntax that determines which s-expressions are LISP forms.∙The evaluator works as a function that takes a valid LISP form as an argument and returns a value. This is the reason why we put the LISP expression in parenthesis, because we are sending the entire expression/form to the evaluator as argument.The 'Hello World' ProgramLearning a new programming language does not really take off until you learn how to greet the entire world in that language, right ?Let us create new source code file named main.lisp and type the following code in it:(write-line "Hello World")(write-line "I am at 'Tutorials Point'! Learning LISP")When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:Hello WorldI am at 'Tutorials Point'! Learning LISP13LISP14This chapter introduces you to basic syntax structure in LISP.Basic Elements in LISPLISP programs are made up of three basic elements:∙ atom ∙ list ∙stringAn atom is a number or string of contiguous characters. It includes numbers and special characters. The following examples show some valid atoms: hello-from-tutorials-point name 123008907 *hello* Block#221 abc123A list is a sequence of atoms and/or other lists enclosed in parentheses. The following examples show some valid lists: ( i am a list) (a ( a b c) d e fgh)(father tom ( susan bill joe)) (sun mon tue wed thur fri sat) ( )A string is a group of characters enclosed in double quotation marks. The following examples show some valid strings:4. BASIC SYNTAX" I am a string""a ba c d efg #$%^&!""Please enter the following details:""Hello from 'Tutorials Point'! "Adding CommentsThe semicolon symbol (;) is used for indicating a comment line.Example(write-line "Hello World") ; greet the world; tell them your whereabouts(write-line "I am at 'Tutorials Point'! Learning LISP")When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result returned is:Hello WorldI am at 'Tutorials Point'! Learning LISPNotable PointsThe following important points are notable:∙The basic numeric operations in LISP are +, -, *, and /∙LISP represents a function call f(x) as (f x), for example cos(45) is written as cos 45∙LISP expressions are not case-sensitive. Means, cos 45 or COS 45 are same.∙LISP tries to evaluate everything, including the arguments of a function. Only three types of elements are constants and always return their own value:o Numberso The letter t, that stands for logical trueo The value nil, that stands for logical false, as well as an empty list.15LISP FormsIn the previous chapter, we mentioned that the evaluation process of LISP code takes the following steps:∙The reader translates the strings of characters to LISP objects or s-expressions.∙The evaluator defines syntax of LISP forms that are built from s-expressions.This second level of evaluation defines a syntax that determines which s-expressions are LISP forms.A LISP form can be:∙An atom∙An empty list or non-list∙Any list that has a symbol as its first elementThe evaluator works as a function that takes a valid LISP form as an argument and returns a value.This is the reason why we put the LISP expression in parenthesis,because we are sending the entire expression/form to the evaluator as argument.Naming Conventions in LISPName or symbols can consist of any number of alphanumeric characters other than whitespace, open and closing parentheses, double and single quotes, backslash, comma, colon, semicolon and vertical bar. To use these characters in a name, you need to use escape character (\).A name can have digits but must not be made of only digits, because then it would be read as a number. Similarly a name can have periods, but cannot be entirely made of periods.Use of Single Quotation MarkLISP evaluates everything including the function arguments and list members.At times, we need to take atoms or lists literally and do not want them evaluated or treated as function calls. To do this, we need to precede the atom or the list with a single quotation mark.16The following example demonstrates this:Create a file named main.lisp and type the following code into it:(write-line "single quote used, it inhibits evaluation")(write '(* 2 3))(write-line " ")(write-line "single quote not used, so expression evaluated")(write (* 2 3))When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:single quote used, it inhibits evaluation(* 2 3)single quote not used, so expression evaluated617LISP18LISP data types can be categorized as:Scalar types - numbers, characters, symbols etc. Data structures - lists, vectors, bit-vectors, and strings.Any variable can take any LISP object as its value, unless you declare it explicitly. Although, it is not necessary to specify a data type for a LISP variable, however, it helps in certain loop expansions, in method declarations and some other situations that we will discuss in later chapters.The data types are arranged into a hierarchy. A data type is a set of LISP objects and many objects may belong to one such set.The typep predicate is used for finding whether an object belongs to a specific type. The type-of function returns the data type of a given object.T ype Specifiers in LISPType specifiers are system-defined symbols for data types.Array fixnum package simple-string Atom float pathname simple-vector Bignum function random-state single-float Bit hash-table Ratio standard-char bit-vector integer Rational stream Character keyword readtable string [common]listsequence[string-char]5. DATA TYPESLISP compiled-function long-float short-float symbolComplex nill signed-byte tCons null simple-array unsigned-bytedouble-float number simple-bit-vector vectorApart from these system-defined types, you can create your own data types. When a structure type is defined using defstruct function, the name of the structure type becomes a valid type symbol.>/p>Example 1Create new source code file named main.lisp and type the following code in it:(setq x 10)(setq y 34.567)(setq ch nil)(setq n 123.78)(setq bg 11.0e+4)(setq r 124/2)(print x)(print y)(print n)(print ch)(print bg)(print r)When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result returned is:1034.567123.78NIL19LISP110000.062Example 2Next let us check the types of the variables used in the previous example. Create new source code file named main.lisp and type the following code in it:(setq x 10)(setq y 34.567)(setq ch nil)(setq n 123.78)(setq bg 11.0e+4)(setq r 124/2)(print (type-of x))(print (type-of y))(print (type-of n))(print (type-of ch))(print (type-of bg))(print (type-of r))When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:(INTEGER 0 281474976710655)SINGLE-FLOATSINGLE-FLOATNULLSINGLE-FLOAT(INTEGER 0 281474976710655)20LISP 21LISP22This chapter introduces you about macros in LISP.A macro is a function that takes an s-expression as arguments and returns a LISP form, which is then evaluated. Macros allow you to extend the syntax of standard LISP.Defining a MacroIn LISP, a named macro is defined using another macro named defmacro. Syntax for defining a macro is:(defmacro macro-name (parameter-list)"Optional documentation string."body-form)The macro definition consists of the name of the macro, a parameter list, an optional documentation string, and a body of LISP expressions that defines the job to be performed by the macro.ExampleLet us write a simple macro named setTo10, which takes a number and sets its value to 10.Create new source code file named main.lisp and type the following code in it: defmacro setTo10(num)(setq num 10)(print num))(setq x 25)(print x)(setTo10 x)When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:6. MACROSLISP251023LISP24In LISP, each variable is represented by a symbol. The name of the variable is the name of the symbol and it is stored in the storage cell of the symbol. Global V ariablesGlobal variables are generally declared using the defvar construct. Global variables have permanent values throughout the LISP system and remain in effect until new values are specified.Example(defvar x 234)(write x)When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:234As there is no type declaration for variables in LISP, you need to specify a value for a symbol directly with the setq construct.Example->(setq x 10)The above expression assigns the value 10 to the variable x. You can refer to the variable using the symbol itself as an expression.The symbol-value function allows you to extract the value stored at the symbol storage place.ExampleCreate new source code file named main.lisp and type the following code in it: (setq x 10)(setq y 20)7. VARIABLES(format t "x = ~2d y = ~2d ~%" x y)(setq x 100)(setq y 200)(format t "x = ~2d y = ~2d" x y)When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:x = 10 y = 20x = 100 y = 200Local V ariablesLocal variables are defined within a given procedure. The parameters named as arguments within a function definition are also local variables. Local variables are accessible only within the respective function.Like the global variables, local variables can also be created using the setq construct. There are two other constructs - let and prog for creating local variables.The let construct has the following syntax:(let ((var1 val1) (var2 val2).. (varn valn))<s-expressions>)Where var1, var2,…,varn are variable names and val1, val2,…, valn are the initial values assigned to the respective variables.When let is executed, each variable is assigned the respective value and at last, the s-expression is evaluated. The value of the last expression evaluated is returned.If you do not include an initial value for a variable, the variable is assigned to nil. ExampleCreate new source code file named main.lisp and type the following code in it:(let ((x 'a)(y 'b)(z 'c))(format t "x = ~a y = ~a z = ~a" x y z))25When you click the Execute button, or type Ctrl+E, LISP executes it immediately and the result is:x = A y = B z = CThe prog construct also has the list of local variables as its first argument, which is followed by the body of the prog,and any number of s-expressions.26End of ebook previewIf you liked what you saw…Buy it from our store @ https://27。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
LISP语言教程作者:牛魔王—上次修改时间: 2007-03-22 13:13Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
Scheme 语言概要Author: 宋国伟吉林省德惠市信息中心Date: 2003 年 12 月 01 日Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
作为Lisp 变体,Scheme 是一门非常简洁的计算语言,使用它的编程人员可以摆脱语言本身的复杂性,把注意力集中到更重要的问题上,从而使语言真正成为解决问题的工具。
本文分为上、下两部分来介绍 scheme 语言。
一.Scheme语言的特点Scheme 语言是LISP语言的一个方言(或说成变种),它诞生于1975年的MIT,对于这个有近三十年历史的编程语言来说,它并没有象C++,java,C#那样受到商业领域的青睐,在国内更是显为人知。
但它在国外的计算机教育领域内却是有着广泛应用的,有很多人学的第一门计算机语言就是Scheme语言。
它是一个小巧而又强大的语言,作为一个多用途的编程语言,它可以作为脚本语言使用,也可以作为应用软件的扩展语言来使用,它具有元语言特性,还有很多独到的特色,以致于它被称为编程语言中的"皇后"。
下面是洪峰对Scheme语言的编程特色的归纳:∙词法定界(Lexical Scoping)∙动态类型(Dynamic Typing)∙良好的可扩展性∙尾递归(Tail Recursive)∙函数可以作为值返回∙支持一流的计算连续∙传值调用(passing-by-value)∙算术运算相对独立本文的目的是让有编程基础(那怕是一点点)的朋友能尽快的掌握Scheme语言的语法规则,如果您在读完本文后,发现自己已经会用Scheme语言了,那么我的目的就达到了。
二.Scheme语言的标准与实现R5RS (Revised(5) Report on the Algorithmic Language Scheme)Scheme语言的语法规则的第5次修正稿,1998年制定,即Scheme语言的现行标准,目前大多数Scheme语言的实现都将达到或遵循此标准,并且几乎都加入了一些属于自己的扩展特色。
Guile (GNU's extension language)Guile是GNU工程的一个项目,它是GNU扩展语言库,它也是Scheme语言的一个具体实现;如果你将它作为一个库打包,可以把它链接到你的应用程序中去,使你的应用程序具有自己的脚本语言,这个脚本语言目前就是Scheme语言。
Guile可以在LINUX和一些UNIX系统上运行,下面是简单的安装过程:下载guile-1.6.4版,文件名为guile-1.6.4.tar.gz,执行下面的命令:tar xvfz guile-1.6.4.tar.gzcd guile-1.6.4./configuremakemake install如此,即可以执行命令guile,进入guile>提示符状态,输入调试Scheme程序代码了,本文的所有代码都是在guile下调试通过。
其它实现除了Guile外,Scheme语言的实现还有很多,如:GNU/MIT-Scheme, SCI,Scheme48,DrScheme等,它们大多是开源的,可以自由下载安装使用,并且跨平台的实现也很多。
你会发现既有象basic的 Scheme语言解释器,也有将Scheme 语言编译成C语言的编译器,也有象JAVA那样将Scheme语言代码编译成虚拟机代码的编译器。
三.基本概念注释Scheme语言中的注释是单行注释,以分号[;]开始一直到行尾结束,其中间的内容为注释,在程序运行时不做处理,如:; this is a scheme comment line.标准的Scheme语言定义中没有多行注释,不过在它的实现中几乎都有。
在Guile 中就有多行注释,以符号组合"#!"开始,以相反的另一符号组合"!#"结束,其中内容为注释,如:#!there are scheme comment area.you can write mulity lines here .!#注意的是,符号组合"#!"和"!#"一定分做两行来写。
Scheme用做脚本语言Scheme语言可以象sh,perl,python等语言那样作为一种脚本语言来使用,用它来编写可执行脚本,在Linux中如果通过Guile用Scheme语言写可执行脚本,它的第一行和第二行一般是类似下面的内容:#! /usr/local/bin/guile -s!#这样的话代码在运行时会自动调用Guile来解释执行,标准的文件尾缀是".scm"。
块(form)块(form)是Scheme语言中的最小程序单元,一个Scheme语言程序是由一个或多个form构成。
没有特殊说明的情况下 form 都由小括号括起来,形如:(define x 123)(+ 1 2)(* 4 5 6)(display "hello world")一个 form 也可以是一个表达式,一个变量定义,也可以是一个过程。
form嵌套Scheme语言中允许form的嵌套,这使它可以轻松的实现复杂的表达式,同时也是一种非常有自己特色的表达式。
下图示意了嵌套的稍复杂一点的表达式的运算过程:变量定义可以用define来定义一个变量,形式如下:(define 变量名值)如: (define x 123) ,定义一个变量x,其值为123。
更改变量的值可以用set!来改变变量的值,格式如下:(set! 变量名值)如: (set! x "hello") ,将变量x的值改为"hello" 。
Scheme语言是一种高级语言,和很多高级语言(如python,perl)一样,它的变量类型不是固定的,可以随时改变。
四.数据类型1. 简单数据类型逻辑型(boolean)最基本的数据类型,也是很多计算机语言中都支持的最简单的数据类型,只能取两个值:#t,相当于其它计算机语言中的 TRUE;#f,相当于其它计算机语言中的 FALSE。
Scheme语言中的boolean类型只有一种操作:not。
其意为取相反的值,即:(not #f) => #t(not #t) => #fnot的引用,与逻辑非运算操作类似guile> (not 1)#fguile> (not (list 1 2 3))#fguile> (not 'a)#f从上面的操作中可以看出来,只要not后面的参数不是逻辑型,其返回值均为#f。
数字型(number)它又分为四种子类型:整型(integer),有理数型(rational),实型(real),复数型(complex);它们又被统一称为数字类型(number)。
如:复数型(complex) 可以定义为 (define c 3+2i) 实数型(real)可以定义为 (define f 22/7) 有理数型(rational)可以定义为 (define p 3.1415) 整数型(integer) 可以定义为 (define i 123)Scheme 语言中,数字类型的数据还可以按照进制分类,即二进制,八进制,十进制和十六进制,在外观形式上它们分别以符号组合 #b、 #o、 #d、 #x 来作为表示数字进制类型的前缀,其中表示十进制的#d可以省略不写,如:二进制的 #b1010 ,八进制的 #o567,十进制的123或 #d123,十六进制的 #x1afc 。
Scheme语言的这种严格按照数学定理来为数字类型进行分类的方法可以看出Scheme语言里面渗透着很深的数学思想,Scheme语言是由数学家们创造出来的,在这方面表现得也比较鲜明。
字符型(char)Scheme语言中的字符型数据均以符号组合 "#\" 开始,表示单个字符,可以是字母、数字或"[ ! $ % & * + - . / : < = > ? @ ^ _ ~ ]"等等其它字符,如:#\A 表示大写字母A,#\0表示字符0,其中特殊字符有:#\space 表示空格符和 #\newline 表示换行符。
符号型(symbol)符号类型是Scheme语言中有多种用途的符号名称,它可以是单词,用括号括起来的多个单词,也可以是无意义的字母组合或符号组合,它在某种意义上可以理解为C中的枚举类型。
看下面的操作:guile> (define a (quote xyz)) ; 定义变量a为符号类型,值为xyz guile> axyzguile> (define xyz 'a) ; 定义变量xyz为符号类型,值为aguile> xyza此处也说明单引号' 与quote是等价的,并且更简单一些。
符号类型与字符串不同的是符号类型不能象字符串那样可以取得长度或改变其中某一成员字符的值,但二者之间可以互相转换。
2. 复合数据类型可以说复合数据类型是由基本的简单数据类型通过某种方式加以组合形成的数据类型,特点是可以容纳多种或多个单一的简单数据类型的数据,多数是基于某一种数学模型创建的。
字符串(string) 由多个字符组成的数据类型,可以直接写成由双引号括起的内容,如:"hello" 。
下面是Guile中的字符串定义和相关操作:guile> (define name "tomson")guile> name"tomson"guile> (string-length name) ; 取字符串的长度6guile> (string-set! name 0 #\g) ; 更改字符串首字母(第0个字符)为小写字母g (#\g)guile> name"gomson"guile> (string-ref name 3) ; 取得字符串左侧第3个字符(从0开始)#\s字符串还可以用下面的形式定义:guile> (define other (string #\h #\e #\l #\l #\o ))guile> other"hello"字符串中出现引号时用反斜线加引号代替,如:"abc\"def" 。