正在阅读:智能合约与函数式编程语言智能合约与函数式编程语言

2018-07-11 17:32 出处:其他 作者:佚名 责任编辑:liukaiping

最近以太坊不是很太平,爆出利用钱包和多重签名合约漏洞盗取资金的问题,这让我想起了久违了的函数式编程语言,相比现在流行的过程式语言可能在智能合约编码上具有先天优势

最近的以太坊漏洞现在有文章做了仔细的分析,纠其根本是基于图灵机的过程式语言与人类逻辑思维冲突的问题,今天就来聊聊函数式编程语言,这个非常古老可能未来会大热的编程语言体系。

什么是函数式编程语言

首先,我们要明确函数式编程语言和函数式编程的区别,函数式编程是近来过程式语言吸收函数式编程语言的优点形成的一种编程风格,通过框架定义形成的类似函数式编程语言的风格,使得过程式语言(包括面向对象语言)具备某些函数式语言的特征,其核心还是过程式语言。

在计算机编程王国里面有两个重要语言,一个是C,一个是LISP,都是非常古老的语言。C语言相信大家都不陌生,C语言影响了后来很多语言的发展,包括C++,JAVA,C#,javascritp都可以看做是类C语言的延伸;LISP语言可能很多人就比较陌生了,计算机专业的学生可能听说过,由LISP派生出的方言,比较有代表性的有CL,Scheme,包括受到LISP语言影响的Haskell,Erlang等(Erlang由于分布式应用,前几年大热),可以这样说C和LISP代表了计算机语言的两个流派,过程式(也称为命令式)语言和函数式语言。

这两个流派的形成要从解决问题的思路说起,我们都知道现在的计算机体系是冯诺依曼结构(存储转发结构),冯式结构本身就受到图灵机的启发,所以图灵机非常适合操作这个结构,强调通过有限集合解决机器的问题;而另一个分支是兰帕德范式(Lambda),强调直接从解决数学问题入手;于是计算机语言王国诞生了基于图灵机的过程式语言包括后来发展成为面向对象语言,而基于Lambda范式诞生的就是函数式编程语言。我查到的资料说图灵机和拉帕德表达式可以相互推导,在逻辑上证明是一致的,所以他们都可以操作冯诺依曼结构的计算机体系。(具体证明过程没有看到,估计也很难看懂)

总体来说函数式编程语言是一种编程范式,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。

函数式语言的优缺点

其实过程式语言和函数式语言的优缺点必须放在一定场景下才能准确分出其优缺点,就主观支持者而言,估计吵100年也难分高下;在资深码农世界存在各种鄙视链,每种语言都有其铁粉,我有一个朋友在学习了Erlang语言后曾经大骂oop(面向对象)耽误他的技术生命,所以为了避免无谓的争吵,本文重点强调在区块链智能合约应用场景下函数式语言的优点。

可能有人要问函数式语言作为一个古老的编程范式,为什么以前很少听说,其实了解计算机的发展就知道,软件的发展一直受制于硬件的发展,过程式语言来自最原始的图灵机模型(读、写、跳转这样操作),而函数式语言来自 Lambda 函数(符号替换、规约等操作),过程式语言较函数式语言在性能上有先天优势,所以在硬件能力比较落后的70~80年代,过程式语言的优势明显所以,以C为代表的语言得到了充分的发展,同时也影响了后期面向对象语言的发展,大学基本上都开设过程式语言的课程,所以大多数人只知道过程式语言,解决问题思路也一直受过程式语言的影响。

但是随着多线程、分布式计算的发展,过程式语言复杂的上下文逻辑,线程安全不能得到很好的保证,并行计算开发难度直线上升,于是人们开始从头找回函数式编程语言,函数式语言变量只与值有关,与物理存储地址无关。变量与值环境一一对应,这一性质就消除了程序与机器结构的相关性,使得程序员在进行编程的时候无需考虑计算的操作行为、计算机的状态变化。只要按照有关语言的语法,用数学或逻辑的方法给出问题的描述和目标即可求解,每一行代码都可以是一个独立的函数,输入输出清晰,非常适合多线程和并行计算,同时函数式语言更符合人类的思维习惯,在高可靠性场景中,代码更容易阅读和查错,代码运行稳定(Erlang语言就是代表,最早是70年代爱立信开发的交换机语言),所以这些年人们开始重新研究和发展函数式语言,包括近几年流行的函数式编程风格。

