者|何婧誉
编辑|小智
编程语言的圣战,除了语言种类之分,也有动静门派之别。我们写着静态语言往往想着动态语言的灵活,写着动态语言又容易想着静态语言的稳定和可靠。常听到有人说,Clojure 确实优美,但动态语言实在驾驭不了,怎么办?
注:本文整理自 Morgan Stanley VP 何婧誉在 QCon 2017 北京站上的演讲,原题为:《属兔的处子——喜欢 Clojure,但怕动态语言太灵活怎么办》。
写在前面
古话说的好,静若处子,动若脱兔。这个我觉得非常适合形容动静态语言的区别,静态语言因为类型系统的关系,一直给人的是很稳定、很可靠,但是可靠到一定程度就变成了死板,会变成一个牢狱或者困住业务上所需的灵活性,因此常常需要很多层抽象,很多层胶水代码,代码就开始变得非常的晦涩,非常的难懂,而动态语言则完全是相反的。
常听到有人说,Clojure 确实优美,但动态语言实在驾驭不了啊!没有类型的帮助,在涉及到复杂的数据结构之后很容易失去对现有程序的理解,易读性也会急速下降,而这也确实是 Clojure 作为动态语言所造成的问题。但是部分解决这个问题的办法总是有的。core.typed 和 core.spec 两个核心库就可以帮助我们缓解动态语言太过野性框不住的问题,而本次演讲的任务就是向大家介绍这两个库,以及这两个库解决这一问题的不同角度。
静态语言 VS 动态语言
静态语言因为类型系统的关系,一直给人的是很稳定、很可靠,但是可靠到一定程度就变成了死板,会变成一个牢狱或者困住业务上所需的灵活性,因此常常需要很多层抽象,很多层胶水代码,代码就开始变得非常的晦涩,非常的难懂。动态语言则完全是相反的,所有东西都是从类型上来讲,以函数为例,灵活性已经足够了,但是通常我们写着写着就忘记数据长什么样子了,你可能今天写了一个函数说,输入一个函数的数据,然后过了一个星期之后,我已经完全忘记这个数据是什么东西了,因为生产环境里面,类型系统在没有编译器的帮助下,基本上都是一次性的,这个问题对于用户来说有相当大的困扰。
一直以来,这两派之间没有争出特别的高低,静态语言笑动态语言做不出大系统,动态语言笑静态语言写的太慢、废话太多,今天这个主题当然不可能解决这个纷争,但是希望通过 Clojure 这个语言可以给大家一些不太为人知的思路。马上就有人来问了,我写 Clojure 就是为了逃避这样的内容来写系统,这样灵活多好用啊,我想写什么就写什么,快速原型靠的就是这个,我非常同意这一点。
简单示例
在 Clojure 里面有一个 json,因为动态语言的关系相当的简单,完全没有废话。这个函数我觉得哪怕是不写 Clojure 的,这个也是应该很能读的懂的。首先有一个 Java 的 Reader,是 FileReader,这个 Reader 被传递到了这个 json 的函数里面,读出来文件内容,读到 Map 里面,但是读完之后,你知道数据长什么样吗?不知道,下次换一个 json 文件,同样的函数可以同样读,但是你不知道读出来是什么东西。讲到这里就已经有一点难度在里面了。
现在看一下,我现在读完了要处理,我处理之后,我写任意一个函数,如果说你不看这个函数写的什么东西,你知道它处理完成之后长什么样吗?不知道,你知道他希望这个 json 数据是什么样的形状吗?不知道。我现在看了代码之后,可以给你讲,它里面会有会有 Age、Name、Job、Address。
看一下 Age,它需要能够使用 Int,那应该是个整数,但是要看代码才知道,再下面还是简单,那你们觉得 Name 的值是什么东西?完全没有使用到,它是一个 String,它是不是姓和名放在一起了?还是放在一个 Vector 里面,可能姓和名是分开的,就是说不知道,要看代码才知道。
你看到代码之后觉得,原来是这样,它应该是一个 Vector,或者是 List,姓和名是分开放,因为它这系,它用空格来 Join 一下,这个是一个很浅显的例子,就已经说明了 Clojure 的动态灵活性非常强,但是也造成对数据的解释性标记不是很清楚。
前文是一个很浅显的例子,现在来看一个更具体的。为了这个主题我想了好几天,觉得还是写一个很小的项目来展示一下要讲的东西。那写什么东西呢?我又想了好几天,在此先谢谢链家。因为是这样的,既然要来北京,就要关注一下房价。我到网上去看二手房信息,但一页页翻过去很累,我不可能手写一个总结,于是就写点程序抓取。当然这里不是真的写了一个爬虫,只是抓几个页面做做样子,没有让链家服务受到伤害,请鸟哥放心。
命名空间做的基本上就是通过一个库把 html 读进来之后,进行一些简单的操作,把整理好的数据写到一个 EDN 文件里边。比如说第一条你可以看到这个小区 1150 万,三卧室两个客厅,一个厨房两个卫生间,包括面积之类的东西。再看这个数据转换的函数,它收到一个参数是 Page,但这个 Page 长什么样完全不知道。我是通过库读进来的,读进来之后,并不知道它长什么样子,现在看这个代码也很难知道,它到底会返回一个什么样的类型,什么样的数据,如果将来需要扩展的话,或者将来我要给另外一个人用,或者帮助另外的一个人去做一些扩展,做一些维护很难搞定。
这就是前文说的 Clojure 作为一个动态语言的弊端——太灵活。这个弊端导致经常会忘记函数的参数是什么样子,而且这个是小项目,项目一大,那就更麻烦。可能有人会说的,文档不就是做这个事情的吗?文档跟测试,没有紧密的联合在一起,文档本身的代码是剥离的,而相对代码本身是没有限制的。比如说很多代码上面会写,但是其实代码里面并没有,它可能起到的效果某种程度上也是挺有限的。
Core.typed
Core.typed 是一个类型系统。它和其他语言的类型系统还是有点不一样的地方,不同点在于它不是语言的一部分,而是一个即查即用的库。Lisp 的灵活性导致它能够作为一个库直接插进去,而不是要作为一个语言核心。因为它有宏,通过宏可以把一个很大的类型系统直接插进去,而且这个类型系统比一般的系统要灵活很多,主要体现在这几个方面:
第一,它可以给已经写好的,没有标注过的,或者说是用的库里面没有标注过的函数直接加上类型;
第二,不需要把所有函数全部加上类型,你不想要的话,就不需要;
第三,你即使加上了也不一定要进行类型检查,所以它是一个选择性非常强的东西。它是为了能够和 Clojure 这样的语言进行协作。
那我们现在看一下它支持什么东西:
OptionType,现在很流行,这个流行的语言现在都有这个结构。
Ordered Intersection Type 这个我不多讲了,这个就是说一个函数,比如有两种参数形式,这两种参数类型可能又不一样,你再进行类型检查的时候,它会把这个参数从上到下有序的来进行一个匹配。unionType,写过 Haskell 人都知道,这个很简单,比如说整数,或者说是字符串,把它 union 一下,那就表示这个类型里面的东西可以是字符串,也可以是函数。
Identity 是很简单的函数,它会给你一模一样的东西,那它的类型是什么呢?它这个函数的类型是什么东西呢?让 Core.type 来帮我看一下。这个基本上可以看到前面有个 all,在这里对所有的 X 能取得的类型它返回的是一个 X,就是 Polymorphism 最简单的一个体现了。Occurrence Typing 这个东西见到的比较少,它是什么呢?它是通过检查代码里面写的控制流,比如像 if,或者像 switch,它能够进行类型推导。
举个例子,首先把这个 Form 绑到 A 这个名字上面,值就是 1,但是我把它标注成了 any,就是说这个 A,就算只是 1,然后再返回 A,这里大家觉得会返回什么东西?如果是检查一个类型,它最后返回的是 A,它是什么类型?Any,因为我已经标过了,我说 A 是 Any,所以它就相信 A 是 Any,但是如果我这么写,这个会返回什么东西?你可以看到它现在还是返回的是 A,这个 A 或者这个也是 A,那其他情况返回的是 Nil,那他现在觉得这个东西是什么呢?还是不是 Any,因为你现在有了控制流在这边,代码里已经写过了,所以它知道你只可能是 number,或者是 string,要不然就是 nil,所以最后 A 是 union string/number/nil。这个东西功能上是非常强大的,这个也是我强推的一个东西,这个你真正用起来就知道方便。
最后一个就是宏也会被展开之后再推导类型,宏跟大家刚刚知道的 switch 有点像,就是已经很直接了当的,告诉大家这个宏是可以展开之后判断类型。我做的 Demo 的 types Demo,就是把刚刚链家那个小项目加了类型系统,我现在是把它所制造的结果定义类型,但它其实是什么呢?是一个 Map。
Core.spec 总结
通过一个库给动态语言加上类型系统——即插即用
可以给已经写好的函数或者是用的无类型库标注类型
可以选择性地加上类型
加上了类型也并非一定要 type check
支持 Option Type,Ordered Intersection Types, Union Types
支持 Heterogenous Maps 和 Sequentials
支持 Polymorphism (All, Context Bounds),Higher-Kinds
支持 Occurrence Typing!(通过检查 control flow 进行类型推导)
宏也会被展开后再推导类型
Core.spec
我本人很喜欢写这个,我觉得给函数加上类型非常过瘾,但是有问题,那有别的办法吗?有的,Core.spec,现在这个东西是 Clojure 核心,在很尽力地推广。在方法上或者在函数上,加上先限条件,功能要强大一点,强大在什么地方呢?
比方说生产环境,Runtime 不会受到影响,它的性能不会受到影响。因为如果你一天到晚在检验,它的性能上是会受到影响的,所以缺省验证是关闭掉的,如果你觉得某些东西可能重要性比较大,你要加上去也是可以的。spec 非常灵活,它可以把那种正则方式的 rule 给写起来,就是比如某个 list,我觉得里面开头至少有一个字符串,然后后面跟着的至少是 0 个的整数等等,你就可以用正则里面的加号,星号直接定义这个 rule。并且所有只有一个参数的 predicate 的函数统统可以跟它进行无缝对接,不需要另外语法把它转换成 spec。这里面有很多种的验证方式,那么多的验证的方式可能现在没有时间讲,就不讲了,总体来说就是可以把数据套在一个很灵活的模子里。
Core.spec 总结
Runtime 性能基本不会受到影响(缺省 spec 验证关闭)
Map 的类型应该就是 key 及其对应的值的类型!(keys)
Sequence 可以多方面限制(cat, alt, regex style matching, coll-of)
只有一个参数的返回 boolean 值的函数通通都自动成为 predicate
各种验证方式,满足你的需求 (conform, explain, valid?)
multi-spec 支持更复杂的数据结构
Core.type vs Core.spec
写在最后
core.typed 和 core.spec 你推荐哪个?
我的脑子喜欢 core.spec,因为有前景。我的内心喜欢 core.typed,因为给东西加类型写起来真得很过瘾。
写《程序员修炼之路》的 Andy Hunt 和 David Thomas 大师曾说,要在软件开发这个行当立于不败之地,应该“每年学一种新的语言”。10 月 QCon 上海站上,C++ 之父 Bjarne Stroustrup会分享关于 C++ 语言的发展和未来编程语言格局,还有摩根大通高级程序员赵劼(老赵)、阿里中心主管杨冠宝(孤尽)、PingCAP 首席架构师唐刘、饿了么资深 Android 工程师张涛、沪江资深 Android 工程师何梁伟、Movoto 前端工程师吴名扬等,分享有关 Kotlin、Rust、TypeScript、.Net 的语言实践,也欢迎你到现场和我们交流。
点击【阅读原文】抵达 QCon 全球软件开发大会,学习 2017 你想学习的新语言。如有任何问题可联系购票经理 Hanna ,电话:15110019061,微信:qcon-0410。
何婧誉(Loretta),Morgan Stanley VP。一枚剑桥大学计算机科学系毕业的妹子,兴趣范围从技术、数学、金融到桌游、国标、英文书法、语言学、哲学、钢琴等范围极广,属于样样都知道一些的典型 jack of all trades。技术上主要擅长 JVM 语言,有几年 Java 经验,2010 年遇见 Clojure 之后顿时被其简洁的语法、简单的写法及极具表达力的特性深深吸引,2011 年得以开始专业 Clojure 5 年多,现于大摩写 Scala。主要用 Clojure 做数据流处理,但也曾用其做过网络应用乃至安卓应用。JVM 之外亦与 Python、Perl 等主流语言,以及 ML 等非主流函数语言打过交道。约四年前开始与国内的 Clojure 社区有所接触,业余时间致力于解答 Clojure 相关问题,并希望能将 Clojure 的影响范围继续扩大。
点击下方图片即可阅读
百度正式开源其 RPC 框架 brpc
年我都会关注一下Stack Overflow的开发者调查,因为从中可以观察到一些有趣的东西和业界的趋势, 然后和自己的技能点比较一下,瑟瑟发抖或者心中窃喜一下......
2021年的调查有8万多人参与,主要以欧美+印度为主, 中国程序员参与不多,也许是语言障碍吧。
70%的程序员年龄都在34岁以下,看来“35岁”是全世界程序员的魔咒
毫不意外, 男生占到了90%以上
最常用的编程语言
JavaScript继续问鼎,这已经是连续第九年排名第一了,用JavaScript做开发的人可真多啊!
让我感到意外的是,Go语言排名居然这么低 !难道真是如网上所说,Go语言在中国的火爆程度超越外国?
最常用的数据库
MySQL 依然排在榜首, PostgreSQL紧随其后。
Oracle 怎么这么低?
SQL Sever怎么这么高?应该是微软Azure的功劳吧!
不过,开源软件占据了统治性的地位!
最常用的Web框架
前端框架再次刷榜,别的框架都没有“活路”了!
Spring排名真低!
我怀疑这是因为前端程序员参与调查的人比较多,后来看了看开发人员的类别调查,有近一半的人选了全栈程序员,他们肯定也会选前端框架,于是把前端框架拉高了吧。
最常用的IDE
Visual Studio Code 已经成神, Eric Gamma实在是牛逼,不知道他看到自己一手缔造的Eclipse的排名会是什么感觉。
Visual Studio还是那么强势,从上世纪90年代开始,微软在开发工具上一直挺立潮头。
注意一下Vim ,排名很高
最爱的和最想抛弃的编程语言
这是Stackoverflow调查最有趣的地方。
对于一门语言,如果你今年用了,明年还想用,就被划分到“最爱的” 范畴。
如果你今年用了,但是明年不想用了,就被划分到“最想抛弃的”范畴。
没想到Rust, Clojure, Elixir, Julia 这些小众语言有这么多人热爱,它们身上肯定有与众不同的东西。
大Java有近53%的人想抛弃它,惨!
估计是维护祖传代码受不了了吧!
最想学习的语言
对于一门语言,如果你今年没用,明年想用,就被划分到“最想学习的”范畴。
Python名列榜首, 两个Script紧随其后。
我觉得我也应该写一个Python教程了。
收入最高的编程语言
终于来到激动人心的环节 !
Clojure排名第一, 解决10万美元!想不想学一下?但是估计职位不好找吧。
F#, Elixir, Erlang , Perl , Ruby紧随其后。
这些都不是最常用的编程语言,看来小众语言人才不好找啊。
收入最高的编程框架
Ruby on Rails居然排名第一!
Spring只能排名第9 。
收入最高的职业
收入高的除了管理人员,CXO,还有SRE,DevOps,Data工程师,意外吧?
不知道在中国是不是这样,希望国内也有知名的网站发动一下程序员,做一下类似调查,看看国内的情况如何,如果已经存在了,欢迎留言告诉我。
完整调查结果: https://insights.stackoverflow.com/survey/2021
个好的文本编辑器对于想要建立网站或进行编码的任何人都是必不可少的。这对于习惯于面面俱到的环境的Mac开发人员而言更加明显。对于他们来说存在一系列不同的优质软件之选。今天小编将介绍几款Mac上好用的HTML文本编辑器,对于每一款文本编辑器,小编将对对其中的亮点和不足之处进行了简单的描述。
Atom(免费)
Atom被公认为Mac上最好的免费文本编辑器,以Node.js进行编写,并嵌于GitControl中。它可以作为单纯的Mac文本编辑器使用,也可以作为源代码编辑器来使用。通过插件程序的使用,此应用支持很多语言,如HTML, CSS, C/C++, Objective-C, Java, Go, C#, JavaScript, Python, PHP, Perl, XML, Mustache, Clojure, Ruby等等,使之成为了现代开发人员的有用工具。
其部分有用的功能包括多标签编辑,自动完成,多面板组,一个文件系统浏览器,优秀的导航选项,以及软件包管理器。此外,Atom的一项非常重要的功能在于数以万计的虚拟免费软件包的可用性,其充分增强了它的功能性。
它的用户界面非常友好,同时还提供一系列不同的主题可供用户根据自己的喜好来选择可视化环境。
一般而言,Atom可谓是明智之选,尤其是对于MEAN网页开发人员而言。
Visual Studio(免费)
像Atom一样,Visual Studio Code是一个功能强大的综合应用程序,可以作为HTML编辑器使用。VS Code是一款轻量级的文本和脚本编辑器,以扩展对插件的支持为概念,与Microsoft的功能强大的Visual Studio不会混淆。
有一些插件可用于在Code中编写和运行Shell脚本,编写Markdown文档,甚至编写AppleScript。那就对了; 您可以使用Microsoft的文本编辑器来创建仅在Apple计算机上运行的脚本。
但是轻量级的Visual Studio意味着对插件的依赖,但是它具有响应能力,您不用在意那些永远不会使用的功能。
MacVim (免费)
MacVim是一个将Vim程序员编辑器带入Mac的项目。另一方面,Vim基于强大的Vi应用程序,这是一个为Unix操作系统开发的文本编辑器。除了其他功能之外,MacVim应用程序还支持使用热键,包括全屏模式,允许您使用透明背景等等。
尽管Vim已内置到操作系统中,仍有很多人对MacVim感兴趣。它具有功能完整的菜单栏控件和比Apple维护的Vim更新的版本,对于新手来说,还算友好!
Sublime Text
Sublime Text是一款商业化的Mac文本编辑器。这款编辑器采用了Python应用程序接口(API),并支持多种语言。此外,它的功能性通过插件的形式进一步予以强化,这些插件通常是由社团进行开发的,根据免费软件许可予以开放使用。Sublime Text拥有超级友好的界面,有22种不同的主题可供选择。在其众多有趣功能当中有一项被称为免分心模式,在该模式下,屏幕中心只包含文本。
其他的功能包括建立在简单的JSON文件基础之上的高级定制功能;以及分割编辑,也即编辑能够在两个不同的文件或一个文件的不同部分之间完成。简单来说,它的快速文件和文本行导航,它的跨平台支持,以及以项目为本的参数选择,使得这款应用经常被评为“最佳Mac文本编辑器”。
TextMate
强大,简单且轻巧的TextMate是许多Mac专业人士的首选,不难理解为什么。该编辑器支持多种语言和语法,选项卡以及特定于语言的方法,可以节省您的时间和精力。
TextMate包含摘要,宏和作用域确定功能,可在不逐步进入完整IDE范围的情况下极大地加快工作流程。开发人员旨在将“ Apple的操作系统方法带入文本编辑器世界”,这是为什么这么多人喜欢TextMate的一个很好的总结。
这是一个易于使用的简单工具,界面简洁,价格合理。尽管开发有时会停滞不前,但TextMate仍然坚持不懈地追随专业用户。
它是典型的Mac文本编辑器,与TextWrangler来自同一开发人员。尽管缺少Atom的新鲜度或Sublime Text中清晰的UI,但BBEdit是针对macOS从头开始构建的,针对该平台进行了优化,并采用Mac方式进行文本编辑。
这意味着对于普通的Mac用户来说,键盘快捷键是有意义的,以及遵循Apple的许多设计敏感性的文本编辑方法。它还支持Bonjour等Mac技术。这消除了其他应用程序中出现的一些进入障碍,但导致UI与其竞争对手相比更加笨拙。
BBEdit非常适合HTML和文本编辑,并支持通过FTP / SFTP进行远程编辑。该应用程序高度可定制,从语法着色到菜单选项,用户定义的功能,键盘快捷键以及直接在该应用程序中的macOS终端支持。
什么是最好的HTML文本编辑器?它不一定是功能最多的那个。但一定是最适合您工作方式的那一个。小编建议您在决定之前先进行一些测试,找到最适合自己的那款!
(来自Mac下载macz.com)
*请认真填写需求信息,我们会在24小时内与您取得联系。