声明式vs命令式

例如我们有一个用户列表,用 python 查找手机号为 183 开头的用户,可能会这么写:

def get_users():ret = []for user in users:if user['phone'].startswith('183'):ret.append(user)return ret

这是命令式的作法,给出通向目标的每个指令;而声明式语言则直接描述目标,如 SQL 可能会这么写:

SELECT * FROM users where phone like '183%';

显然,声明式语言对用户更友好,用户可以关心更少的细节。更重要的是:它允许多种底层实现方式,保持目标不变的同时不断优化,如上例中 SQL 的实现既可以遍历所有的用户,也可以使用索引来加速查找。

而命令式的好处自然是它的表达能力了,图灵完备的语言可以表达任何的可计算问题。

声明式不是万能的

声明式语言直接描述目标,那怎么才能清晰地描述目标呢?有时候也需要命令式的帮助。

考虑下面的命令式的伪代码要如何用 SQL 实现:

goods = (SELECT * from goods)
for g in goods:#>> 注意在内层循环中可以引用外层表 goods 的字段evaluations = (SELECT * from evaluations e where e.good_id == g.id)if len(evaluations) > 3:print(g, len(evaluations))

会发现使用常规的 JOIN 语义,很难实现上述目标。子查询里是无法引用其它查询的字段的,这本身是一种优势,数据库内部可以对 JOIN 的实现进行优化,但同时也限制了对复杂 JOIN 语义的表达。

后来 SQL 里加了个关键字:LATERAL[3],用来表达子查询的先后顺序,上例可以写成:

SELECT g.*, e.num FROM goods as g
LEFT JOIN LATERAL(SELECT COUNT(ev.id) as num FROM  evaluation AS ev WHERE ev.goods_id=g.id
) AS e ON TRUE WHERE num > 3

有了 LATERAL,在 LATERAL 后的子查询就可以引用前面子查询的变量。那么LATERAL 算是声明式还是命令式?似乎变得模糊了,一方面它依旧是表达目标,是声明式;另一方面它似乎指定了操作步骤(先查 goods,再查 evaluations)属于命令式。

当描述的目标变复杂时,声明式语言也不可避免变得更命令式,通过描述过程来描述更多细节

命令式里的声明式

传统上的一些编程语言,如 C/C++、Java、Python 等都被认为是命令式语言。用这些语言编写程序时的确是一条语句一条语句导向最终的目标。但这些编程语言与声明式的界限也并非泾渭分明。

除了机器码,包括汇编在内的几乎其它所有编程语言都有“函数”的概念。通过将语句组装成函数,无论是在使用还是阅读上,似乎都可以认为是在指定目标,是声明式的。例如要计算 Fibonacci 数列的第 N 个数,如果已经有现成的库,我们也只需要写 x = fibonacci(n),似乎也不是“命令式”吧。

另外,编程语言的一些语法糖也加强了我们“声明目标”的能力,如 Python 的装饰器 (decorator) @dataclass,“声明”式地定义一个类为数据类,Java 的 lombok 库也有 @Data 这样的注解(annotation)实现类似的功能。

通过适当的封装、组件化,命令式也可以变成目标导向,变得更加“声明式”

小结

声明式使用方便、容易理解、易于优化,但表达能力有限,要表达更复杂的目标时,它往往也在向命令式靠拢了。而命令式里很多重复性的工作,也可以通过适当地组件化部分变成声明式。这样看来,一门语言是声明式还是命令式,似乎取决于我们接触的细节多少。

生活中,大老板决定路线,小老板决定方案,螺丝钉具体落实,不也类似嘛。

在我们设计语言、库时,尽可能地将接口设计得“声明式”,暴露更少的细节给用户,不仅能让用户用得开心,也方便内部的扩展、优化。

参考

https://reactjs.org/ React 的设计理念:Declarative view
《Design Data-Intensive Applications》第二章,说明 CSS/XSL 是声明式的语言
未来属于声明式编程 对声明式编程语言的思考
命令式和声明式,哪个才是你的菜 描述了声明式、命令式的一些差别

引用

[1] https://en.wikipedia.org/wiki/Declarative_programming

[2] https://en.wikipedia.org/wiki/Imperative_programming

[3] 出现在 ISO/IEC 7095:199 标准中,Postgre、 Flink 支持

