PL真有意思(四):控制流

对大多数计算模型而言,顺序都是基本的东西,它确定了为完成所期望的某种工作,什么事情应该最先做,什么事应该随后做,我们可以将语言规定顺序的机制分为几个类别:

顺序执行

选择

迭代

过程抽象

递归

并发

异常处理和推断

非确定性

对于不同类别的语言对不同类别的控制流的重要性也不尽相同,比如顺序执行相比于函数式对于命令式则更加重要。而命令式中更倾向用迭代,函数则更强调递归

表达式求值

在讨论控制流之前先讨论下表达式的问题,先明确两个概念:运算符通常是指那些采用特殊语法形式的内部函数(比如+-*/等),运算对象指的是运算符的参数(如2+3,2和3就是运算对象),那么运算符和运算对象的组合就是表达式。一般根据运算符出现的位置(相对于运算对象而言),可以分为3类表示形式:前缀、中缀和后缀。比如Lisp就运用前缀语法:

(+ 1 3 4 6) (* (+ 1 7) 8)

大多数命令式语言对二元运算符都使用中缀记法,而对一元运算符和其它函数使用前缀激发。但是像Lisp就全部统一使用中缀记法

优先级和结合性

大多数程序设计语言都提供丰富的内部算术。在用中缀方式(没有括号)写出就可能出现歧义。所以就需要优先级和结合性来解决歧义性,但是我觉得

妈的你写括号就完事儿了

而且不同语言的优先级和结合性也不尽相同

赋值

在纯函数式语言中,程序的基本组成部分是表达式,计算也仅是对表达式求值。任何一个表达式对于整个计算的影响也仅限于这个表达式所处的上下文环境。

而命令式语言的情况与此截然不同,计算通常是通过对内存中变量值的一系列修改操作来完成,赋值就是这种修改的最基本手段。每一次赋值都表示一个值被放入一个对应的变量中。

一般来说,如果语言中的一个结构除了返回一个值供其外围环境所使用,还能以其他方式影响后续计算(并最终影响程序输出),那么我们就说这种结构有副作用。而副作用也是命令式语言里最核心的部分

而在纯函数语言中没有任何的副作用,表达式的值只依赖于输入

但是现在许多语言都是混合的,像Python和Ruby主要是命令式的,但是也提供了很多的函数式的特征,现在连Java都提供了对函数式的支持

引用和值

考虑一下下面的C语言的赋值:

d = a; a = b + c;

第一个语句中,赋值语句右部引用了a的值,并希望把这个值放入d。第二个语句左部引用了a的位置,希望把b+c的结果放进去。这两种解释(值和位置)都是可行的,因为c语言中变量就是能保存值的命名容器,所以我们会说类似的语言的变量是值模型。由于指示位置的表达式被放在赋值语句的左部,所以这种指示位置的表达式成为左值表达式。表示一个值的表达式称为右值。在变量的值模型下,同一表达式也可能是左值或者右值,比如(a=a+1),左部的a是左值,用于表示存放结果的位置;右部的a是右值,用于代表a具体所指的值。

在采用了变量的引用模型的语言中,这种左值和右值的差异就更加明显了。

b = 2; c = b; a = b + c;

在值模型语言中程序员会说:“把2放入b,然后复制到c,然后用它们两个的值相加,把结果4放入a。”。;

在引用模型语言中的程序员会说:“让b引用2,让c也引用2,然后把这两个引用送给+运算,并让a引用算出的结果,也是4“。

而在Java中,对于内部类型使用值模型,而类使用引用模型

装箱

对于内部类型使用值模型,就无法以统一的方式将它们传给要求类类型的参数的方法,所以这里就需要一个装箱过程

比如Java提供的Integer类

Integer i = new Integer(12); 多路赋值

我们知道赋值操作有右结合性,这使得我们可以写出a=b=c的简练代码,在一些语言中(Ruby,Go,Python)我们可以进一步这样写:

a, b = 1, 2; //上面的语句结果就是a等于1,b等于2。 a, b = b, a; //交换两个值,如果没有这种语言特性,那么就需要引入临时变量了。 a, b , c = funx(d, e, f);

这种记法也消除了大多数程序设计语言中函数的非对称性,这些语言可以允许任意多个参数,但只能返回一个返回值。但是其实在Python中的返回多个值,就是将多个值封装为元组,在赋值的时候又拆箱而已

初始化

并不是所有语言都提供声明变量时指定初始值的方式,但是至少有这几点可以证明提供初始值的机制是有益的

局部静态变量需要一个初始值才能使用

使用静态分配的变量,可以由编译器放入全局内存,避免了在运行时赋予吃数值所造成的开销

可以避免意外的使用未初始的变量

如果声明时没有明确的给定变量的初始值,语言也可以给定一个默认值。像C、Java和C#也都提供了类似的机制

动态检查

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfgwf.html