真正理解程序和功能之间的区别 [英] Truly understanding the difference between procedural and functional

查看:288
本文介绍了真正理解程序和功能之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很难理解程序性功能性编程范例之间的区别。

以下是维基百科入门的前两段:功能性编程:
$ b


在计算机科学中,函数
编程是一个编程范例
,它将计算视为数学函数

评估,并避免了状态和可变数据。它
强调
函数的应用,与
命令式编程风格相反,
强调状态的变化。
lambda微积分函数式编程的根源是
,在20世纪30年代为了研究
函数定义,函数
应用程序和递归而开发了一个正式系统
。许多
函数式编程语言可以将
视为对
lambda微积分的详细描述。

实际上,
$ b $ $ b数学函数和命令式
编程中使用的函数的概念
是命令式
函数可能有副作用,
会改变程序状态的值。
因此,它们缺少参照
透明度,即相同语言
表达式可能会在不同时间导致不同
值,这取决于
执行程序的状态。
相反,在函数代码中,函数的
输出值仅依赖于输入
给函数的参数
,所以调用一个函数
<$对于
参数 x ,c $ c> f 会产生相同的
结果 f(x)两次。消除
的副作用可以更容易地理解和预测程序的行为
,这是开发
函数的关键
动机之一编程。

在第2段中,它说


相反,在函数代码中,函数的输出值仅依赖于输入到函数的参数,因此使用相同的值调用函数 f 两次对于参数 x ,两次都会产生相同的结果 f(x)


与过程式编程不一样吗?



程序vs vs功能性突出?

解决方案

函数式编程



函数式编程是指将函数当作值来对待的能力。



让我们共同与常规价值观类比。我们可以使用两个整数值,并使用 + 运算符来组合它们以获得新的整数。或者我们可以用一个浮点数乘一个整数来得到一个浮点数。

在函数式编程中,我们可以将两个函数值合并为一个新的函数值诸如撰写 lift 。或者,我们可以使用运算符(如地图折叠



请注意,许多语言都具有函数式编程能力 - 即使是通常不被认为是函数式语言的语言。即使祖父FORTRAN也支持函数值,尽管它没有提供很多功能组合操作符。对于一种被称为功能性的语言,它需要大力支持函数式编程能力。



程序编程是指将一个常见的指令序列封装到一个过程中的能力,以便这些指令可以在很多地方被调用而不需要复制和粘贴。由于程序是编程中的一个非常早期的发展,其能力几乎总是与机器或汇编语言编程所要求的编程风格相联系:强调存储位置和指令在这些位置之间移动数据的概念的风格。 / p>

对比



这两种风格并非真正的对立面 - 从另一个。有些语言完全支持这两种风格(例如LISP)。以下情况可能会让您对两种风格有所区别。让我们编写一些代码,用于确定列表中的所有单词是否具有奇数个字符的情况。首先,程序风格:

 函数allOdd(words){
var result = true;
for(var i = 0; i< length(words); ++ i){
var len = length(words [i]);
if(!odd(len)){
result = false;
休息;
}
}
返回结果;
}

我认为这个例子是可以理解的。现在,函数风格:

pre $函数allOdd(words){
return apply(和,map(compose(odd,长度),单词));
}

从内到外,这个定义会做以下事情:


  1. 撰写(奇数,长度)结合奇数 length 函数生成一个新函数,该函数确定字符串的长度是否为奇数。
  2. map(...,words) words 中的每个元素调用新函数,最终返回一个新的布尔值列表,每一个都表示相应的单词是否有奇数个字符。

  3. apply(and,...)应用and运算符添加到结果列表中, - 将所有布尔值组合在一起以产生最终结果。

您可以从这些示例中看到,过程式编程非常关心在变量中移动值并明确描述产生最终结果所需的操作。相比之下,功能风格强调将初始输入转换为最终输出所需的函数组合。



该示例还显示了程序代码与功能代码的典型相对大小。此外,它表明程序代码的性能特征可能比功能代码更容易看到。考虑:函数计算列表中所有单词的长度,还是每个函数在找到第一个偶数长度单词后立即停止?另一方面,功能代码允许高质量的实现进行一些非常严格的优化,因为它主要表达意图而不是明确的算法。



更进一步阅读



这个问题出现了很多......例如:



John Backus的图灵奖授课详细阐述了函数式编程的动机:

Can Pro从von Neumann风格解放出来?



我现在不应该在这篇文章中提到这篇文章,因为它非常快速,技术性很强。我只是无法抗拒,因为我认为它确实是基础性的。



评论家指出,流行的当代语言提供了其他程序风格,超越程序和功能。这些语言通常提供以下一种或多种编程风格:


  • 查询(例如列表解析,语言集成查询)

  • 数据流(例如隐式迭代,批量操作)
  • 面向对象(例如封装数据和方法)
  • (例如特定于应用程序的语法,宏)



请参阅下面的注释以获取此响应中的伪代码示例受益于其他风格的一些设施。特别是,程序性的例子将从几乎任何更高层次的构造中受益。

所展示的例子有意避免混合这些其他编程风格,以强调区别正在讨论的两种风格。

I'm really having a hard time understanding the difference between procedural and functional programming paradigms.

Here are the first two paragraphs from the Wikipedia entry on functional programming:

In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as elaborations on the lambda calculus.

In practice, the difference between a mathematical function and the notion of a "function" used in imperative programming is that imperative functions can have side effects, changing the value of program state. Because of this they lack referential transparency, i.e. the same language expression can result in different values at different times depending on the state of the executing program. Conversely, in functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) both times. Eliminating side effects can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.

