2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 声明式(declarative) vs 命令式(imperative)

声明式(declarative) vs 命令式(imperative)

时间:2019-06-02 12:44:06

相关推荐

声明式(declarative) vs 命令式(imperative)

声明式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 gLEFT 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)实现类似的功能。

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

小结

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

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

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

参考

/ React 的设计理念:Declarative view

《Design Data-Intensive Applications》第二章,说明 CSS/XSL 是声明式的语言

未来属于声明式编程 对声明式编程语言的思考

命令式和声明式,哪个才是你的菜 描述了声明式、命令式的一些差别

引用

[1] /wiki/Declarative_programming

[2] /wiki/Imperative_programming

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。