2019独角兽企业重金招聘Python工程师标准>>>

Scheme语言入门

最早听说 LISP,是 Stallman 的 GNU Emacs 中将 LISP 作为嵌入语言,定制和增强 Emacs。GNU Emacs 是一个文本编辑器,文本就是一种符号,而 Lisp 正好就是针对符号计算发明的,因此在GNU Emacs 中使用 Lisp 是顺理成章的事情。

Lisp 语言的历史已经很久了,几乎与 Fortran 一样长。二十世纪五十年代,计算机科学家先是发明了针对数字计算的 Fortran 语言,后来针对符号计算,由MIT 的John McCarthy于1960年开发出了Lisp(List processing)语言。该语言原来是为表处理而设计的编程语言,后来广泛用于处理人工智能问题。Lisp 程序中充满了一对对嵌套的小括号,这些嵌套的符号表达式体现着递归。递归是数学上的基本概念之一,从递归理论出发,一切可以计算的函数最终都可以划归为几种基本的递归函数的种种组合。

1994年时众多 Lisp 版本又得到了相当的统一,统一之后的版本称为Common LISP。Common Lisp 含有非常丰富的库,仅仅语言的规范就长达千页以上,包括面向对象的 CLOS。

Scheme 语言是 Lisp 的一个现代变种、方言,诞生于1975年,由 MIT 的 Gerald J. Sussman and Guy L. Steele Jr. 完成。Scheme语言的规范很短,总共只有50页,甚至连Common Lisp 规范的索引的长度都不到,但是却被称为是现代编程语言王国的皇后。它与以前和以后的 Lisp 实现版本都存在一些差异,但是却易学易用。

DSSSL需要完成的工作是解析文档,它的设计就采用了Scheme语言。本书时介绍DocBook的专著,因此并不打算写一个Scheme大全,只是想通过蜻蜓点水的介绍使读者认识Scheme,能够达到看懂和简单的修改DSSSL。

Scheme特点

Scheme语言具有它独特的魅力,看看Scheme的语法特点:

  • 括号嵌套

    Lisp 程序中充满了一对对嵌套的小括号,这些嵌套的符号体现了最基本的数学思想——递归。

  • 语法简洁

    Scheme语言的规范很短,总共只有50页。

  • 函数编程语言

    一个函数(Function)是这个编程语言中所谓的第一等的公民。也就是说函式可以像一个 int 或者 float 一样被很方便的传递来传递去。这也就是所谓"Functional 编程语言"中,Functional 一词的由来。

  • 自动内存管理

    自动内存管理可不是JAVA的专利呦。

  • 可移植性好

    Scheme开发的程序有很好的可移植性,这是由于Scheme是一种解释语言,在不同的平台都可以有相应的解释器。

  • 适合于作为脚本语言和嵌入语言

    语法简洁,这使得Scheme的实现可以非常的经济,一个Scheme解释器可以非常的小巧。Scheme可以作为脚本语言而内嵌于一些工具之中,如:GNU Emacs。

其他特点还有,关键字对大小写不敏感。

数据结构

  • 数字

    下面都是合法的数字表示方法:47,1/3,2.3,4.3e14,1+3i。

  • 字符

    字符前面需要用#\做前缀。如下面都是合法字符:

    #\a #\A #\b #\B #\space #\newline

  • 字符串

    由双引号括起来的字符组成字符串。如:"A little string"

  • 布尔值

    布尔值True和False分别用 #t 和 #f 表示。

  • 列表

    用圆括号括起来的,可以包含任何数据类型的称为列表。如: (a little (list of) (lists))

  • 数组(vector)

    用#为前缀,如: #(1 2 "string" #\x 5)

  • 函数(或称为过程)

    把函数作为一种数据类型,是Scheme语言的特色。

  • 符号

    符号除了不能够以数字开头的任何字符可组成符号。如:Symbols: this-is-a-symbol foo a32 c$23*4&7+3-is-a-symbol-too!

表达式和函数

注释

分号开始一段注释。如:

(+ 3 1) ;return 4

常量表达式

  1. 常量表达式

    常量表达式返回本身的值。如:

    3.14 ; 返回 3.14 #t ; 返回布尔值 #t #\c ; 返回字符 #\c "Hi!" ; 返回字符串 "Hi!"
  2. 引用(Quotation)

    语法:(quote obj)  或者简写为 'obj

    (+ 2 3)   ; 返回 5 '(+ 2 3)  ; 返回列表 (+ 2 3) (quote (+ 2 3)) ; 返回列表 (+ 2 3)

