Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SCIP学习笔记

SCIP学习笔记

作者头像
刘笑江
发布于 2018-05-28 05:42:29
发布于 2018-05-28 05:42:29
1.7K00
代码可运行
举报
文章被收录于专栏:刘笑江的专栏刘笑江的专栏
运行总次数:0
代码可运行

引言

SCIP(Structure and Interpretation of Computer Programs)[1]是MIT自1984年起的编程入门教程,尽管最近他们用Python的课程取代了Lisp语言,但是随着工业界越来越多的应用函数编程语言,如Clojure、Scala、Racket,以及软件开发使用并发的趋势(见文章[2]),重读SCIP是很有意义的。

SCIP分五章:构造过程抽象,构造数据抽象,模块化、对象和状态(涉及并发),源语言抽象,寄存器机器里的计算(编译器如何工作)

环境

OS X下使用IDE DrRacket及其语法插件#PLaneT neil sicp.plt

在文件头使用 #lang planet neil/sicp 声明语言类型

Lisp基本语法

Lisp的原始定义在John McCarthy1960发表的论文[3]

Lisp[4]是一个语言族,包括Common Lisp和Scheme,二者区别见[5]

过程定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(define (<name> <formal parameters>) <body>)

e.g.
(define (square x) (* x x))
(square 13) ; 169
``` 


### 代换模型

> 1. 正则序求值:完全展开后规约
> 
> 2. 应用序求值:先求值参数而后应用,通过替换去模拟,避免重复求值 (Scheme使用)


### 条件表达式

``` scheme
(cond (<p1> <e1>)
	(<p2> <e2>)
	...
	(<pn> <en>))

(cond (<p1> <e1>)
	(else <e2>))
		
(if <predicate> <consequent> <alternative>)

e.g.
(define (abs x)
	(cond 	((> x 0) x)
		((= x 0) 0)
		((< x 0) (- x))))
``` 

### 谓词

``` scheme
((<|=|>) 	<e1> ... <en>)
(and 		<e1> ... <en>)
(or 		<e1> ... <en>)
(not 		<e1> ... <en>)

以上是Scheme的主要语法,可以容易而优雅地生成语法树,没有语法糖。那么递归和迭代怎么用?使用上面的语法规则即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
; 递归法求阶乘
(define (factotrial n)
	(if	(= n 1)
		1
		(* n (factorial (- n 1)))))

; 迭代法求阶乘
(define (fact n)
	(fact-iter 1 1 n))
	
(define (fact-iter product counter max-count)
	(if (> counter max-count)
		product
		(fact-iter (* counter product)
			(+ counter 1)
			max-count)))

高阶函数

过程作为参数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# define ∑f(n), n∈[a,b]
; style 1
(define (sigma f a next b)
	(if (> a b)
		0
		(+ (f a) (sigma f (next a) next b))))

; style 2
(define (sigma_ f a next b)
	(define (iter a result)
		(if (> a b)
			0
			(iter (next a) (+ result (f a)))))
	(iter a 0))


; calc ∑sqrt(n), n∈[1,4]
(define (inc x) (+ x 1))
(sigma sqrt  1 inc 4) ; 3.41
(sigma sqrt_ 1 inc 4) ; 3.41
Lambda构造过程

匿名函数,用法同Python

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(lambda <formal-parameters> <body>)
(lambda <formal-parameters> <body> <values>)

e.g.
(define plus6 (lambda (x) (+ x 6))) ; returns a func

(lambda (x y) (+ x y) 4 5) ; return 9

let表达式,注意var不是变量是常量,无副作用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(let (	(<var1> <exp1>)
		(<var2> <exp2>)
		...
		(<varn> <expn>))
	<body>)

e.g.
(define (circle-len d)
	(let (	(π 3.14) 
			(Ω 1))
		(* d π)))
工具函数

打印

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(define (print x)
	(newline)
	(display x))

(print 3)
;
; 3

以上是Lisp的主要语法规则,非常简练。

至此,SCIP第一章结束,其中有许多练习,余不一一。

构造数据抽象

闭包

(这里指的不是匿名函数)

是在处理符合数据中的一个关键思想:用于组合数据对象的粘合剂,不但能用于组合基本的数据对象,同样也可以用复合数据的对象。

其中,粘合剂指:程序设计语言应该提供的,把一些数据对象组合起来,形成更复杂的数据对象的操作。

Wiki: 闭包是引用了自由变量的函数

序对

用来粘合两个对象,用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(define x (cons 1 2))

(car x)
; 1

