[SICP]第一章构造过程抽象( 综述)

本文重新组织了《SICP》中关于函数抽象的知识,涵盖计算过程、函数、流程结构、接口与实现分离以及高阶函数的概念。强调函数式编程中函数作为数据的特性,讨论了Scheme语言的表达式、组合与抽象手段,并探讨了递归、迭代、顺序结构以及接口设计在 Scheme 中的实现。
摘要由CSDN通过智能技术生成

功能抽象是对可执行代码的抽象

《SICP·第一章构造过程抽象》,看得我有些凌乱。这里重新组织一下Scheme功能抽象部分的知识。

行为抽象/功能抽象是对(从指令、操作符发展到)可执行代码的抽象。从C/C++/Java这条语言线看,按照行为抽象的逻辑发展[1],其包含:

  • 表达式
  • 3种流程结构
  • 函数/子程序和结构化分解
  • 接口与实现相分离原则
  • 抽象方法——函数抽象的最高形式。
  • 设计通用性的函数[2]

那么,Scheme如何进行功能抽象,以及它有什么特色呢?

从Scheme等函数式语言看,按照行为抽象/功能抽象的逻辑发展,它也包括三种流程结构、函数和结构化分解;但是动态类型语言天然地不遵循接口与实现相分离原则(因此也没有抽象函数),而在设计通用性的函数上,其高阶函数概念大放异彩。

 


[1]参考《编程导论(Java)·第三章功能抽象》

[2]在函数级别,行为抽象中还有一个十分重要内容:设计通用性的方法,请参考[2.2.1求和函数]。

 


 

1.computational process(计算过程)与procedure(函数)

本章的开场白,第一句话我就不喜欢。yqj2065没有搞懂它的第一个术语computational process是什么意思。

We are about to study the idea of a computational process. Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes. 

‘[注:processes、procedures加上日常生活中常用的processes,看翻译版的时候,会看得头晕。所以yqj2065将procedures全部译为函数。对于子程序,在命令式编程的C语言中称为函数,而函数式编程的Scheme中偏偏称为procedures。]

1.2  Procedures and the Processes They Generate

或许这是Processes 的含义最接近清晰的地方。A procedure is a pattern for the local evolution of a computational process.

]

为什么选Lisp?...这些特征中最显著的一点是,对processes的Lisp描述(称为procedures/函数,能够作为Lisp数据来表示和操作。对于填平数据与函数的传统划分,方式为函数视为数据——函数是头等公民、高阶函数。

2.表达式和3种结构

Every powerful language has three mechanisms  for :

•primitive expressions, 基本表达形式【这里不仅说 表达式,也包含基本函数】,语言设计者关心的要素,程序员只是被动地知道它们。如原子/基本类型、特殊块(特殊形式)define、if,基本操作符等。
•means of combination, 组合的手段。表达式定义中,组合表达式是基本要求。函数的组合则是函数式编程语言最典型的特征。数据类型的合成,也是编程语言的一个较重要的部分,只不过程序员自定义类型在C、Java中不那么引人注目。
•means of abstraction, 抽象的手段(命名与封装)给组合实体一个名字并作为操作的单元。这里,我们可以给常量、组合表达式、函数命名。

1.块(form)

Scheme中文字是基本表达式(primitive expression),而块(form)是基本程序单元,form 都由小括号括起来,如(+ 1 2)。一个Scheme语言程序是由一个或多个form构成。

1.1.1 用括号限定的一个表达式列表,用于表示函数应用的这些表达式,称为组合式。列表最左的那个元素称为操作符,其他为操作数——实参。

1.1.2

变量:using names to refer to computational objects。

Define 是该语言最简单的抽象手段。

用变量逐一为更复杂的表达式命名?a Lisp program usually consists of a large number of relatively simple procedures.【这句话容易导致误解。难怪有人说函数式编程是“自低而上”,从目前的最简单的例子出发,可以看到由简单的函数逐步构造出复杂的函数。另一方面,一个复杂的函数,需要分解为多个小函数,即功能分解——一个程序也是由简单的函数构成。函数式编程仍然可以结构化编程】

1.1.4 函数抽象(定义函数)

1.1.6 介绍分支结构

1.2 介绍递归Vs.迭代。这一节看得令我不爽。在解释器的尾调用优化 tail-call optimization (TCO)的支持下,一般递归和尾递归有了两种执行的方式。明明白白地写出来解释器的支持,很好理解。

3.1.1 介绍顺序结构begin。由于顺序结构必然产生副作用(除了最后的表达式作为整个form的值,其他的表达式就是用于产生副作用的),放在前面介绍一下也可以。

命令式编程Vs.函数式编程,从程序结构上看(表面上看),前者为顺序结构,后者为(solving <param list>).

3.函数抽象

由于函数抽象在define后介绍[1.1.4],而[1.3.2Constructing Procedures Using Lambda]中写“it seems terribly awkward to have to define trivial procedures”真是像讲故事。lambda作为匿名函数与命名函数各有用处。

4.接口与实现相分离

[1.1.8 Procedures as Black-Box Abstractions]介绍了这方面的内容。主要是Scheme在此没有太多手段,方法的形参是局部变量/约束变量也讲了1/3的篇幅;于是,define内部define既是隐藏helper函数的手段又是解决命名空间的手段。

5.高阶函数

[1.3  Formulating Abstractions with Higher-Order Procedures]是重点和Scheme的主场。功能抽象的一个重要方面:由函数到一般性函数。在Java中通常使用模板方法模式完成,(Java 8后,如果将它添加到功能抽象中加以讲解呢?)

 

其他:求值顺序

 


 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值