声明式(declarative) vs 命令式(imperative)相关推荐

  1. 声明式UI是否会成为Android开发的主流?

    从Windows到Web,到Android,到iOS,我们编写应用 (App) 最初的方式都是命令式的 (Imperative Style) .但随着声明式 (Declarative Style) 的 ...

  2. Flink 能够改写成 FlinkSQL的理论依据:命令式代码 vs 声明式代码

    普通的业务逻辑是否能改写成 SQL?Flink 能够改写成 FlinkSQL的理论依据是什么? 当关系模型最初被引入时,就包含了查询数据的不同方法:SQL 是一种声明式查询语言,而 IMS 和 COD ...

  3. 函数式编程与声明式语言

    原文链接:https://www.cnblogs.com/doit8791/p/8232821.html 编程语言可以分成两类: 命令式 声明式 事实上,凡是非命令式的编程都可归为声明式编程.因此,命 ...

  4. 声明式UI(Declarative)和命令式(Imperative)UI的差异?

    声明式UI(Declarative)和命令式(Imperative)UI的差异? 声明式 这里应该展示一个缩小50%的,旋转180的图片.可以表示为,what should happen. 命令式 需 ...

  5. 声明式和命令式编程_命令式与声明式编程

    声明式和命令式编程 At this point you've undoubtedly heard about imperative programming vs declarative program ...

  6. 功能性,声明式和命令式编程[关闭]

    功能,声明和命令式编程这两个术语是什么意思? #1楼 命令式 - 表达式描述要执行的动作序列(关联) 声明性 - 表达式是有助于程序行为的声明(关联,交换,幂等,单调) 功能 -词汇具有值作为唯一的影 ...

  7. java 函数式编程 示例_功能Java示例 第1部分–从命令式到声明式

    java 函数式编程 示例 功能编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数. 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么? 在这个名为&qu ...

  8. 功能Java示例 第1部分–从命令式到声明式

    函数式编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数. 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么? 在这个名为" Functiona ...

  9. 理解JS中的声明式与命令式

    理解JS中的声明式与命令式? 声明式编程 :告诉机器你想要的是什么    让机器想出去做 优缺点 : 声明式减少了可变量(Immutable Variable)的声明,程序更为安全,   代码更加简洁 ...

最新文章

  1. tf.keras.losses.SquaredHinge 损失函数 示例
  2. Dubbo负载均衡原理
  3. 使用ajax预加载图片
  4. python核心理念_《Python核心技术第二版》笔记
  5. python msi installer_Windows10 MYSQL Installer 安装(mysql-installer-community-5.7.19.0.msi)
  6. 数字图像处理与分析_第一章
  7. lu分解法c语言编程,LU分解法(C语言).doc
  8. Oracle物化视图的刷新
  9. CenOS7 搭建无人值守安装服务器
  10. 区块链 入门 基础知识
  11. java mars2_Mars-java 2.2.2 发布,不需要容器的 Java Web 开发框架
  12. 4g运行内存手机还能用多久_8G运存手机可用运存不到4G,这到底是为什么呢?告诉你根本原因...
  13. 虚幻4引擎2d游戏基础
  14. 语句的认识,选择语句和循环语句(2022.11.13)
  15. probably,possibly,may的用法区别是什么呀
  16. 用c语言编写rfid读卡系统,USB免驱RFID读写器编程解析之一:智能卡篇
  17. t-learning 产品经理课程笔记
  18. COMPAQ CQ36 拆解全纪实
  19. 爬山法和模拟退火算法求解选址问题
  20. 欧姆龙温控器参数笔记(三)(操作菜单)

热门文章

  1. 进军微信第一步:接入微信JS-SDK
  2. 脊柱、脊髓损伤应该怎么去有效的去预防?
  3. 安装了增强扩展包,虚拟机鼠标还是不能自动切换
  4. 百度地图通过具体位置定位
  5. navicat怎么查看数据库的url_Navicat使用HTTP通道连接MySQL
  6. 阿里云是做什么的呢?
  7. Google Earth Engine(python)——SRTM 生成坡度高程数据
  8. SRTM数据提取(使用Python语言)
  9. 奇数阶魔方阵(洛书)
  10. IEC104 模拟器使用教程