表达式记法

Scheme的表达式的写法有些特别,表达式用括号括起来。括号里面的第一个出线的是函数名或者操作符,其它是参数。Scheme的这种表达式写法可以叫做前置式。下面是一些Scheme的表达式的例子以及其对应的C语言的写法。

  Scheme                               C ------------------------------------------------------------------ (+ 2 3 4)                       (2 + 3 + 4)  (< low x high)                  ((low < x) && (x < high))  (+ (* 2 3)                      (* 4 5)) ((2 * 3) + (4 * 5))  (f x y)                         f(x, y)  (define (sq x) (* x x))         int sq(int x) { return (x * x) }

赋值和函数定义

  1. let 表达式和赋值

    语法:(let ((var val) ...) exp1 exp2 ...)

    说明:let 表达式的赋值只在表达式内部有效。

    示例:

    (let ((x 2) (y 3)) (+ x y))

    ; 先赋值: x=2, y=3,再计算x+y的值,结果为5。注意 (x 2) 和 (y 3) 外还有一层括号。

    更多的示例:

    (let ((f +))   (f 2 3))  ; return 5  (let ((f +) (x 2))   (f x 3))  ; return 5  (let ((f +) (x 2) (y 3))   (f x y))  ; return 5
  2. 用define 和 set! 赋值

    语法:(define var exp)  , (set! var exp)

    说明:define和 set! 表达式的赋值在全局有效。define 和 set! 的区别是define既能赋值又能定义变量,而set!只能对已经定义的变量赋值。

    示例:

    (define a 1)   a ; return 1 (set! a 2) a ; return 2 (let ((a 3)) a)  ; return 3 a ; return 2 (let ((a 3)) (set! a 4) a) ; return 4 a ; return 2 (let ((a 3)) (define a 5) a) ; return 5 a ; return 2 (set! b 1) ; 错误,b尚未定义
  3. lambda 表达式和函数定义

    语法:(lambda (var ...) exp1 exp2 ...)

    说明:lambda 表达式用于定义函数。var ... 是参数,exp1 exp2 ...是函数的执行 部分。通常需要结合局部定义 let 或者全局定义表达式 define,再进行函数调用。

    示例:

    ((lambda (x) (+ x x)) (* 3 4))  ; return 24

    说明:先用lambda定义了函数,参数是x,函数返回x+x。同时该语句也完成了函数调用,实参是 12 (等于3*4),因此返回值是 24 (等于12+12)。

  4. 在let表达式中定义函数。

    Scheme语言中,函数作为一种数据类型,通过赋值语句,将lambda表达式赋值给相应的函数。

    示例:

    (let ((double (lambda (x) (+ x x))))   (list (double (* 3 4))         (double (/ 99 11))         (double (- 2 7))))     ; return (24 18 -10)

    说明:let表达式将lambda定义的函数赋值给double,参数是x,返回 x+x。接下来分别三次调用 double 函数,并将结果以列表形式返回。list 表达式负责生成列表。

  5. 用define全局定义表达式来定义函数。

    用 let 定义的函数只能在 let 表达式中有效,如果想定义在整个程序中有效的函数定义,需要用到全局定义表达式——define。

    示例:

    (define double (lambda (x) (+ x x))) (double 12)            ; return 24 (double (* 3 4))       ; return 24

    说明:define表达式定义了全局有效的函数 double。两次调用double的返回值都是 24。

  6. 定义函数的简写

    用 define 定义的函数的语法可以简化,即将 lambda 去掉。即将语法

    (define var0   (lambda (var1 ... varn)     e1 e2 ...))

    简写为:

    (define (var0 var1 ... varn)   e1 e2 ...)

    示例:

    (define (double x) (+ x x)) (double 12)            ; return 24 (double (* 3 4))       ; return 24

    说明:本例是前一个例子的简化版本。更简介,明了。

顺序计算表达式

语法:(begin exp1 exp2 ...)

说明:顺序执行表达式 exp1, exp2, ...,返回最后一个表达式的结果

示例:

(define x 3) (begin   (set! x (+ x 1))   (+ x x))             ; 返回结果 8

说明:begin 表达式,依次先用set!表达式为x赋值为4,在运算x+x,返回结果8。

