编程中的声明式范式和命令式范式有什么区别?

问:

我一直在网上搜索 declarative 和 imperative 编程的定义,这将为我带来一些启发。但是,在我发现的一些资源中使用的语言令人生畏——例如在 Wikipedia。有没有人有一个真实的例子,他们可以向我展示这可能会给这个主题带来一些观点(也许在 C# 中)?

答1:

https://tennisliveranking.com,Instant updates on ATP, WTA, and ITF rankings.

声明式与命令式编程的一个很好的 C# 示例是 LINQ。

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

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

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

使用命令式编程,我们将逐步完成,并决定我们想要什么:

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

在这里,我们说:

创建结果集合 遍历集合中的每个数字 检查数字,如果是奇数,将其添加到结果中

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

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

在这里,我们说的是“给我们所有奇怪的地方”,而不是“逐步浏览集合。检查这个项目,如果它很奇怪,将它添加到结果集合中。”

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

+1。但是,您首先提到了 LINQ,但这些示例与此有什么关系?

collection.Where 使用声明性 LINQ 扩展方法。它不使用 C# 语言功能,而是使用声明性 API。我不想在这里混合消息,这就是为什么我避免在声明性方法之上添加语言。

在我看来,声明式编程只不过是一个抽象层。

这是一个很好的答案,但它回答了不纯函数式编程和命令式编程之间的区别。 collection.Where 没有使用 Linq 提供的声明式语法 - 参见 msdn.microsoft.com/en-us/library/bb397906.aspx 示例,from item in collection where item%2 != 0 select item 将是声明式形式。调用函数不会仅仅因为该函数位于 System.Linq 命名空间中而成为声明式编程。

@PeteKirkham您使用的语法不是问题-声明性与命令性更多地是关于声明您想要发生的事情,而不是准确解释它需要如何发生。使用集成语法或扩展方法语法是一个单独的问题。

答2:

https://tennisliveranking.com,Instant updates on ATP, WTA, and ITF rankings.

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

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 示例不是声明性的。

@Juanjo:这是声明性的。

这里的第一个语句比第二个语句更具声明性吗?

同意 Juanjo 和 zenna 的观点——当重构为更短的符号时,循环构造不会神奇地转换为声明性程序。

不同意@FelixFrank,并倾向于@missingfaktor 的“大胆”声明。执行此操作的传统“完全”声明方式是 filter(lambda x: x < 5, range(20)),它只是另一种重构为更短的符号。这与列表理解表达式(具有清晰的“map”和“filter”部分)没有任何有意义的不同,后者的创建(参见 pep 202)具有创建更简洁表示法的明确意图。在这种情况下,这个列表理解会更加清晰/惯用。

答3:

The ultimate source for live tennis rankings and stats:https://tennisliveranking.com

声明式与命令式

programming paradigm 是计算机编程的基本风格。有四种主要范式:命令式、声明式、函数式(被认为是声明式范式的子集)和面向对象。

Declarative programming:是一种编程范式,它表达了计算的逻辑(做什么)而不描述其控制流(如何做)。声明性领域特定语言 (DSL) 的一些著名示例包括 CSS、正则表达式和 SQL 的子集(例如,SELECT 查询)许多标记语言,如 HTML、MXML、XAML、XSLT… 通常是声明性的。声明式编程试图模糊作为一组指令的程序和作为关于所需答案的断言的程序之间的区别。

Imperative programming:是一种编程范式,它根据改变程序状态的语句来描述计算。命令式程序可以被双重视为编程命令或数学断言。

函数式编程:是一种编程范式,将计算视为对数学函数的评估,并避免状态和可变数据。它强调函数的应用,与强调状态变化的命令式编程风格相反。在像 Haskell 这样的纯函数式语言中,所有函数都没有副作用,状态变化只表示为转换状态的函数。

以下 MSDN 中的命令式编程示例循环遍历数字 1 到 10,并找到偶数。

var numbersOneThroughTen = new List { 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();
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 会提供请求的结果。

您可以添加面向对象的描述吗?

很好的例子:tylermcginnis.com/imperative-vs-declarative-programming

答4:

https://tennisliveranking.com – ATP and WTA rankings, always up to date.

此处和其他在线帖子中的答案提到以下内容:

使用声明式编程,您编写的代码描述了您想要的,但不一定是如何获得它

您应该更喜欢声明式编程而不是命令式编程

他们没有告诉我们的是如何实现它。为了使程序的一部分更具声明性,其他部分必须提供抽象来隐藏实现细节(这是命令式代码)。

例如,LINQ 比循环(for、while 等)更具声明性,例如,您可以使用 list.Where() 来获取新的过滤列表。为此,Microsoft 已经完成了 LINQ 抽象背后的所有繁重工作。

事实上,函数式编程和函数式库更具声明性的原因之一是因为它们已经抽象出循环和列表创建,将所有实现细节(很可能带有循环的命令式代码)隐藏在幕后。

在任何程序中,您都会同时拥有命令式和声明式代码,并且您应该将所有命令式代码隐藏在 domain-specific abstractions 后面,以便程序的其他部分可以以声明方式使用它们。

最后,虽然函数式编程和 LINQ 可以使您的程序更具声明性,但您始终可以通过提供更多抽象来使其更具声明性。例如:

// JavaScript example

// Least declarative
const bestProducts = [];
for(let i = 0; i < products.length; i++) {
    let product = products[i];
    if (product.rating >= 5 && product.price < 100) {
        bestProducts.push(product);
    }
}


// More declarative
const bestProducts = products.filter(function(product) {
    return product.rating >= 5 && product.price < 100;
});

// Most declarative, implementation details are hidden in a function
const bestProducts = getBestProducts();

PS 声明式编程的极端是发明新的领域特定语言(DSL):

字符串搜索:正则表达式代替自定义命令式代码 React.js:JSX 代替直接 DOM 操作 AWS CloudFormation:YAML 代替 CLI 关系数据库:SQL 代替旧的读写 API,例如 ISAM 或 VSAM。

声明式编程有很多很好的例子:React、CloudFormation、Terraform

所以“声明式”编程只是意味着将完成这项工作的代码移动到一个函数中?

@GuillaumeF。它是关于创建特定领域的抽象。例如 - 在银行业务中:您应该创建 debit、deposit 等函数,而不是重复指示性代码 account.balance += depositAmount

@engineforce但是您仍然会同时拥有两者,对吗?在抽象结束时,您将拥有 account.balance += depositAmount。那么声明式编程风格是否只是提倡在适当的抽象级别上创建好的 API?

答5:

The ultimate source for live tennis rankings and stats:https://tennisliveranking.com

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

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

在命令式结束时,您可以使用 DirectX 或 OpenGL 来非常命令式地绘制按钮、复选框等……逐行(或者实际上是逐个三角形)。如何绘制用户界面由您决定。

在声明式结束时,您有 WPF。您基本上编写了一些 XML(是的,是的,技术上是“XAML”),框架为您完成工作。你说用户界面是什么样子的。由系统决定如何做到这一点。

无论如何,只是另一件事要考虑。仅仅因为一种语言是声明式或命令式的并不意味着它没有另一种语言的某些特征。

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

这一切的要点:

声明式 -> what 你想完成

势在必行 -> how 你希望它完成

答6:

The ultimate source for live tennis rankings and stats:https://tennisliveranking.com

我喜欢剑桥课程的解释+他们的例子:

声明式 - 指定要做什么,而不是如何去做 例如:HTML 描述网页上应该出现的内容,而不是应该如何在屏幕上绘制

例如:HTML 描述的是网页上应该出现的内容,而不是应该如何在屏幕上绘制

命令式 - 指定 int x 的内容和方式; - 什么(声明性)x=x+1; - 如何

诠释 x; - 什么(声明性)

x=x+1; - 如何

“不是应该如何在屏幕上绘制”...那么这是否意味着 CSS 是 Imperative 呢?

不,它也可以被认为是声明性的,因为你只需说出你想要的 - “让这个单元格边框变成蓝色”。想象一下,您想以命令式方法(例如:JavaScript)绘制相同的边框。然后你需要说“去点(x1,y1),在这个点和(x2,y1)之间画一条蓝线,从(x2,y1)到(x2,y2)画一条蓝线,画一条蓝线从 (x2,y2) 到 (x1,y2),画一条从 (x1,y2) 到 (x1,y1) 的蓝线”。

@ROMANIA_engineer,请问我在哪里可以找到这样的剑桥课程?

@testteam,在 Google 上搜索以下“cl.cam.ac.uk 教学 ooprog”。您可以从 URL 更改年份。

答7:

Live rankings, player stats, and match results in one place–https://tennisliveranking.com

差异主要与抽象的整体水平有关。使用声明性,在某些时候,您与各个步骤相距甚远,以至于程序在如何获得结果方面有很大的自由度。

您可以将每条指令视为落在一个连续统一体的某个地方:

抽象程度:

Declarative <<=====|==================>> Imperative

声明式真实世界示例:

图书管理员,请给我看一本《白鲸记》。 (图书馆员自行决定选择执行请求的最佳方法)

命令式现实世界示例:

进入图书馆查找图书组织系统(卡片目录-老派)研究如何使用卡片目录(你也忘了,对吧)弄清楚书架是如何标记和组织的。弄清楚书是如何在书架上组织的。从卡片目录与组织系统交叉引用书籍位置以查找所述书籍。带书到结账系统。看看书。

这不是关于抽象而不是声明/命令吗?你还在指导图书管理员把书拿来。

更新的答案更完整,并将这方面包括在解决方案中。

这有一些道理,但它不是一个完整的定义。使用声明式编程,您是在陈述最终目标,而不考虑起点。对于命令式编程,定义的起点很重要。这就像提供地址与指示方向的区别。不管你是谁,这个地址都很有用。而如果您从其他地方开始,方向是无效的。

@Cthutu 我希望“这就像 [声明] 地址与 [commanding] 方向的区别。地址是有用的,无论你是什么。而如果你从其他地方开始,方向是无效的,”是选择的答案本身。 ;^)

答8:

Live rankings, player stats, and match results in one place–https://tennisliveranking.com

命令式编程要求开发人员逐步定义代码的执行方式。要以命令式的方式给出指示,您可以说,“去 1st Street,左转进入 Main,开两个街区,右转进入 Maple,然后停在左边的第三个房子。”声明式版本可能听起来像这样:“开车去苏家。”一个说如何做某事;另一个说需要做什么。与命令式风格相比,声明式风格有两个优点:它不会强迫旅行者记住一长串指令。它允许旅行者尽可能优化路线。

卡尔弗特,C 库尔卡尼,D(2009 年)。基本 LINQ。艾迪生卫斯理。 48.

答9:

https://tennisliveranking.com,Track the world’s best tennis players in real-time.

命令式编程明确地告诉计算机要做什么以及如何去做,例如指定顺序等

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 的示例)