函数式语言的优点

在函数式语言中,由于数据全部都是不可变的,所以没有并发编程的问题,是多线程安全的。可以有效降低程序运行中所产生的副作用,对于快速迭代的项目来说,函数式编程可以实现函数与函数之间的热切换而不用担心数据的问题,因为它是以函数作为最小单位的,只要函数与函数之间的关系正确即可保证结果的正确性。

函数式语言的表达方式更加符合人类日常生活中的语法,代码可读性更强。实现同样的功能函数式编程所需要的代码比面向对象编程要少很多,代码更加简洁明晰。函数式编程广泛运用于科学研究中,因为在科研中对于代码的工程化要求比较低,写起来更加简单,所以使用函数式编程开发的速度比用面向对象要高很多,如果是对开发速度要求较高但是对运行资源要求较低同时对速度要求较低的场景下使用函数式会更加高效。

函数式语言的缺点

由于所有的数据都是不可变的,所以所有的变量在程序运行期间都是一直存在的,非常占用运行资源。同时由于函数式的先天性设计导致性能一直不够。虽然现代的函数式编程语言使用了很多技巧比如惰性计算等来优化运行速度,但是始终无法与过程式语言程序相比。

函数式编程虽然已经诞生了很多年,但是至今为止在工程上想要大规模使用函数式编程仍然有很多待解决的问题,尤其是对于规模比较大的工程而言。如果对函数式编程的理解不够深刻就会导致跟面相对象一样晦涩难懂的局面。

智能合约采用函数式语言的优势

目前以以太坊为代表的区块链智能合约中有两种主要开发语言,

Solidity (类JavaScript 语言)和LLL(类Lisp语言),Solidity和LLL分别代表了过程式语言和函数式编程语言,前文已经谈到了函数式编程语言的优势,由于智能合约大多不是非常复杂的编程,不属于大型工程,执行效率要求不那么极端,但要求很高的可靠性和可读性,因为一旦合约部署直接影响到各方利益,同时合约需要经过利益相关方审计,符合人类思维习惯,直接面向解决问题的函数式语言更加合适。

智能合约使用函数式语言还有一个优点就是避免造成逻辑歧义,这好比日常的合同,同一段文字表达可能形成两种完全不同的解释,如果未来诞生智能合约律师的话,第三方审计将更容易,可以有效避免逻辑陷阱(比如国外的口是心非C语言编程大赛),用C语言的指针调用和跳转可以轻易构造一个逻辑陷阱,这次以太坊合约问题也是因为代码逻辑bug被人抓住形成攻击。

而且兰帕德数学表达式可读性高,比如在数学计算中(智能合约计算各方利益场景)不必考虑常见的先乘除后加减运算法则,造成不必要的损失,经过简单学习就能够看懂Lambda表达式,下面举个例子:

计算某人一年中每天应该取得的利息和本金合计常用公式为:

(A+A*5%)/365

在过程式语言中如果括号异位写成 (A+A*5%/365)就赚大发了,而在函数式语言中采用Lambda表达式就很容易识别出来

(/ (+ A (* A 0.05))365)

Lambad表达永远都是从最内层开始计算,括号成对出现,不必考虑乘除和加减先后的运算法则,当一个公式非常复杂时,有经验的编程人员可以很轻易构造运算陷阱,有些逻辑bug需要在运行时才会发现(有经验的程序员都知道逻辑bug的查错难度),这种问题在普通应用中不是问题,但是对于区块链智能合约来说,一旦部署就会造成难以估量的损失,所以本人认为在智能合约上推广函数式编程语言是非常必要的。

相关文章

关注我们

最新资讯离线随时看 聊天吐槽赢奖品