我一直在网上搜索声明式编程和命令式编程的定义,希望能给我一些启发。然而,我发现在一些资源中使用的语言令人生畏——例如在维基百科。 有没有人可以给我举一个现实世界的例子,让我对这个主题有一些了解(也许是c#)?


当前回答

声明性编程是你说你想要什么,命令式编程是你说如何得到你想要的。

一个简单的Python例子:

# Declarative
small_nums = [x for x in range(20) if x < 5]

# Imperative
small_nums = []
for i in range(20):
    if i < 5:
        small_nums.append(i)

第一个例子是声明性的,因为我们没有指定构建列表的任何“实现细节”。

以c#为例,一般来说,使用LINQ的结果是声明式的,因为你没有说如何获得你想要的东西;你只是在说你想说的话。你可以对SQL说同样的话。

声明式编程的一个好处是,它允许编译器做出可能比手工编写更好的代码的决定。运行SQL示例,如果您有这样的查询

SELECT score FROM games WHERE id < 100;

SQL“编译器”可以“优化”这个查询,因为它知道id是一个索引字段——或者它可能没有索引,在这种情况下,它必须遍历整个数据集。或者SQL引擎知道这是利用所有8个核心进行快速并行搜索的最佳时机。作为程序员,你不需要考虑这些条件,也不需要编写代码来处理任何特殊情况。

其他回答

声明性编程是你说你想要什么,命令式编程是你说如何得到你想要的。

一个简单的Python例子:

# Declarative
small_nums = [x for x in range(20) if x < 5]

# Imperative
small_nums = []
for i in range(20):
    if i < 5:
        small_nums.append(i)

第一个例子是声明性的,因为我们没有指定构建列表的任何“实现细节”。

以c#为例,一般来说,使用LINQ的结果是声明式的,因为你没有说如何获得你想要的东西;你只是在说你想说的话。你可以对SQL说同样的话。

声明式编程的一个好处是,它允许编译器做出可能比手工编写更好的代码的决定。运行SQL示例,如果您有这样的查询

SELECT score FROM games WHERE id < 100;

SQL“编译器”可以“优化”这个查询,因为它知道id是一个索引字段——或者它可能没有索引,在这种情况下,它必须遍历整个数据集。或者SQL引擎知道这是利用所有8个核心进行快速并行搜索的最佳时机。作为程序员,你不需要考虑这些条件,也不需要编写代码来处理任何特殊情况。

声明式编程和命令式编程的一个很好的c#例子是LINQ。

使用命令式编程,你一步一步地告诉编译器你想要发生什么。

例如,让我们从这个集合开始,并选择奇数:

List<int> collection = new List<int> { 1, 2, 3, 4, 5 };

在命令式编程中,我们将逐步执行这些步骤,并决定我们想要什么:

List<int> results = new List<int>();
foreach(var num in collection)
{
    if (num % 2 != 0)
          results.Add(num);
}

这里,我们说:

创建一个结果集合 逐步检查集合中的每个数字 检查数字,如果是奇数,就把它加到结果中

另一方面,在声明式编程中,你写的代码描述了你想要的东西,但不一定是如何得到它(声明你想要的结果,但不是一步一步的):

var results = collection.Where( num => num % 2 != 0);

这里,我们说的是“把所有奇怪的东西都给我们”,而不是“遍历集合”。选中此项,如果为奇数,则将其添加到结果集合中。”

在许多情况下,代码也将是两种设计的混合,因此并不总是黑白分明的。

声明性程序只是它的一些或多或少的“通用”命令式实现/虚拟机的数据。

pluses: specifying just a data, in some hardcoded (and checked) format, is simpler and less error-prone than specifying variant of some imperative algorithm directly. some complex specifications just cant be written directly, only in some DSL form. best and freq used in DSLs data structures is sets and tables. because you not have dependencies between elements/rows. and when you havent dependencies you have freedom to modify and ease of support. (compare for example modules with classes - with modules you happy and with classes you have fragile base class problem) all goods of declarativeness and DSL follows immediately from benefits of that data structures (tables and sets). another plus - you can change implementation of declarative language vm, if DSL is more-or-less abstract (well designed). make parallel implementation, for example. or port it to other os etc. all good specifed modular isolating interfaces or protocols gives you such freedom and easyness of support.

缺点: 你猜对了。一般的(通过DSL参数化的)命令式算法/虚拟机实现可能比特定的算法慢和/或占用内存。在某些情况下。 如果这种情况很罕见,那就忘了它吧,让它慢慢来。如果这种情况经常发生,你总是可以扩展你的DSL/vm。某个能减缓其他案件的地方,当然…

P.S.框架介于DSL和命令式之间。作为所有的折中方案……他们结合了缺点,而不是优点。它们不是那么安全,也不是那么快:)看看万事通haskell——它介于强大的简单ML和灵活的元程序Prolog之间……真是个怪物。你可以把Prolog看作一个Haskell,它只包含布尔函数/谓词。它对Haskell的灵活性是多么简单……

我将添加另一个在声明式/命令式编程讨论中很少出现的示例:用户界面!

在c#中,您可以使用各种技术构建UI。

在命令式端,你可以使用DirectX或OpenGL命令式地绘制按钮、复选框等。一行一行的(或者实际上是一个三角形一个三角形的)。如何绘制用户界面由您决定。

在声明端,有WPF。您只需编写一些XML(是的,是的,技术上是“XAML”),框架就会为您完成工作。你说用户界面是什么样的。如何做到这一点取决于系统。

总之,这是另一件值得思考的事情。仅仅因为一种语言是声明式或命令式的,并不意味着它没有另一种语言的某些特性。

此外,声明式编程的一个好处是,通过阅读代码通常更容易理解目的,而命令式编程则可以更好地控制执行。

要点是:

说明性->你想做什么

命令式->你想怎么做

我喜欢剑桥一门课程的解释和他们的例子:

声明性-指定要做什么,而不是如何做 例如:HTML描述的是什么应该出现在网页上,而不是它应该如何在屏幕上绘制 命令式-同时指定“什么”和“如何” int x;-什么(陈述性的) x = x + 1;——如何