姬長信(Redy)

声明式和命令式

> In computer science, declarative programming is a programming paradigm /u2014 a style of building the structure and elements of computer programs/u2014that expresses the logic of a computation without describing its control flow. > This is in contrast with imperative programming, which implements algorithms in explicit steps. 声明式编程/uff1a告诉/u201c机器/u201d你想要的是什么(what)/uff0c让机器想出如何去做(how)。 > In computer science, imperative programming is a programming paradigm that uses statements that change a program's state. In much the same way that the imperative mood in natural languages expresses commands, an imperative program consists of commands for the computer to perform. Imperative programming focuses on describing how a program operates. > The term is often used in contrast to declarative programming, which focuses on what the program should accomplish without specifying how the program should achieve the result. 命令式编程/uff1a命令/u201c机器/u201d如何去做事情(how)/uff0c这样不管你想要的是什么(what)/uff0c它都会按照你的命令实现。 ## 声明式编程和命令式编程的代码例子 举个简单的例子/uff0c假设我们想让一个数组里的数值翻倍。 我们用命令式编程风格实现/uff0c像下面这样/uff1a ```JavaScript var numbers = [1,2,3,4,5] var doubled = [] for(var i = 0; i [2,4,6,8,10] ``` 我们直接遍历整个数组/uff0c取出每个元素/uff0c乘以二/uff0c然后把翻倍后的值放入新数组/uff0c每次都要操作这个双倍数组/uff0c直到计算完所有元素。 而使用声明式编程方法/uff0c我们可以用 Array.map 函数/uff0c像下面这样/uff1a ```JavaScript var numbers = [1,2,3,4,5] var doubled = numbers.map(function(n) { return n * 2 }) console.log(doubled) //=> [2,4,6,8,10] ``` map 利用当前的数组创建了一个新数组/uff0c新数组里的每个元素都是经过了传入 map 的函数处理。 map 函数所作的事情是将直接遍历整个数组的过程归纳抽离出来/uff0c让我们专注于描述我们想要的是什么(what)。注意/uff0c我们传入 map 的是一个纯函数/uff1b**它不具有任何副作用(不会改变外部状态)**/uff0c它只是接收一个数字/uff0c返回乘以二后的值。 在一些具有函数式编程特征的语言里/uff0c对于**集合数据类型**/uff0c还有一些其他常用的声明式的函数方法。例如 **reduce、filter** ## 声明式编程很奇怪吗/uff1f 作为程序员/uff0c我们非常习惯去指出事情应该如何运行。当我们已经知道了如何告诉机器该如何做事时/uff08假如集合数据类型没有 reduce、filter、map 等函数/uff0c那么作为程序员/uff0c肯定想到的是 for 循环/uff0c变量操作等等/uff09/uff0c为什么我们需要去学习这种看起来有些怪异的归纳抽离出来的函数工具/uff1f 很多情况下/uff0c命令式编程很好用。当我们写业务逻辑/uff0c我们通常必须要写命令式代码/uff0c没有可能在我们的专项业务里也存在一个可以归纳抽离的实现。但是我们可以在小的功能组件或者 UI 渲染等层面做声明式编程。比如 SwiftUI、Flutter、React、Vue 等。 但是/uff0c如果我们花时间去学习(或发现)声明式的可以归纳抽离的部分/uff0c它们能为我们的编程带来巨大的便捷。首先/uff0c我可以少写代码/uff0c这就是通往成功的捷径。而且它们能让我们站在更高的层面是思考/uff0c站在顶层去思考我们想要的是什么/uff0c而不是站在最底层思考事情该如何去做。 ## 声明式编程语言/uff1aSQL 没意识到我们在学习数据库的时候/uff0cSQL 就是声明式编程。 你可以把 SQL 当做一个处理数据的声明式查询语言。完全用SQL写一个应用程序/uff1f这不可能。但如果是处理相互关联的数据集/uff0c它就显的无比强大了。 像下面这样的查询语句/uff1a ```SQL SELECT * from dogs INNER JOIN owners WHERE dogs.owner_id = owners.id; ``` 如果我们用命令式编程方式实现这段逻辑/uff1a ```JavaScript //dogs = [{name: 'Fido', owner_id: 1}, {...}, ... ] //owners = [{id: 1, name: 'Bob'}, {...}, ...] var dogsWithOwners = [] var dog, owner for(var di=0; di