Posted on in 泛函
前几天一个朋友向我抱怨,说Scala语言太晦涩了,他实在不明白为什么这么晦涩的语言反而被誉为具有更好的表达能力呢?我想就此解释一下。 我们要评价任何一个东西好或者坏,首先都必须先确定一个标准,评价一门编程语言也是一样,那应该如何确定一门语言的评价标准呢?它的语法算不算?通过语法来评价恐怕是许多人的第一反应,因为这个我们最熟悉,但是语法恰好不能作为评判标准的。除非是领域专有语言,否则不同的(同代)通用语言在逻辑表达上基本都大同小异,所谓“晦涩不晦涩”主要是因不同的人的习惯而言,就好比中文和英文,你觉得哪个更晦涩?熟悉中文的人认为中文的表达能力胜过英文,而熟悉英文的人则相反;同样,熟悉Word的人恐怕认为任何编程语言的表达能力都是垃圾,但是程序员则认为Word文档才是多余,所以“语法”这个东西,只要是同代编程语言,用于相同的目的,我们是不能通过主观来评价他们的表达力的,这难免会出现先入为主的偏差。 那么语法不是评判的标准,那么什么才是呢?应该是看它对业务的“持续追踪”能力。我们知道当我们使用一门语言来编程的时候,我们的最终目的是要尽可能完美地实现我们想表达的业务,这是最核心的问题,但是问题是我们在编写代码的过程中很难做到总是围绕这个核心来进行,因为我们不得不不断地跳出业务的正常框架,而去处理一些周边问题,比如处理异常问题,比如约束输入信息的格式,还有比如打印日志等等。所有的这些与正常业务有关联,但是又偏离业务主线的事情我们也需要通过代码来管理。编程语言究竟能够在多大程度上帮组我们将精力尽量聚焦在业务的主线表达上,这才是评价一门语言优劣最重要的标准。放在业务主线上的代码越连贯,业务的表达也就会越清晰,焦点问题也就越能得到有效梳理,这门语言它的表达力也就越强。 在泛函编程中有一个很重要的概念叫 effect,所谓“effect”也就是对核心问题的有效解答,effect 的一个特点就是尽可能地避免那些可能导致偏离主线的事情发生,尽可能地围绕核心业务逻辑,所谓核心业务逻辑就是业务正常状态下才应该发生的事情。当我们在用泛函语言编程的时候,我们要尽可能地在主线上串联 effect,相对于effect 而言其它的问题也就是 side effect(副作用),side effect 则要尽一切手段推送到程序的“边缘”去处理。 如果直接这么说很抽象的话,我们来做个类比。假设在现实生活中我们正在去银行开设一个账户,开设账户的过程需要经过,首先要出示证件,然后填写表格,柜台业务人员录入电脑,经主管审核确认……等等一系列操作。正常的开户流程肯定不应该聚焦在诸如证件丢失、表格缺页、电脑掉电、主管恰好上厕所……等等“异常”状态上,这就是 effect 和 side effect的区别,很显然我们不能忽略副作用的存在,正常的业务流程虽然不聚焦在这些问题上,但是对这些问题的发生是不可避免的,问题是当他们发生的时候都应该有相应的处理机制。我们不可能在正常的开户过程中要求主管先去上个厕所以免需要他确认的时候他不在的情况发生,但是在编程中这样的要求就的的确确不是开玩笑。所以理解了这个问题,我们回来比较Scala语言和Java的优劣就高下立判了。 传统编程语言的 effect 和 side effect 总是纠缠在一起的,甚至side fffect 的范围有时候比effect 的范围更广(排除了一切不正确后才能得到正确的结果)。而泛函语言则通过选择恰当的 “容器”将副作用尽可能地延迟到 the end of the world才发生,这样也就尽可能地将舞台的中心留给了正常的业务主线。也得益于“容器”概念的使用,Scala语言甚至具有构造DSL语言的能力,让我们能够更有效的表达专业术语,让表达能力更进一步。这就是为什么我们说泛函语言在业务的表达能力上强于传统编程语言的原因。