In paragraph 2 where it says

Conversely, in functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) both times.

Isn't that the same exact case for procedural programming?

What should one look for in procedural vs functional that stand out?

解决方案

Functional Programming

Functional programming refers to the ability to treat functions as values.

Let's consider an analogy with "regular" values. We can take two integer values and combine them using the + operator to obtain a new integer. Or we can multiply an integer by a floating point number to get a floating point number.

In functional programming, we can combine two function values to produce a new function value using operators like compose or lift. Or we can combine a function value and a data value to produce a new data value using operators like map or fold.

Note that many languages have functional programming capabilities -- even languages that are not usually thought of as functional languages. Even Grandfather FORTRAN supported function values, although it did not offer much in the way of function-combining operators. For a language to be called "functional", it needs to embrace functional programming capabilities in a big way.

Procedural Programming

Procedural programming refers to the ability to encapsulate a common sequence of instructions into a procedure so that those instructions can be invoked from many places without resorting to copy-and-paste. As procedures were a very early development in programming, the capability is almost invariably linked with the style of programming demanded by machine- or assembly-language programming: a style that emphasizes the notion of storage locations and instructions that move data between those locations.

Contrast

The two styles are not really opposites -- they are just different from one another. There are languages that fully embrace both styles (LISP, for example). The following scenario may give a sense of some differences in the two styles. Let's write some code for a nonsense requirement where we want to determine if all of the words in a list have an odd number of characters. First, procedural style:

function allOdd(words) {
  var result = true;
  for (var i = 0; i < length(words); ++i) {
    var len = length(words[i]);
    if (!odd(len)) {
      result = false;
      break;
    }
  }
  return result;
}

I'll take it as a given that this example is comprehensible. Now, functional style:

function allOdd(words) {
  return apply(and, map(compose(odd, length), words));
}

Working from the inside out, this definition does the following things:

  1. compose(odd, length) combines the odd and length functions to produce a new function that determines whether the length of a string is odd.
  2. map(..., words) calls that new function for each element in words, ultimately returning a new list of boolean values, each indicating whether the corresponding word has an odd number of characters.
  3. apply(and, ...) applies the "and" operator to the resulting list, and-ing all of the booleans together to yield the final result.

You can see from these examples that procedural programming is very concerned with moving values around in variables and explicitly describing the operations needed to produce the final result. In contrast, the functional style emphasizes the combination of functions required to transform the initial input to the final output.

The example also shows the typical relative sizes of procedural versus functional code. Furthermore, it demonstrates that the performance characteristics of procedural code might be easier to see than that of functional code. Consider: do the functions compute the lengths of all of the words in the list, or does each stop immediately after finding the first even length word? On the other hand, the functional code permits a high-quality implementation to perform some pretty serious optimization since it primarily expresses intent rather than an explicit algorithm.

Further Reading

This question comes up a lot... see, for example:

John Backus' Turing award lecture spells out the motivations for functional programming in great detail:

Can Programming Be Liberated from the von Neumann Style?

I really shouldn't mention that paper in the present context because it gets pretty technical, pretty quickly. I just couldn't resist because I think it is truly foundational.


Addendum - 2013

Commentators point out that popular contemporary languages offer other styles of programming over and above procedural and functional. Such languages often offer one or more of the following programming styles:

  • query (e.g. list comprehensions, language-integrated query)
  • dataflow (e.g. implicit iteration, bulk operations)
  • object-oriented (e.g. encapsulated data and methods)
  • language-oriented (e.g. application-specific syntax, macros)

See the comments below for examples of how the pseudo-code examples in this response can benefit from some of the facilities available from those other styles. In particular, the procedural example will benefit from the application of virtually any higher-level construct.

The exhibited examples deliberately avoid mixing in these other programming styles in order to emphasize the distinction between the two styles under discussion.

这篇关于真正理解程序和功能之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