功能性,声明性和命令式编程

时间:2009-03-02 14:03:07

标签: terminology paradigms

术语功能,声明和命令式编程是什么意思?

12 个答案:

答案 0 :(得分:100)

对于这些,没有任何非模棱两可的客观定义。以下是 I 定义它们的方式:

势在必行 - 重点是计算机应采取的步骤,而不是计算机将做什么(例如C,C ++,Java)。

陈述性 - 重点是计算机应该做什么而不是应该如何做(例如SQL)。

功能 - 重点关注递归的声明性语言的子集

答案 1 :(得分:52)

命令式声明式描述了两种相反的编程风格。当务之急是传统的“一步一步的食谱”方法,而声明更多是“这就是我想要的,现在你要弄清楚如何去做。”

这两种方法贯穿整个编程 - 即使使用相同的语言和相同的程序。一般来说,声明性方法被认为是可取的,因为它使程序员不必指定如此多的细节,同时也有更少的机会获取错误(如果你描述了你想要的结果,并且一些经过良好测试的自动过程可以从那个向后工作定义步骤然后你可能希望事情比必须手动指定每一步更可靠。

另一方面,一种命令式方法可以让您进行更低级别的控制 - 这是编程的“微管理方法”。这可以让程序员利用有关问题的知识来提供更有效的答案。因此,程序的某些部分以更具说明性的方式编写并不罕见,但速度关键部分更为迫切。

正如您可能想象的那样,您用来编写程序的语言会影响您的声明性 - 一种内置“智能”的语言,用于解决结果的描述,这将允许比程序员需要首先在命令式代码中添加这种智能,然后才能在顶部构建更具声明性的层之前,更多的声明式方法。因此,例如,像prolog这样的语言被认为是非常具有声明性的,因为它内置了一个搜索答案的过程。

到目前为止,您会注意到我没有提到功能编程。那是因为它是一个术语,其含义与其他两个词没有直接关系。最简单的函数式编程意味着您可以使用函数。特别是,您使用支持函数作为“第一类值”的语言 - 这意味着您不仅可以编写函数,还可以编写函数来编写函数(编写函数...),并将函数传递给功能。简而言之 - 功能与字符串和数字一样灵活和通用。

那么,看起来很奇怪,功能性,命令性和声明性经常被一起提到。其原因是将功能编程理念“推向极端”。从最纯粹的意义上讲,函数是来自数学的东西 - 一种“黑盒子”,它接受一些输入并始终提供相同的输出。而且这种行为不需要存储变化的变量。因此,如果你设计一种编程语言,其目的是实现一种非常纯粹的,数学上受影响的函数式编程思想,那么你最终会拒绝可以改变的价值观(在一定的,有限的,技术意义上)。

如果你这样做 - 如果你限制变量的变化 - 那么几乎是偶然的,你最终强迫程序员编写更具说明性的程序,因为命令式编程的很大一部分是描述变量如何变化,而你再也不能那样了!事实证明,函数式编程 - 特别是函数式编程 - 往往会提供更多的声明性代码。

总结一下,然后:

  • 命令式和声明性是两种相反的编程风格(相同的名称用于鼓励这些风格的编程语言)

  • 函数式编程是一种编程风格,其中函数变得非常重要,因此,更改值变得不那么重要。指定值更改的能力有限会强制使用更具说明性的风格。

所以“函数式编程”通常被描述为“声明性的”。

答案 2 :(得分:50)

简而言之:

命令式语言指定计算机按顺序执行的一系列指令(执行此操作,然后执行此操作)。

声明性语言声明了一组关于哪些输出应该来自哪些输入的规则(例如,如果你有A,那么结果是B)。引擎会将这些规则应用于输入,并提供输出。

功能语言声明一组数学/逻辑函数,用于定义输入如何转换为输出。例如。 f(y)= y * y。它是一种声明性语言。

答案 3 :(得分:23)

势在必行: 如何 来实现我们的目标

   Take the next customer from a list.
   If the customer lives in Spain, show their details.
   If there are more customers in the list, go to the beginning

声明: 我们想要实现的

   Show customer details of every customer living in Spain

答案 4 :(得分:21)

命令式编程是指任何编程风格的程序,其中程序的结构是描述计算机执行操作的方式

声明性编程是指任何编程风格,其中您的程序是问题或解决方案的描述 - 但没有明确说明工作将如何完成

功能编程是通过评估函数的函数和函数进行编程......正如(严格定义的)函数编程意味着通过定义无副作用的数学函数进行编程,因此是一种形式声明性编程,但它不是唯一的声明式编程

逻辑编程(例如在Prolog中)是另一种形式的声明性编程。它涉及通过判断逻辑语句是否为真(或者是否可以满足)来进行计算。该程序通常是一系列事实和规则 - 即描述而不是一系列指令。

术语重写(例如CASL)是另一种形式的声明性编程。它涉及代数术语的象征性转换。它完全不同于逻辑编程和函数式编程。

答案 5 :(得分:13)

命令式 - 表达式描述要执行的操作序列(关联)

声明性 - 表达式是有助于程序行为的声明(关联,交换,幂等,单调)

功能 - 表达式只有效果;语义支持等式推理

答案 6 :(得分:6)

命令式编程:告诉“机器”如何做某事,结果你想要发生什么。

声明性编程:告诉“机器”你想要发生什么,并让计算机弄清楚如何去做。

命令式示例

function makeWidget(options) {
    const element = document.createElement('div');
    element.style.backgroundColor = options.bgColor;
    element.style.width = options.width;
    element.style.height = options.height;
    element.textContent = options.txt;

    return element;
}

声明性

的示例
function makeWidget(type, txt) {
    return new Element(type, txt);
}

注意:区别不在于简洁,复杂或抽象。如上所述,区别在于 的内容

答案 7 :(得分:4)

如今,新焦点:我们需要旧的分类?

势在必行/声明/功能方面在过去很好地对通用语言进行了分类,但是现在所有的“大语言”(如Java,Python,Javascript等)都有一些选择(通常frameworks)以“其他焦点”表达而不是主要的(通常的命令),并表达并行过程,声明性函数,lambdas等。

这个问题的一个很好的变体是“今天对框架进行分类的哪个方面很好?” ......一个重要的方面是我们可以标记“编程风格” ......

专注于数据与算法的融合

一个很好的例子来解释。你可以read about jQuery at Wikipedia

  

jQuery核心功能集 - DOM元素选择,遍历和操作 - 由其选择器引擎(...)启用,创建了一种新的“编程风格”,融合算法和DOM数据结构

因此,jQuery是关注“新编程风格”的最佳(流行)示例,不仅是面向对象,而是“融合 {{3} }”。 jQuery在电子表格方面有些反应,但不是“面向细胞”,“面向DOM节点”......在此上下文中比较主样式

  1. 无融合:在所有“大语言”中,在任何功能/声明/命令式表达中,通常是“无融合”的数据和算法,除了一些面向对象,这是algorithms and data-structures观点中的 fusion

  2. 一些融合:所有经典的融合策略,在当今都有一些框架使用它作为范例...... strict algebric structuredataflow(或旧的特定领域)语言为Event-driven programmingawk)...与使用现代电子表格编程一样,它们也是 XSLT 样式的示例。

  3. 大融合:是“jQuery风格”... jQuery是一种专注于“融合算法和reactive programming”的专用域语言。
    PS:其他“查询语言”,如XQuery,SQL(PL作为命令式表达选项)也是数据算法融合的例子,但它们是 islands ,没有与其他融合系统模块... DOM-data-structures,当使用find() - 变体和规范子句时,是另一个很好的融合示例。

