我一直在网上搜索声明式编程和命令式编程的定义,希望能给我一些启发。然而,我发现在一些资源中使用的语言令人生畏——例如在维基百科。 有没有人可以给我举一个现实世界的例子,让我对这个主题有一些了解(也许是c#)?
当前回答
From my understanding, both terms have roots in philosophy, there are declarative and imperative kinds of knowledge. Declarative knowledge are assertions of truth, statements of fact like math axioms. It tells you something. Imperative, or procedural knowledge, tells you step by step how to arrive at something. That's what the definition of an algorithm essentially is. If you would, compare a computer programming language with the English language. Declarative sentences state something. A boring example, but here's a declarative way of displaying whether two numbers are equal to each other, in Java:
public static void main(String[] args)
{
System.out.print("4 = 4.");
}
另一方面,英语中的祈使句给出命令或提出某种请求。因此,命令式编程只是一个命令列表(做这个,做那个)。下面是在Java中,在接受用户输入时显示两个数字是否相等的强制方法:
private static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.println();
System.out.print("Enter an integer value for x: ");
int x = input.nextInt();
System.out.print("Enter an integer value for y: ");
int y = input.nextInt();
System.out.println();
System.out.printf("%d == %d? %s\n", x, y, x == y);
}
从本质上讲,声明性知识跳过某些元素,在这些元素之上形成一个抽象层。声明式编程也是如此。
其他回答
再举一个手机应用开发的例子。在iOS和Android中,我们有界面构建器,在那里我们可以定义应用程序的UI。
使用这些生成器绘制的UI本质上是声明性的,我们可以在其中拖放组件。实际的绘图发生在框架和系统下面,由框架和系统执行。
但我们也可以在代码中画出整个组件,这在本质上是必要的。
此外,一些新语言,如Angular JS,专注于以声明方式设计ui,我们可能会看到许多其他语言提供同样的支持。就像Java在Java swing或Java FX中没有任何好的声明性方法来绘制本地桌面应用程序,但在不久的将来,他们可能会这样做。
这里借用菲利普·罗伯茨的一句话:
命令式编程告诉机器如何做某事(导致你想要发生的事情) 声明性编程告诉机器你想要发生什么(然后计算机找出如何去做)
两个例子:
1. 将数组中的所有数字加倍
命令式地:
var numbers = [1,2,3,4,5]
var doubled = []
for(var i = 0; i < numbers.length; i++) {
var newNumber = numbers[i] * 2
doubled.push(newNumber)
}
console.log(doubled) //=> [2,4,6,8,10]
声明:
var numbers = [1,2,3,4,5]
var doubled = numbers.map(function(n) {
return n * 2
})
console.log(doubled) //=> [2,4,6,8,10]
2. 对列表中的所有项求和
命令式地
var numbers = [1,2,3,4,5]
var total = 0
for(var i = 0; i < numbers.length; i++) {
total += numbers[i]
}
console.log(total) //=> 15
以声明的方式
var numbers = [1,2,3,4,5]
var total = numbers.reduce(function(sum, n) {
return sum + n
});
console.log(total) //=> 15
请注意,命令式示例涉及如何创建一个新变量,改变它,并返回新值(即,如何使某事发生),而声明式示例执行给定的输入,并根据初始输入返回新值(即,我们想要发生什么)。
我发现基于幂等性和交换性更容易区分陈述性和命令性。通过参考资料来了解他们。
看看这个简化版,了解幂等性。
然后引入“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
From my understanding, both terms have roots in philosophy, there are declarative and imperative kinds of knowledge. Declarative knowledge are assertions of truth, statements of fact like math axioms. It tells you something. Imperative, or procedural knowledge, tells you step by step how to arrive at something. That's what the definition of an algorithm essentially is. If you would, compare a computer programming language with the English language. Declarative sentences state something. A boring example, but here's a declarative way of displaying whether two numbers are equal to each other, in Java:
public static void main(String[] args)
{
System.out.print("4 = 4.");
}
另一方面,英语中的祈使句给出命令或提出某种请求。因此,命令式编程只是一个命令列表(做这个,做那个)。下面是在Java中,在接受用户输入时显示两个数字是否相等的强制方法:
private static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.println();
System.out.print("Enter an integer value for x: ");
int x = input.nextInt();
System.out.print("Enter an integer value for y: ");
int y = input.nextInt();
System.out.println();
System.out.printf("%d == %d? %s\n", x, y, x == y);
}
从本质上讲,声明性知识跳过某些元素,在这些元素之上形成一个抽象层。声明式编程也是如此。
命令式编程是显式地告诉计算机做什么,以及如何做,比如指定顺序等
C#:
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Hello World!");
}
说明性是指你告诉计算机做什么,而不是如何做。Datalog / Prolog是在这方面首先想到的语言。基本上所有东西都是声明性的。你不能保证秩序。
c#是一种更命令式的编程语言,但某些c#特性更具有声明性,如Linq
dynamic foo = from c in someCollection
let x = someValue * 2
where c.SomeProperty < x
select new {c.SomeProperty, c.OtherProperty};
同样的东西也可以写成命令式:
dynamic foo = SomeCollection.Where
(
c => c.SomeProperty < (SomeValue * 2)
)
.Select
(
c => new {c.SomeProperty, c.OtherProperty}
)
(例子来自维基百科Linq)
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?
- c#对象列表,我如何得到一个属性的和