条件表达式

  1. 关系运算符

    (< -1 0)   #t (> -1 0)   #f  (eqv? 'a 'a)  #t
  2. 逻辑运算

    (not #t)   #f (not #f)  #t  (not 1)   #f (not '(a b c))   #f  (or)   #f (or #f)   #f (or #f #t)   #t (or #f 'a #f)   a  (and)   #t (and #f)   #f (and #f #t)   #f (and #f 'a #f)   #f (and 'a #t 'b) 'b
  3. if 表达式

    语法:(if test consequent alternative)

    说明:如果test表达式为真,返回 consequent,否则返回 alternative。

    示例:

    (define (abs n)     (if (< n 0)         (- 0 n)         n))

    说明:函数abs功能为取绝对值。

  4. cond 表达式

    语法:(cond (test exp) ... (else exp))

    说明:多路分支判断表达式,类似于C语言的 "if ... else if ... else"。

    示例:

    (define abs   (lambda (n)     (cond       ((= n 0) 0)       ((< n 0) (- 0 n))       (else n))))

    说明:用cond表达式重新实现取绝对值函数 abs。

  5. case 表达式

    语法:(case exp0 clause1 clause2 ... )

    clause 的语法结构为:((key1 ...) exp1 ...) 最后一个表达式的结构可以为:(else exp1 exp2 ...)

    说明:类似于C语言的 "switch ... case..." 语句。

    示例:

    (let ((x 4) (y 5))   (case (+ x y)     ((1 3 5 7 9) 'odd)     ((0 2 4 6 8) 'even)     (else 'out-of-range))) ; 返回 odd

    说明:case 表达式先计算 x+y 的值为9,接下来在key中进行匹配,并返回对应的表达式的值 'odd。

循环

  1. do 表达式

    语法:(do ((var1 val1 update1) ...) (test res ...) exp ...)

    说明:类似于C语言的for循环。先将val1赋值给var1,...,之后循环开始,在每次循环的开始,先执行表达式 test,如果返回布尔值真,则循环终止,并返回结果 res,如果表达式 test返回布尔值#f,则运行表达式 exp...,之后依次用 update1 ... 的值来为变量 var1 ... 重新赋值。

    示例1:计算阶乘 n! = n*(n-1)!

    (define factorial   (lambda (n)     (do ((i n (- i 1)) (a 1 (* a i)))         ((zero? i) a))))  (factorial 10)  ; 返回 3628800

    说明:其对应的C语言实现如下

    long factorial(int n) { int  i=n; long a=1; for (i=n;; i--) { if (i == 0) return a; a *= i; } }

    示例2:计算fibonacci数列:f(n+1)=f(n)+f(n-1) , n>0, f(1)=1, f(0)=0

    (define fibonacci   (lambda (n)     (if (= n 0)         0         (do ((i n (- i 1)) (a1 1 (+ a1 a2)) (a2 0 a1))             ((= i 1) a1)))))  (fibonacci 6)  ; 返回 8

    说明:其对应的C语言实现如下

    long fibonacci(int n) { long f=1; int i = n; int a1= 1; int a2= 0; if (n == 0) return 0; while(1) { if (i == 1) return a1; i--; a1=a1+a2; a2=a1; } }
  2. map 表达式

    语法:(map procedure list1 list2 ...)

    说明:列表 list1 list2 ... 必须具有同样的长度;过程 procedure 接受的参数个数同列表的个数,各个列表中对应的变量分别作为过程 procedure 的参数被执行, 将每次的运算结果以列表形式返回。

    (map abs '(1 -2 3 -4 5 -6))  ; 返回 (1 2 3 4 5 6),abs接受一个参数 (map (lambda (x y) (* x y))      '(1 2 3 4)      '(8 7 6 5)) 返回(8 14 18 20) ,lambda (x y) 接收两个参数
  3. for-each 表达式

    语法:(for-each procedure list1 list2 ...)

    说明:同 map表达式, 但是不返回结果列表。

转载于:https://my.oschina.net/zhoukuo/blog/349453

Scheme语言入门相关推荐

  1. lisp语言cond和if套用_lisp语言入门

    Lisp 语言入门 Lisp 是一门历史悠久的语言,全名叫 LISt Processor ,也就是"表处理语言",它是由 John McCarthy 于 1958 年就开始设计的一 ...

  2. 写一篇C语言入门第一讲

     嗨~大家好~  我是小白,最近才使用这个博客,我是一个计算机系的学生,我会在这里发一些我给我们班其他同学讲C语言入门的博文,希望大家能共享这些资料,当然了,我也很希望大家给我提出好的意见或建议.(P ...

  3. C语言入门练习 - 第二期 判断语句与循环语句(题解)

    比赛地址:C语言入门练习 - 第二期 判断语句与循环语句 A.入门--基础语法(for) #include<stdio.h> int main(){int n,i;scanf(" ...

  4. 计算机书籍-Go语言入门经典SAMS Teach Yourself

    书名:Go语言入门经典 作者:[英]乔治 奥尔波(George Ornbo) 出版社:人民邮电出版社 出版时间:2018年08月 去当当网了解

  5. c语言中描述y是奇数,4章选择结构程序设计C语言入门习题

    C语言入门习题 第四章 选择结构程序设计 一.选择题 1.有以下程序 main() { int i=1,j=2,k=3; if(i++==1&&(++j==3||k++==3)) pr ...

  6. C#forUnity快速入门(连载2)-C#语言入门

     C# for Unity 编程语言快速入门教程(连载2)---C#语言入门 接上篇内容,我们把更多的C#语言入门级编程习题发布如下,希望能够对C#编程小白提高技能有帮助. 三:  学习循环语句(续) ...

  7. python终结一个循环额_Python语言入门之内存管理方式和垃圾回收算法解析

    本文主要向大家介绍了Python语言入门之内存管理方式和垃圾回收算法解析,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 在列表,元组,实例,类,字典和函数中存在循环引用问题.有 ...

  8. VML编程之------VML语言入门《VML极道教程》原著:沐缘华

    <VML极道教程>原著:沐缘华 1章4节:VML语言入门 1:VML语言入门 - 极道学法 在我正式开始讲解.你正式开始学习VML语言以前,请务必遵循以下规则,可以达到最佳效果.极道学习方 ...

  9. c++ 结构体赋值_《零基础看得懂的C语言入门教程》—(十二)结构体是这么回事

    一.学习目标 了解C语言的结构体的使用方法 了解C语言结构体的结构的赋值 了解多种C语言结构体变量的赋值方法和取值方法 目录 <零基础看得懂的C语言入门教程>--(二)简单带你了解流程 & ...

  10. c语言作业ppt模板,C语言入门教学PPT模板

    目前要说发展前景最好的行业,那么就必然是互联网行业了,大部分行业现在都离不开计算机,也就是说学好计算机,走到哪里都不怕,特别是程序员,那么C语言就是首先需要接触的.本模板是由西西为大家整理的C语言入门 ...

最新文章

  1. kvm虚拟化学习笔记(十一)之kvm虚拟机扩展磁盘空间
  2. python自学平台-Python编程和人工智能平台学习
  3. 用Windows Live Writer离线写博客
  4. 时间序列分析源资料汇总
  5. IBM® Bluemix 上运行ASP.NET Core
  6. linux线程间同步(1)读写锁
  7. MySQL Miscellaneous Functions(ip uuid方法)
  8. JavaScript 邮件正则练习
  9. ubuntu的系统服务管理
  10. QTeewidget逐行进行遍历(递归)
  11. Android中app的请求抓包工具 Fiddler 详解
  12. 大一计算机理论知识测试题,2017计算机基础大一考试试题「附答案」
  13. 【黑马程序员】vue学习笔记(未完)
  14. 5操作系统的运行机制和体系结构
  15. MAC VScode 强制重启后保存的代码全没了
  16. 一键制作所有微信好友头像墙照
  17. springboot返回404错误页面
  18. 新研究显示尿石素A (Mitopure®)可改善线粒体健康,减少关节软骨损伤并减轻骨关节炎疼痛
  19. 磁链观测器结合霍尔传感器转子角度方案
  20. 动手做个 AI 机器人,帮我回消息

热门文章

  1. Visio 2013最新产品密钥分享,在安装时可以使用以下密钥:
  2. 中国游戏企业扬帆出海,应该选择怎样的云平台?
  3. 边缘计算相关论文汇总
  4. redhat 8常用命令实践
  5. 领导邀请一起跳槽?搞清楚这5件事再决定
  6. ​ClickHouse在手淘流量分析业务实践
  7. 『SnowFlake』雪花算法的详解及时间回拨解决方案
  8. 计算机应用情话,2018最新版情话大全浪漫情话 好听感人的情话
  9. 电脑小技巧:关于修复只能看无法拖…
  10. 【初识Unity】UI游戏:看看你能答对几题?(游戏可下载)