(cdr x)
; 2

序对的一种定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(define (cons_ x y)
  (define (dispatch m)
    (cond ((= m 0) x)
          ((= m 1) y)
          (else (error "ar not 0 or 1 -- CONS" m))))
  dispatch)

(define (car_ z) (z 0))
(define (cdr_ z) (z 1))

另一种定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(define (cons__ x y)
	(lambda (m) (m x y)))
	
(define (car__ z)
	(z (lambda (p q) p)))

(define (cdr__ z)
	(z (lambda (p q) q)))
	
e.g.
(car__ (cons__ 33 99)) ;33
(cdr__ (cons__ 33 99)) ;99

序列(列表)

可看做嵌套的序对:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(list <a1> <a1> ... <an> nil)

等价于

(cons <a1> (cons <a2> ... (cons <an> nil) ...))

表操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
; list[0]
(car list)

; list[2:n]
(cdr list)

; list[2]
(car (cdr <list>))
(cadr <list>)

; list[n-1]
(list-ref <list> <n>)

; len(list)
(length <list>)

; list1.append(list2)
(append <list1> <list2>)

; Map
(map <list> <process>)
(reduce <list> <process>)

  1. http://mitpress.mit.edu/sicp/ ↩︎
  2. http://davidlau.me/2015/05/11/notes-on-The-Free-Launch-Is-Over/ ↩︎
  3. http://www-formal.stanford.edu/jmc/recursive.html ↩︎
  4. http://en.wikipedia.org/wiki/Lisp_(programming_language) ↩︎
  5. http://c2.com/cgi/wiki?LispSchemeDifferences ↩︎
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《SICP》读书笔记之一:构造过程抽象(上)
本章节将介绍有关计算过程(computational process)的知识。计算过程是存在于计算机里的一类抽象事物。在其演化过程中,这些过程会去操作一些被称为数据(data)的抽象事物。而人们则会创造程序(programs)来指导这些过程。在正常工作的计算机里,一个计算过程将精密而准确地执行相应的程序。
口仆
2020/08/16
8540
日拱一卒,伯克利CS61A大作业,scheme 解释器(四)
我们来继续肝伯克利CS61A的scheme project,这是本project的第四篇,如果漏掉了之前的内容,可以去翻一下历史记录。
TechFlow-承志
2022/09/21
1.2K1
日拱一卒,伯克利CS61A大作业,scheme 解释器(四)
Lisp 学习资源集锦
http://acl.readthedocs.io/en/latest/zhCN/index.html
一个会写诗的程序员
2018/08/17
1.9K0
日拱一卒,伯克利CS61A,居然有Lisp这样的语言……
我们继续来肝伯克利CS61A,今天我们看的是作业8。这一次的作业有些特殊,不再是基于Python,而是一门全新的语言Lisp。
TechFlow-承志
2022/09/21
1K0
日拱一卒,伯克利CS61A,居然有Lisp这样的语言……
日拱一卒,期末测试,伯克利61A完结篇
从四月初至今,经过了一个多月的漫长学习,我们终于迎来了它的尾声。说真的,从看视频,到写作业、做实验再到把相应的内容写成文章。这一步一步下来,我真的有一种重新回到课堂上课的感觉。即使之前学过Python,对算法也有一定的了解,这节课下来也依然收获满满。
TechFlow-承志
2022/09/21
5940
日拱一卒,期末测试,伯克利61A完结篇
JavaScript: 挑战函数式数据结构
先前想在自己的 函数式方言解释器 里实现 元组 这种数据结构,但是没有什么方向,就去看了下 Scheme 的语法,看了下 Wiki,然后不知不觉间,看到了用 Lisp 实现 Pair。
腾讯IVWEB团队
2020/06/28
7960
众数的算法分析
  所谓众数,源于这样的一个题目:一个长度为len的数组,其中有个数出现的次数大于len/2,如何找出这个数。
