Lisp-1 vs Lisp-2[1]

Scheme的求值模型非常简单:只是用一个名字空间,所有表达式中相应位置的值应该是明确的。

Common Lisp和Scheme最大的不同是,函数名字空间和数据的名字空间是分离的。操作函数名字空间的语句包括,defunfletlabelsdefmethoddefgeneric等方法。要用函数名作为另一个函数的参数来传递函数时,需要使用function特殊操作符或者使用#'

我们称Scheme的变量模型为Lisp-1,Common Lisp的变量模型是Lisp-2.

绑定

在编程语言中绑定是变量名(变量标识符)和对象(保存于内存中的存储单元,数据或代码)的映射关系。在这个绑定过程中是作用域有密不可分的关系,作用域决定了哪个变量绑定了哪个存储单元。

为变量建立绑定之后,就可以通过变量名来引用其所绑定的值。绑定的具体含义,可以参考下图

词法作用域(lexical scoping)

词法作用域又叫静态作用域(static scope)。顾名思义,词法变量即是使用词法作用域的变量。在词法作用域里,一个变量的变量名只能在一个函数或一段代码区域( block )内存在,此时变量名才会绑定到变量的值。

词法变量拥有不确定的生存期,即从时间上来讲,一个词法变量可以在任意的时间里持续存在,取决于该变量需要被使用(reference)多久。 词法作用域里,对于函数体中的一个符号,不会逐层检查函数的调用链,而是检查函数定义时的外部环境,即捕捉的是函数定义时该符号的绑定。

动态作用域(dynamic scoping)

使用动态作用域的变量叫做动态(dynamic)变量,有时也叫做特殊(special)变量。动态作用域里,每个变量名(变量标识符)都拥有一个全局的绑定栈。引入一个与动态变量同名的局部变量会为此变量名创建一个新的变量绑定并将其压入此变量名的全局绑定栈中,一个全局的变量名(变量标识符)总是引用当前其栈顶的绑定,当使用该变量绑定的代码执行完毕(即程序控制流离开了此变量的作用域),该变量绑定就会从此变量名的全局绑定栈中被弹出,该变量绑定就失效。

动态作用域表示的范围是不确定的,可从任何位置访问一个动态变量,取决于它们在什么地方被绑定。动态变量拥有动态的生存期。因容易引起误会而需要注意的是,不确定的作用域和动态生存期的组合经常被错误地称为动态作用域(dynamic scope)。

动态作用域里,函数执行遇到一个符号,会由内向外逐层检查函数的调用链,并打印第一次遇到的那个绑定的值。最外层的绑定即是全局状态下的那个值。

Common Lisp的例子

请看下面的代码

(let ((y 7))(defun foo (x)(print x)(print y)))(let ((y 5))(foo 1))

我们通过SLIM执行后,可以得到输出1和7,这说明Common Lisp使用的是词法作用域。在foo中寻找y的绑定时,它检查函数foo的词法上下文。

再请看下面代码

(let ((y 7))(defun foo (x)(print x)(print y)(setq y (+ y 2))))(let ((y 5))(foo 1)(foo 1))(let ((y 5))(foo 2))

我们通过SLIM执行后,我们会看到,1,7,1,9,2和11。在例子中的第一个let表里,定义了一个变量,符号名为y并绑定了值7,那么这个y的作用域就是这个let表区域。 foo函数定义在这个区域内,其内部会使用到一个符号名为y的变量。 那么在词法作用域的情况下,当foo被调用时,其会查找其定义的环境有没有符号名y的变量可以绑定,如果有则把foo中符号y的值绑定,在这里就是7。 并且这里foo中的y和外部let中的y共享一个值,都是对这个值的引用,并不是拷贝了一个新值。

参考

  1. ^https://en.wikipedia.org/wiki/Common_Lisp#The_function_namespace