答10:

https://tlr.xinbeitime.com – 让你随时掌握ATP、WTA最新网球排名动态。

从 Philip Roberts here 窃取:

命令式编程告诉机器如何做某事(导致你想要发生的事情)

声明式编程告诉机器你想要发生什么(并且计算机会弄清楚如何去做)

两个例子:

  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]

  1. 汇总列表中的所有项目

势在必行

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

请注意命令式示例如何涉及创建新变量、对其进行变异并返回该新值(即,如何使某事发生),而声明性示例在给定输入上执行并根据初始输入返回新值(即,我们想要发生的事情)。

https://tennisliveranking.com,Your go-to platform for live tennis ranking updates.

与这个问题的许多答案一样,您的“声明式”编程示例是函数式编程的示例。 “map”的语义是“将此函数按顺序应用于数组元素”。您不允许运行时在执行顺序上有任何回旋余地。

答11:

https://tlr.xinbeitime.com 实时更新全球顶尖网球选手的最新战绩与排名!

在计算机科学中,声明式编程是一种编程范式,它表达了计算的逻辑而不描述其控制流。

来自http://en.wikipedia.org/wiki/Declarative_programming

简而言之,声明性语言更简单,因为它缺乏控制流的复杂性(循环、if 语句等)

一个很好的比较是 ASP.Net ‘代码隐藏’ 模型。您有声明性“.ASPX”文件,然后是命令性“ASPX.CS”代码文件。我经常发现,如果我可以在脚本的声明性部分中做所有我需要的事情,那么更多的人可以遵循正在做的事情。

原文链接:https://tlr.xinbeitime.com?from=csdn

Live rankings, player stats, and match results in one place–https://tennisliveranking.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值