窗户
2020/04/16
1.1K0
Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序” 1,表达式2,原子3,表(list) 4,点对(pair)5,向量(vector)6,变量7,
2020的春季中小学受疫情影响,一直还没有开学,孩子宅在家说想做一个学校要求的研究项目,我就说你做一个怎么样通过编程来学习数学的小项目吧,用最简单的计算机语言来解决小学数学问题。虽然我是一个老码农,但一直不赞成教小学生学编程,觉得这是揠苗助长,小学生不应该过早的固化逻辑思维而放松形象思维,某些少儿编程机构居然教学C++游戏编程,我觉得这真是在摧残祖国的花朵。现在孩子宅在家 ,想让他学点什么好几次冒出学编程的想法都被自己给否决了,直到我看到数学老师要求同学们整理小学阶段的数学公式、概念,我看到有一个小朋友居然画出了平面几何体的“继承”关系,让我眼前一亮:这种抽象关系如果用程序来表示不正合适吗?明白抽象方法了,那么学编程问题就不大了。于是我在想应该教孩子学什么语言比较好:LOGO、VB还是炙手可热的Python?虽然我非常熟悉C#,但需要了解许多背景知识,还需要安装一个很大的框架环境,显然C#不适合小学生学习,Java也是。LOGO是老牌的儿童编程语言了,操控一个小海龟来画图很形象,VB入门简单,但要一个小学生熟悉它的集成开发环境要求还是高了点,选Python无非就是因为AI应用火它就火,除此之外我找不出它适合儿童使用的理由。
用户1177503
2020/06/19
1.6K0
Scheme实现数字电路仿真(1)——组合电路
  EDA是个很大的话题,本系列只针对其中一小部分,数字电路的仿真,叙述一点概念性的东西,并不会过于深入,这方面的内容实则是无底洞。本系列并不是真的要做EDA,按照SICP里的相关内容,采用Lisp的方言Scheme。再者,Lisp并不是只有函数式一种编程范式,真正做EDA,仿真的核心部分为了运行效率可以采用C/C++编写,编程的思路也可以借鉴。
窗户
2019/12/16
1.1K0
Scheme实现数字电路仿真(1)——组合电路
Scheme来实现八皇后问题(2)
  上一章讲了用1~n的排序来表示n皇后的解,然后通过枚举1~n所有的排列、判定谓词过滤所有排列得到最终的所有解。
窗户
2018/10/25
7840
Scheme来实现八皇后问题(2)
日拱一卒,伯克利教你用Lisp写递归,写完后我感觉代码更溜了
我们继续伯克利CS61A公开课之旅,这一次是它的第九次实验课。昨天的期中测试过后,这门课关于Python的编程基础以及面向对象的部分就算是讲完了,接下来就到了Scheme和数据处理的部分。
TechFlow-承志
2022/09/21
7160
日拱一卒,伯克利教你用Lisp写递归,写完后我感觉代码更溜了
Scheme来实现八皇后问题(1)
  皇后是国际象棋里杀力最强的子,它可以吃掉同一条横线、竖线上其他棋子,也可以吃掉所在的两条斜线上的其他棋子(当然在角上只有一条斜线)。
窗户
2018/10/15
8310
符号求导,scheme实现
sicp练习2.57 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
byronhe
2021/06/25
4960
相互递归(3)
  我们根据上一章最开始的相互递归转一般递归的方法,结合Y Combinator,来对第一章的append实现做一下测试。
窗户
2019/06/05
4480
Scheme实现数字电路仿真(2)——原语
  上一章给出了组合电路的仿真实现,这一章开始思考时序电路的仿真实现。但时序电路远比组合电路复杂的多,我们先从组成电路的每个元件说起。在程序实现层次,我们可以考虑给每个基础元件一个自定义描述方式,称为原语。
窗户
2020/02/18
7590
Scheme实现数字电路仿真(2)——原语
Python装饰器的一点解读
理论上,函数是一等公民(first class function)的语言都可以使用函数式编程,从而利用算子(高阶函数)来做装饰器。
窗户
2020/06/03
4570
自然数到底可以表示到多大?
  小朋友都对巨大的数有一种天然的憧憬,以至于很多人都会想过这么一个问题,我们可以表示出多大的数?
窗户
2018/10/11
1.5K0
自然数到底可以表示到多大?
map的实现和柯里化(Currying)
  对于函数式编程来说,map/reduce/filter这几个算子非常重要,其中有的语言不是reduce而是fold,但功能基本一样,不过reduce的迭代一般只有一个方向,fold可能会分两个方向,这是题外话。
窗户
2019/09/29
9090
map的实现和柯里化(Currying)
相互递归(1)
  相互递归就是多个函数互相定义,最常见的就是两个函数,比如f和g,f的定义中用到g,而g的定义中用到f。
窗户
2019/05/25
6900
Extempore:实时系统的实时编程语言
介绍 Extempore 实时编程语言和环境,并详细探讨了使用 Extempore 演奏音乐的方法和技巧。
HaHack
2018/07/03
2.4K0
相关推荐
《SICP》读书笔记之一:构造过程抽象(上)
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验