引入静态变量_Common Lisp变量的一些事情相关推荐

  1. 堆栈,静态变量和普通变量,静态函数和普通函数的区别

    首先简单介绍一下堆和栈的区别. 1.内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1).栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似 ...

  2. Linux 下的动态库、静态库与环境变量

    最近这几天在处理集群软件的过程中,遇到各种各样的库和环境变量的问题,被虐的不清!趁此机会,整理了一下 Linux 下静态库.动态库(共享库)和环境变量的一些知识,与大家共享一下. 库的种类 Linux ...

  3. 静态变量与实例变量的区别

    静态变量也叫类变量,这种变量前加了static修饰符.可以直接用类名调用,也可以用对象调用,而且所有对象的同一个类变量 都是共享同一块内存空间. 实例变量也叫对象变量,这种变量没有加static修饰符 ...

  4. 面向对象(静态变量和成员变量的区别)

    静态变量叫类变量,成员变量叫对象变量 所属不同 静态变量属于类,所以也称为类变量 成员变量属于对象,所以也称为实例变量(对象变量) 内存中位置不同 静态变量存储于方法区的静态区 成员变量存储于堆内存 ...

  5. 全局变量、成员变量、类变量、静态变量、实例变量、局部变量的定义与区别

    全局变量 全局变量又叫成员变量,它是声明在类里,函数,静态语句块外的变量,全局变量又分为类变量(静态变量).实例变量两种. 通过代码来看一下: private int i;//实例变量 private ...

  6. 静态变量和实例变量的区别

    ①在语法定义上的区别:静态变量前要加static关键字,而实例变量(成员变量)不需要. ②在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个 ...

  7. 常见Java面试题之静态变量和实例变量的区别

    静态变量和实例变量的区别有哪些? 静态变量和实例变量可能大多数同学用的比较多,但是相关阐述并不是很常见,尤其对新手同学可以不能清楚表达. 静态变量和实例变量也是最经常遇到的一个基础java面试题,不管 ...

  8. java线程安全问题之静态变量、实例变量、局部变量

    转载 java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定 ...

  9. c++ 静态变量赋值_Python变量及常量解释说明

    变量 (1)在计算机程序中,变量不仅可以是数字,还可以是任意数据类型, 变量子啊程序中就是一个变量名表示的,变量名必须是大小写英文,数字,和"_"的组合,切不能以数字开头. a = ...

最新文章

  1. 广告行业中常说的 CPC,CPM,CPD,CPT,CPA,CPS 等词的意思是什么?
  2. Oracle undo表空间爆满的解决
  3. 目前微服务/REST的最佳技术栈
  4. plupload上传插件绑定事件的两种方法
  5. java中文乱码解决方案
  6. Hadoop 07_MapReduce运行的三种方式
  7. leetcode--116. 填充每个节点的下一个右侧节点指针
  8. Mysql命令行修改字段类型
  9. JAVA进阶教学之(Enum枚举类)
  10. 使用HttpsUrlConnedtion连接https地址时异常处理 (方式二)
  11. Spring Boot学习笔记:Spring Boot的Web功能
  12. git的简单使用(windows)
  13. 计算机考试试题大一上学期,大一第一学期期末考试计算机试题1
  14. 关于交换的知识点(一)
  15. php文字滚动特效,js文字横向滚动特效_javascript技巧
  16. Android有效解决加载大图片内存溢出问题及优化虚拟机内存
  17. ELGamal 加密算法及Java实现
  18. Arduino 中断程序运行及注意事项
  19. 步进电机低频震动问题
  20. HTML5实现立方体及透视效果

热门文章

  1. 没数据时y轴不显示_Matplotlib数据可视化
  2. Java实现多线程售票
  3. mysql key_len_浅谈mysql explain中key_len的计算方法
  4. PyTorch C++ API libtorch 简介
  5. Java统计做题正确率_ResNet:训练期间的准确率为100%,但使用相同数据的预测准确率为33%...
  6. Linux下导出MySQL为SQL文件_在linux命令下导出导入.sql文件的方法
  7. win7变成xp风格了怎么改回_微软看了会沉默,把 Windows 10 变成经典 98 风格
  8. base64 能放数组里面么_数组:总结篇
  9. docker搭建ldap
  10. 缓存雪崩、击穿、穿透解决方案