我一直在网上搜索声明式编程和命令式编程的定义,希望能给我一些启发。然而,我发现在一些资源中使用的语言令人生畏——例如在维基百科。 有没有人可以给我举一个现实世界的例子,让我对这个主题有一些了解(也许是c#)?
当前回答
我发现基于幂等性和交换性更容易区分陈述性和命令性。通过参考资料来了解他们。
看看这个简化版,了解幂等性。
然后引入“WHAT”和“HOW”的定义,以理解“WHAT”和“HOW”的实际含义。在声明式中,通过定义数据之间的关系来连接数据。你没有提到这种关系应该如何实现,而是“这种关系是什么”。通过关系来描述输出数据的“样子”,而不是“如何”来实现输出数据。
开始在脑海中画一些图表,画一些点(数据),用线(关系)连接起来。画所有可能的方式,一比多,多比一&一比一。为这些行添加箭头,如<-----------。所有箭头都应该朝左,因为必须先计算特定数据所基于的所有数据,然后再向左移动以计算该特定数据。
如果数据a基于数据b,那么数据c和数据d又可能基于其他一些数据。然后先计算b c d,然后才计算a。所以a在这条线的左边其他的都在右边。从b c d有3条线到达a。
这个图表有一些属性:
NO data will violate the relationship it has with all other data control flow or the order doesn't matter, of course b, c and d should be calculated before a but there is no preference between b, c and d i.e. it doesn't matter which one of these 3 is calculated first (commutative) a is only based upon b, c and d and no one else. Hence, it doesn't matter how many times the relationship operation that calculates a using b, c and d is executed, same a should be achieved (idempotent). a is the end result of the relationship operation here. Basically, everyone who is affecting a should have a line pointing to a.
这些关系(线)就像函数(数学函数而不是编程函数)。毫无疑问,函数式编程在学术界很有名。纯函数(在我们的编程中,因此不是粗体)就像函数(在数学中,因此是粗体)。
到目前为止,声明性可能听起来像PURE和IMMUTABLE(通常用于函数式编程),如果是GOOD,如果不是GREAT。因为这不是这里的目的,这是从这个模式中自动出现的。
如果你的一段代码可以转换成这个图表,那么它就是完全声明性的,否则,它就在尺度上的其他地方。
说明性很接近数学。
现在让我们放大这些关系(行),看看在程序执行期间计算机内部发生了什么。
命令式进来了。这就是底层工作完成的地方。在命令式中,你会一步一步地提到“如何”完成它,你知道这一系列步骤将在一个数据(输入b c d)和另一个数据(输出a)之间创建所请求的关系。在这里,你创建变量,改变它们,循环数组和所有其他事情。
命令式接近编程。
我不认为程序是声明式的或命令式的,我更喜欢把它放在最左边是完全声明式的,最右边是完全命令式的。记住,声明式是建立在命令式之上的,因此你看到的任何声明式的东西实际上都是命令式的。一般来说,程序是声明式和命令式的混合。
现在,让我们举两个例子:
第二个例子可以转换成这样的图表:
reduce_r map_r filter_r A <--------- b <--------- c <--------- d
Filter_r(关系):c只是d的偶数 Map_r(关系):b是所有数字乘以10的c Reduce_r (relationship): a是b加起来的所有数字
这应该看起来像数学的复合函数:reduce_r(map_r(filter_r(d)))
在声明中,开发人员的工作是将最终目标(a)分解为有助于实现最终目标的子目标(b, c)。
当然后台程序的映射、缩减和过滤是运行的必要代码。
值得思考的是:如果您需要对map函数做一个假设,从左到右,以使您的代码按预期工作,那么您实际上是在以声明的名义执行命令式操作。
参考资料:purpleidea (James), www.dataops.live, wiki.c2.com
其他回答
这只是一个实际的例子,说明为什么CSS是声明式的,而JavaScript是命令式的。
假设我们有这个导航栏,用户当前正在查看“探索”选项,所以它被标记为当前选中。
<ul>
<li class="selected">
<p>Explore</p>
</li>
<li>
<p>Suggestions</p>
</li>
</ul>
我们希望当前选择的选项的标题是蓝色的,我们如何实现这与CSS和JavaScript?
CSS
li.selected > p {
color: blue;
}
李在这里。Selected > p声明了我们想要属性颜色的元素的模式:蓝色;待应用。结果是“探索”用蓝色突出显示,而“建议”没有。注意,我们的代码描述了我们想要发生什么,而不是如何发生。CSS选择器引擎如何找到“探索”?我们不知道,通常也不在乎。
JavaScript
let liElements = document.getElementsByTagName("li")
for (let i = 0; i < liElements.length; i++) {
if (liElements[i].className === "selected") {
let children = liElements[i].childNodes
for (let j = 0; j < children. length; j++) {
let child = children[j]
if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "P") {
child.setAttribute("style", "color: blue")
}
}
}
}
这段代码要长得多,也更难理解。除此之外,它将蓝色应用于所选选项,但当所选类被删除时,它永远不会取消应用它。蓝色只有在页面重新加载时才会重置。注意,在这段代码中,我们一步一步精确地指定了需要做什么以及如何做。
结论
每种编程范例都有其优点。
CSS(声明)
简洁的 作为程序员,我们不能控制CSS内核如何做我们需要的事情。这给了CSS核心开发人员在任何时候改变CSS选择器实现的机会。为什么CSS核心需要改变?也许,CSS开发人员找到了一种更快的方法来应用属性。
JavaScript(必须)
定制。我们控制代码如何实现目标的所有方面。 适合解决各种各样的问题
声明性编程是你说你想要什么,命令式编程是你说如何得到你想要的。
一个简单的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个核心进行快速并行搜索的最佳时机。作为程序员,你不需要考虑这些条件,也不需要编写代码来处理任何特殊情况。
在计算机科学中,声明式编程是一种编程范式,它在不描述控制流的情况下表达计算逻辑。
从http://en.wikipedia.org/wiki/Declarative_programming
简而言之,声明式语言更简单,因为它缺乏控制流(循环、if语句等)的复杂性。
一个很好的比较是ASP。网络“后台代码”模型。你们有陈述句。'ASPX '文件,然后是'ASPX. cs '代码文件。我经常发现,如果我可以在脚本的声明性部分完成我所需要的一切,那么更多的人可以理解所做的事情。
命令式编程 一种需要编程规程的编程语言,如C/ c++, Java, COBOL, FORTRAN, Perl和JavaScript。用这种语言编写程序的程序员必须基于数据处理和编程知识,开发出适当的操作顺序来解决问题。
声明性编程 一种不需要编写传统编程逻辑的计算机语言; 用户专注于定义输入和输出,而不是过程式编程语言(如c++或Java)中所需的程序步骤。
声明性编程的例子有CSS、HTML、XML、XSLT、RegX。
声明式编程和命令式编程的一个很好的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);
这里,我们说的是“把所有奇怪的东西都给我们”,而不是“遍历集合”。选中此项,如果为奇数,则将其添加到结果集合中。”
在许多情况下,代码也将是两种设计的混合,因此并不总是黑白分明的。
推荐文章
- net HttpClient。如何POST字符串值?
- 我如何使一个方法的返回类型泛型?
- 何时处理CancellationTokenSource?
- 如何获取正在执行的程序集版本?
- AutoMapper vs valueinjector
- 为什么控制台不。Writeline,控制台。在Visual Studio Express中编写工作?
- 什么是.NET程序集?
- 字符串不能识别为有效的日期时间“格式dd/MM/yyyy”
- 函数应该返回空对象还是空对象?
- 如何转换日期时间?将日期时间
- 如何在c#中连接列表?
- 在c#中引用类型变量的“ref”的用途是什么?
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?