PL真有意思(八):其它程序设计模型
前言
在之前几篇我们讨论的语法、语义、命名、类型和抽象适用于所有语言。然而我们的注意力都主要集中在命令式语言上,现在这篇来看看其它范式的语言。函数式和逻辑式语言是最主要的非命令式语言。
函数式语言
命名和作用域问题出现在各种模型中,还有类型、表达式和选择与递归等控制流概念等等。所有语言都必须经过扫描、语法分析和语义分析,
函数式程序设计的概念
函数式程序设计将一个程序的输出定义为其输入的一个数学函数,在其中没有内部状态的概念,因此也没有副作用。函数式提供了一下特征,其中许多都是命令式语言中没有的:
- 第一级的值和高阶函数
- 广泛的多态性
- 表类型和表操作
- 结构性的函数返回
- 结构性的对象的构造函数
- 废料收集
Scheme
我们以Scheme为例子,来看一下概念
约束
(let ((a 3)
(b 4)
(square (lambda (x) (* x x)))
(plus +))
(sqrt (plus (square a) (square b))))
特殊型let有两个或者多个参数,其中第一个参数是一些二元组的表,每个二元组的表,每个二元组中的第一个元素是名字,第二元素就是这个名字在let的第二个参数中代表的值。其余参数将按顺序求值,对于整个结构的求值将是最终参数的值
控制流和赋值
(cond
((< 3 2) 1)
((< 4 3) 2)
(else 3))
cond的参数是一些二元组,它们将被从头到尾按顺序考虑。如果第一个二元组的第一个元素求值得到#t,那么整个表达式的值就是这个二元组的第二个元素的值
求值顺序
在之前的几篇已经提到了两种求职方式:应用序求值和正则序求值。和大多数命令式语言一样,Scheme在大多数情况下都是用应用序求值。
严格求值和惰性求值
如果一个无副作用的函数在其任何一个参数是未定义的情况下也是未定义的,我们就称它为严格。这种函数可以安全的对所有参数求值,所以其结果也将不依赖于求值顺序。
惰性求值使我们可以得到正则序求值的优势,回忆一下我们之前说的,惰性求值对实现无穷数据结构非常有用
高阶函数
如果一个函数以函数作为实际参数,或者返回函数作为值,那么它就是一个高阶函数。
比如Scheme的map函数
(map * '(2 4 6) '(3 5 7)) => (6 20 42)
map将对这些表中的一组元素调用相应的函数
高阶函数主要的作用就是从现有的函数出发构造新函数
(define total (lambda (l) (fold + 0 1)))
(total '(1 2 3 4 5))
(define total-all (lambda (l)
(map tatal l)))
(total-all '((1 2 3 4 5)
(2 4 6 8 10)
(3 6 9 12 15)))
Curry化
柯里化是一个常见的操作,是用一个单参数函数取代一个多参数的函数,这个单参数函数返回一个函数
(define curried-plus (lambda (a) (lambda (b) (+ a b))))
((curried-plus 3) 4)
(define plus-3 (curried-plus 3))
(plus-3 4)
除了其它用途之外,这种curry操作还使我们能够给高阶函数传递一个部分求值函数
(map (curried-plus 3) '(1 2 3)) => (4 5 6)
函数式小结
无副作用的程序设计是一种非常诱人的想法,从前面的几篇可以看出,副作用可能使程序难以阅读和编译。
不过,存在着许多常用的程序设计惯用形式,最正宗的副作用在其中扮演着核心角色。
我们关注计算的函数式模型。命令式程序的计算主要是通过迭代和副作用,而函数式程序的计算主要是通过将参数代换到函数中。
函数式语言的相应模型是lambda演算,许多函数式语言倾向于在lambda演算的基础上扩充一些特征,包括赋值、I/O和迭代。
并发模型
如果一个程序包含了多余一个活动的执行上下文。即多余一个控制线程,则称该程序是并发的。并发的出现至少有三方面的重要原因:
- 为了反映一些问题的逻辑结构。许多程序,必须同时维护一批在同一时间基本相互独立的作业的轨迹
- 利用额外的处理器以提高速度
- 为了应对相互独立的多台物理设备
并发程序设计基础
在一个并发程序中,我们将使用术语线程来指代那些程序员认为与其他线程并发的运行的活动实体。在大多数系统中,给定程序的线程是在操作系统所提供的一个或多个进程的顶部实现的。
/*
通信和同步
在任何并发的程序设计模型中,需要处理的两个最关键的问题就是通信的同步。通信指线程可用于获得其它线程产生的信息的各种机制。
同步
*/
写到一般发现很像之前操作系统写到的进程管理,就不再重复了。放个链接
总结
这一篇就稍微提了一下除了命令式语言之外的其它范式,还有像现在语言支持的并发模型。但是之前讨论的语法、语义、命名、类型和抽象适用于所有语言
PL真有意思(八):其它程序设计模型的更多相关文章
- PL真有意思(二):程序设计语言语法
前言 虽然标题是程序语言的语法,但是讲的是对词法和语法的解析,其实关于这个前面那个写编译器系列的描述会更清楚,有关语言语法的部分应该是穿插在整个设计当中的,也看语言设计者的心情了 和英语汉语这些自然语 ...
- PL真有意思(四):控制流
前言 对大多数计算模型而言,顺序都是基本的东西,它确定了为完成所期望的某种工作,什么事情应该最先做,什么事应该随后做,我们可以将语言规定顺序的机制分为几个类别: 顺序执行 选择 迭代 过程抽象 递归 ...
- PL真有意思(一):引言
前言 断断续续学编译原理到之前发过写一个编译器和正则表达式引擎系列文章也有一段时间了,然后最近看完PLP这本书,这本书应该算是入门书,但是对我这种半吊子收获很大.所以为了弥补最近学操作系统和接外包摸的 ...
- PL真有意思(五):数据类型
前言 现在大多数程序设计语言中都有表达式和/或对象的类型概念.类型起着两种主要作用: 为许多操作提供了隐含的上下文信息,使程序员可以在许多情况下不必显示的描述这种上下文.比如int类型的两个对象相加就 ...
- PL真有意思(六):子程序和控制抽象
前言 在之前我们把抽象定义为一种过程,程序员可以通过它将一个名字与一段可能很复杂的程序片段关联起来.抽象最大的意义就在于,我们可以从功能和用途的角度来考虑它,而不是实现. 在大多数程序设计语言中,子程 ...
- PL真有意思(七):数据抽象和面向对象
前言 在之前的名字.作用域那篇提到模块类型,它使程序员可以从一个给定抽象出发,通过实例化产生多个实例:再后面是类,它使程序员可以定义一族相关的抽象. 在这一篇里,我们会来看一下面向对象程序设计及其三个 ...
- PL真有意思(三):名字、作用域和约束
前言 这两篇写了词法分析和语法分析,比较偏向实践.这一篇来看一下语言设计里一个比较重要的部分:名字.在大部分语言里,名字就是标识符,如果从抽象层面来看名字就是对更低一级的内存之类的概念的一层抽象.但是 ...
- C++对象模型笔记之程序设计模型
C++程序设计模型支持三种程序设计模型 1.程序模型(procedural model) 可以理解为过程化模型,就像C一样 2.抽象数据类型模型(ADT) 数据结构教材里有说过,查了下资料也不是很明确 ...
- CUDA C++程序设计模型
CUDA C++程序设计模型 本章介绍了CUDA编程模型背后的主要概念,概述了它们在C++中的暴露方式.在编程接口中给出了CUDA C++的广泛描述. 使用的矢量加法示例的完整代码可以在矢量加法CUD ...
随机推荐
- redis入门(二)
目录 redis入门(二) 前言 持久化 RDB AOF 持久化文件加载 高可用 哨兵 流程 安装部署 配置技巧 集群 原理 集群搭建 参考文档 redis入门(二) 前言 在redis入门(一)简单 ...
- python中的可变数据类型和不可变数据类型
1.不可变数据类型:数值.字符串.元组 不允许变量的值发生变化,如果变量的值变化了,那么就是新建了一个对象:对于相同值的对象,在内存中只有一个对象. 2.可变数据类型:列表.字典 允许变量的值发生变化 ...
- django-Views之常见的几种错误视图代码(三)
1.404 page not found(找不到对应的页面) 2.500 server error(服务器错误) 3.400 bad request(无效的请求) 4.403 HTTP forbidd ...
- zabbix清理监控历史mysql数据
问题描述: 今天同事说有个zabbix监控数据库历史数据越来越多了, 让我帮忙清一下,顺便熟悉练练手,做个笔记 zabbix监控运行一段时间以后,会留下大量的历史监控数据 zabbix数据库一直在增大 ...
- Application,Session,Cookie,ViewState,Cache对象用法、作用域的区别
1.Application:用于保存所有用户共用的数据信息.在Asp.Net中类似的配置数据最好保存在Web.config文件中.如果使用Application对象,一个需要考虑的问题是任何写操作都要 ...
- Security整合spring boot
Security整合spring boot 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spri ...
- Linux中的快捷方式
history 显示命令历史列表 ↑(Ctrl+p) 显示上一条命令 ↓(Ctrl+n) 显示下一条命令 !num 执行命令历史列表的第num条命令 !! 执行上一条命令 !?string? 执行含有 ...
- golang 包依赖管理 godep 使用
介绍: godep是解决包依赖的管理工具,目前最主流的一种,原理是扫描记录版本控制的信息,并在go命令前加壳来做到依赖管理. 1.安装: go get github.com/tools/godep 2 ...
- K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法
1. 基于实例的学习算法 0x1:数据挖掘的一些相关知识脉络 本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科. 其实人类的科学技术发展的历史,就一直伴随 ...
- [考试反思]0810NOIP模拟测试16:黎明
好吧,你尽力啦.我不说什么啦 []200 []180 [6]170 [7]160 [11]150 [12]140 还好,和前面的差距不大.虽说没有原来最好的那段时间考得那么好,但貌似还可以接受. 这次 ...