我一直在网上搜索声明式编程和命令式编程的定义,希望能给我一些启发。然而,我发现在一些资源中使用的语言令人生畏——例如在维基百科。 有没有人可以给我举一个现实世界的例子,让我对这个主题有一些了解(也许是c#)?
当前回答
再举一个手机应用开发的例子。在iOS和Android中,我们有界面构建器,在那里我们可以定义应用程序的UI。
使用这些生成器绘制的UI本质上是声明性的,我们可以在其中拖放组件。实际的绘图发生在框架和系统下面,由框架和系统执行。
但我们也可以在代码中画出整个组件,这在本质上是必要的。
此外,一些新语言,如Angular JS,专注于以声明方式设计ui,我们可能会看到许多其他语言提供同样的支持。就像Java在Java swing或Java FX中没有任何好的声明性方法来绘制本地桌面应用程序,但在不久的将来,他们可能会这样做。
其他回答
我发现基于幂等性和交换性更容易区分陈述性和命令性。通过参考资料来了解他们。
看看这个简化版,了解幂等性。
然后引入“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
声明性编程是你说你想要什么,命令式编程是你说如何得到你想要的。
一个简单的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个核心进行快速并行搜索的最佳时机。作为程序员,你不需要考虑这些条件,也不需要编写代码来处理任何特殊情况。
这只是一个实际的例子,说明为什么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(必须)
定制。我们控制代码如何实现目标的所有方面。 适合解决各种各样的问题
声明式与命令式
编程范式是计算机编程的一种基本风格。 主要有四种范式:命令式、声明式、函数式(被认为是声明式范式的子集)和面向对象的。
Declarative programming : is a programming paradigm that expresses the logic of a computation(What do) without describing its control flow(How do). Some well-known examples of declarative domain specific languages (DSLs) include CSS, regular expressions, and a subset of SQL (SELECT queries, for example) Many markup languages such as HTML, MXML, XAML, XSLT... are often declarative. The declarative programming try to blur the distinction between a program as a set of instructions and a program as an assertion about the desired answer.
命令式编程:是一种编程范式,它用改变程序状态的语句来描述计算。命令式程序可以被视为编程命令或数学断言。
函数式编程:是一种编程范式,它将计算视为数学函数的求值,并避免状态和可变数据。它强调函数的应用,而命令式编程风格强调状态的变化。 在纯函数式语言(如Haskell)中,所有函数都没有副作用,状态更改仅表示为转换状态的函数。
下面是MSDN中命令式编程的示例,循环遍历数字1到10,并找到偶数。
var numbersOneThroughTen = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//With imperative programming, we'd step through this, and decide what we want:
var evenNumbers = new List<int>();
foreach (var number in numbersOneThroughTen)
{ if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}
//The following code uses declarative programming to accomplish the same thing.
// Here, we're saying "Give us everything where it's even"
var evenNumbers = numbersOneThroughTen.Where(number => number % 2 == 0);
这两个例子都产生了相同的结果,一个既不比另一个好也不比另一个差。第一个示例需要更多代码,但代码是可测试的,命令式方法让您完全控制实现细节。在第二个例子中,代码可以说更可读;然而,LINQ并不能让你控制幕后发生的事情。您必须相信LINQ将提供所请求的结果。
Imperative programming requires developers to define step by step how code should be executed. To give directions in an imperative fashion, you say, “Go to 1st Street, turn left onto Main, drive two blocks, turn right onto Maple, and stop at the third house on the left.” The declarative version might sound something like this: “Drive to Sue’s house.” One says how to do something; the other says what needs to be done. The declarative style has two advantages over the imperative style: It does not force the traveler to memorize a long set of instructions. It allows the traveler to optimize the route when possible.
卡尔弗特,C库尔卡尼,D(2009)。LINQ至关重要。艾迪森·韦斯利48岁
推荐文章
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- c#中有任何连接字符串解析器吗?
- 在Linq中转换int到字符串到实体的问题
- 是否可以动态编译和执行c#代码片段?
- 创建自定义MSBuild任务时,如何从c#代码获取当前项目目录?
- c#和Java的主要区别是什么?
- 在c#中创建一个特定时区的DateTime
- .NET中的属性是什么?
- csproj文件中的“Service Include”是干什么用的?
- 如何使用try catch进行异常处理是最佳实践
- 替换字符串中第一次出现的模式
- .NET中字节的字面后缀?
- 如何处理AccessViolationException
- c#忽略证书错误?