“数据只是愚蠢的代码,代码只是智能数据”是什么意思? 意思是?

发布于 2024-07-19 07:13:23 字数 1459 浏览 7 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夏の忆 2024-07-26 07:13:24

这是 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

某些语言(例如 schema)具有“一流函数”的概念”,这意味着您可以将函数视为数据并将其传递,而不需要对其进行评估,直到您确实需要为止。

结果是“代码”和“数据”之间的划分几乎是任意的,只是视角的函数。 抽象级别越低,代码就必须越“智能”:它必须包含有关如何执行的更多信息。 另一方面,解释器提供的信息越多,代码就越愚蠢,直到它开始看起来像完全没有智能的数据。

编写代码最强大的方法之一是对您需要的内容进行简单描述:数据将转换为代码,描述如何通过解释上下文获取您需要的内容。 我们称之为“声明式编程”

举一个具体的例子,考虑 HTML。 HTML 没有描述图灵完备的编程语言。 它只是结构化数据。 它的结构包含一些智能,可以让它控制其解释上下文的行为——但不是很多智能。 另一方面,它比普通网页上出现的文本段落包含更多的智慧:这些都是非常愚蠢的数据。

This is one of the fundamental lessons of SICP and one of the most powerful ideas of computer science. It works like this:

What we think of as "code" doesn't actually have the power to do anything by itself. Code defines a program only within a context of interpretation -- outside of that context, it is just a stream of characters. (Really a stream of bits, which is really a stream of electrical impulses. But let's keep it simple.) The meaning of code is defined by the system within which you run it -- and this system just treats your code as data that tells it what you wanted to do. C source code is interpreted by a C compiler as data describing an object file you want it to create. An object file is treated by the loader as data describing some machine instructions you want to queue up for execution. Machine instructions are interpreted by the CPU as data defining the sequence of state transitions it should undergo.

Interpreted languages often contain mechanisms for treating data as code, which means you can pass code into a function in some form and then execute it -- or even generate code at run time:

#!/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

Some languages like scheme have a concept of "first-class functions", which means that you can treat a function as data and pass it around without evaluating it until you really want to.

The upshot is that the division between "code" and "data" is pretty much arbitrary, a function of perspective only. The lower the level of abstraction, the "smarter" the code has to be: it has to contain more information about how it should be executed. On the other hand, the more information the interpreter supplies, the more dumb the code can be, until it starts to look like data with no smarts at all.

One of the most powerful ways to write code is as a simple description of what you need: Data which will be turned into code describing how to get you what you need by the interpretive context. We call this "declarative programming".

For a concrete example, consider HTML. HTML does not describe a Turing-complete programming language. It is merely structured data. Its structure contains some smarts that let it control the behavior of its interpretive context -- but not a lot of smarts. On the other hand, it contains more smarts than the paragraphs of text that appear on an average web page: Those are pretty dumb data.

蹲墙角沉默 2024-07-26 07:13:24

在安全方面:由于缓冲区溢出,您认为是数据且无害的内容(例如图像)可以作为代码执行并破坏您的计算机。

在软件开发的背景下:许多开发人员非常害怕“硬编码”事物,并且非常热衷于提取可能需要更改为配置文件的参数。 这通常基于这样的想法:配置文件只是“数据”,因此可以轻松更改(可能由客户更改),而不会引发更改代码中的任何内容所带来的问题(编译、部署、测试)。

这些开发人员没有意识到,由于这些“数据”影响程序的行为,所以它确实是代码; 它可能会破坏程序,并且在进行此类更改后不需要进行完整测试的唯一原因是,如果正确完成,可配置值具有非常具体的、有据可查的效果,并且任何无效值或损坏的文件结构都将被捕获该程序。

然而,经常发生的情况是,配置文件结构本身就变成了一种编程语言,包含控制流和所有内容 - 这种语言的文档记录很差,语法和解析器很奇怪,而且只有团队中最有经验的开发人员才能使用它可以触摸而不完全破坏应用程序。

In the context of security: Due to buffer overflows, what you thought of as data and thus harmless (such as an image) can become executed as code and p0wn your machine.

In the context of software development: Many developers are very afraid of "hardcoding" things and very keen on extracting parameters that might have to change into configuration files. This is often based on the idea that config files are just "data" and thus can be changed easily (perhapy by customers) without raising the issues (compilation, deployment, testing) that changing anything in the code would.

What these developers don't realize is that since this "data" influences the behaviour of the program, it really is code; it could break the program and the only reason not to require complete testing after such a change is that, if done correctly, the configurable values have a very specific, well-documented effect and any invalid value or a broken file structure will be caught by the program.

However, what all too often happens is that the config file structure becomes a programming language in its own right, complete with control flow and everything - one that's badly documented, has a quirky syntax and parser and which only the most experienced developers in the team can touch without breaking the application completely.

み格子的夏天 2024-07-26 07:13:24

因此,在像Scheme这样的语言中,甚至代码也被视为一流数据。 您可以像对待其他代码一样对待函数和 lambda 表达式,例如将它们传递到其他函数和 lambda 表达式中。 我建议继续阅读正文,因为这一切都会变得非常清楚。

So, in a language like Scheme, even code is treated as first class data. You can treat functions and lambda expressions much like you treat other code, say passing them into other functions and lambda expressions. I recommend continuing with the text as this will all become quite clear.

薄荷梦 2024-07-26 07:13:24

这是你应该通过在编译器中编写来理解的。

编译器的一个常见步骤是将程序转换为抽象语法树。 表示通常就像树,例如 [+, 2, 3],其中 + 是根,2、3 是子节点。

Lisp 语言只是将其视为其数据。 因此数据和代码之间没有分离,它们都是看起来像 AST 树的列表。

This is something you should come to understand from writing in a compiler.

One common step in compilers is to transform the program into an abstract syntax tree. Representation will often be like trees such as [+, 2, 3] where + is the root, and 2, 3 are the children.

Lisp languages simply treats this as its data. So there is no separation between data and code which are both lists that look like AST trees.

素罗衫 2024-07-26 07:13:24

代码肯定是数据,但数据绝对并不总是代码。 让我们举一个基本的例子——客户名称。 它与代码无关,它是应用程序的功能(必需)方面,而不是技术(偶然)方面。

您可能会说任何技术/偶然数据都是代码,而功能/基本数据则不是。

Code is definitely data, but data is definitely not always code. Let's take a basic example - customer name. It's nothing to do with code, it's a functional (essential), as opposed to a technical (accidental) aspect of an application.

You could probably say that any technical/accidental data is code and that functional/essential data is not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文