dar*_*rch 37
这是SICP的基础课程之一,也是计算机科学最强大的思想之一.它的工作原理如下:
我们所谓的"代码"实际上并没有能力独自完成任何事情.代码仅在解释的上下文中定义程序 - 在该上下文之外,它只是一个字符流.(真的是一个比特流,它实际上是一个电脉冲流.但是让我们保持简单.)代码的含义由运行它的系统定义 - 而且这个系统只是将你的代码视为告诉的数据它是你想要做的.C源代码由C编译器解释为描述您希望它创建的目标文件的数据.加载器将目标文件视为描述您要排队等待执行的某些机器指令的数据.机器指令由CPU解释为定义它应该经历的状态转换序列的数据.
解释语言通常包含将数据视为代码的机制,这意味着您可以以某种形式将代码传递到函数中然后执行它 - 甚至在运行时生成代码:
#!/usr/bin/perl
# Note that the above line explicitly defines the interpretive context for the
# rest of this file. Without the context of a Perl interpreter, this script
# doesn't do anything.
sub foo {
my ($expression) = @_;
# $expression is just a string that happens to be valid Perl
print "$expression = " . eval("$expression") . "\n";
}
foo("1 + 1 + 2 + 3 + 5 + 8"); # sum of first six Fibonacci numbers
foo(join(' + ', map { $_ * $_ } (1..10))); # sum of first ten squares
Run Code Online (Sandbox Code Playgroud)
像scheme这样的一些语言有一个"一流函数"的概念,这意味着你可以将一个函数视为数据并传递给它而不进行评估,直到你真正想要它为止.
结果是"代码"和"数据"之间的划分非常随意,只是透视的功能.抽象级别越低,代码必须"更智能":它必须包含有关应如何执行的更多信息.另一方面,解释器提供的信息越多,代码就越愚蠢,直到它开始看起来像没有智能的数据.
编写代码的最强大的方法之一是简单描述您需要的内容:数据将转换为代码,描述如何通过解释上下文获取您所需的内容.我们称之为"声明性编程".
有关具体示例,请考虑HTML.HTML没有描述图灵完整的编程语言.它只是结构化数据.它的结构包含一些智能,可以控制其解释上下文的行为 - 但不是很多智能.另一方面,它包含比普通网页上出现的文本段落更多的智能:这些都是非常愚蠢的数据.
在安全性的上下文中:由于缓冲区溢出,您认为数据因此无害(例如图像)可以作为代码执行并且可以将您的机器执行.
在软件开发的背景下:许多开发人员非常害怕"硬编码"事情,并且非常热衷于提取可能必须更改为配置文件的参数.这通常基于这样的想法:配置文件只是"数据",因此可以轻松地更改(客户满意),而不会引起更改代码中任何内容的问题(编译,部署,测试).
这些开发人员没有意识到的是,由于这个"数据"会影响程序的行为,它实际上就是代码; 它可能会破坏程序,并且在这样的更改之后不需要完整测试的唯一原因是,如果正确完成,可配置值具有非常具体的,记录良好的效果,并且任何无效值或损坏的文件结构都将被捕获该程序.
然而,经常发生的事情是配置文件结构本身就变成了一种编程语言,完成了控制流和所有内容 - 一个记录错误,具有奇特的语法和解析器,并且只有团队中经验最丰富的开发人员可以触摸而不会完全破坏应用程序.