答案 8 :(得分:3)

我认为您的分类法不正确。命令式和声明性有两种相反的类型。功能只是声明的一个子类型。顺便说一句,维基百科说明了同样的事实。

答案 9 :(得分:3)

声明性编程是通过在输入和输出之间表达一些永恒逻辑来编程,例如,在伪代码中,以下示例将是声明性的:

def factorial(n):
  if n < 2:
    return 1
  else:
    return factorial(n-1)

output = factorial(argvec[0])

我们在这里定义一个称为“阶乘”的关系,并将输出和输入之间的关系定义为该关系。这里应该很明显,关于任何结构化语言都允许在某种程度上进行声明性编程。声明性编程的一个中心思想是不可变数据,如果你分配给一个变量,你只会这样做一次,然后再也不会。其他更严格的定义意味着可能没有任何副作用,这些语言有时被称为“纯粹声明性”。

命令式风格的结果如下:

a = 1
b = argvec[0]
while(b < 2):
  a * b--

output = a

在这个例子中,我们在输入和输出之间没有表达永恒的静态逻辑关系,我们手动更改了内存地址,直到其中一个保持了所需的结果。显而易见的是,所有语言都允许声明性语义在某种程度上允许,但并非所有语言都允许使用命令式,一些“纯粹”声明性语言允许副作用和完全变异。

声明性语言通常被称为“必须做什么”而不是“如何做”,我认为这是用词不当,声明性程序仍指定必须如何从输入到输出,但在另一个方式,你指定的关系必须有效可计算(重要的术语,如果你不知道它,请查阅它)。另一种方法是非确定性编程,它实际上只是指定结果满足的条件,然后在实现之前耗尽所有试验和错误的路径,直到成功为止。

纯粹的声明性语言包括Haskell和Pure Prolog。从一个到另一个的滑动比例将是:Pure Prolog,Haskell,OCaml,Scheme / Lisp,Python,Javascript,C--,Perl,PHP,C ++,Pascall,C,Fortran,Assembly

答案 10 :(得分:3)

这里有一些关于注意到的“类型”的好答案。

我提交了一些额外的,更具“异国情调”的概念,这些概念通常与功能编程人群有关:

  • 特定于域的语言 DSL 编程:创建一种新语言来处理手头的问题。
  • 元编程:当您的程序编写其他程序时。
  • 进化编程:您可以构建一个不断改进自身或连续生成更好的子程序的系统。

答案 11 :(得分:2)

简而言之,编程风格越强调什么(要做)抽象出如何(做到这一点)的细节越多,该风格被认为是声明性的。对于命令而言则恰恰相反。函数式编程与声明式样式相关联。