我并没有去专门为了Lisp使用前缀表达式而去网上寻找鼓吹有关此方面的文章或书籍。我也并不是Lisp的狂热爱好者。学习Lisp最初只不过是学习其伟大思想。 不过当我慢慢学过Lisp一段时间之后,我慢慢的发自内心的喜欢上了它。我用的是Scheme,一个教学用的语言。当然对于其使用的前缀表达式我也想说一下我自己的认识。
先说一点:前缀表达式也可以叫波兰式,后缀表达式也可以叫逆波兰式。
上过数据结构课,我们都知道前缀、中缀和后缀表达式分别对应的表达式树的先序、中序和后续遍历。也就是说前缀、中缀和后缀表达式这三者可以互相转换的。
比如:
- 中缀:1 + 2 + (3 + 4) * 5 + 6 + 7
- 后缀:1 2 + 3 4 + 5 * + 6 + 7 +
- 前缀:+ + + + 1 2 * + 3 4 5 6 7
很多人是很不适应甚至反感前缀表达式的,因为很不习惯,我们从小学习数学,学习基本的四则运算,好像数学都是用的中缀表达式。真的是这样子吗!
其实不是的,在四则运算加减乘除以外的世界,其实都是用的前缀表达式,举个例子,比如根号√4,这是在数学再常见不过的求根表达式了。它就是一个前缀表达式。 根号在最前面。当然根号是个一元运算符,根号里面的被视为一个整体,对整体求值。
在举一个例子,比如令许多人头疼的积分∫。它也是前缀表达式,积分符号∫在各个参数的最前面。
现在看来,数学书上就是在用前缀表达式,大家也都可以适应,为什么到了编程中就不怎么适应了……
当然更坑爹的是逆波兰式:比如Pascal中定义变量var x : real; 或者近来的年度语言Golang的定义变量var x float。(顺便说一句,之前看过王垠的博客,它也不喜欢go的这种定义变量方法) 大家习惯的是比如double x;这样子的定义变量方法。
当然有些时候,在处理二元关系的时候,无论是波兰式还是逆波兰式都没有中缀表达式好理解。就比如我们的四则运算,只不过是把加减乘除当作了特殊的运算法。 也就是只能处理二元关系的运算符(这里的是减号而不是负号–一元运算符)。
除此之外呢,比如函数f(x . y),这个样子写是表示函数f中可以有多个参数。也就是C语言中的f(int… a)可变参数。
如果我们把函数f当作是一个运算符,其实它可以是运算符或者是它就是运算符,因为它处理了参数。函数就是一个采用前缀的表达方法。
因为如果你不用前缀你怎么写出表达式呢?比如要定义x,y,z这三个参数的和的函数,sum(x, y, z),如果用中缀你如何写出表达式呢? (x sum y) sum z 这个样子吗?这个样子好像也停坑爹的。也就是说前缀可以支持任意多的参数,而中缀只能支持两个。因为到了多元关系之后,中缀几乎不存在 这样的表示方法,根本没有可比较的对象。
所以当处理非二元关系的时候,前缀表达式还是有一些优越的。另一点,如果这个operator的名字比较长,放在前面会好看一些。(窃喜
当然使用前缀表达式可以与函数表示方法相统一。这个样子,就可以使得很多事情变得和谐,统一。
说了这些,其实前缀中缀最大的分歧在于二元关系上,如果二元关系出现的多,那就使用中缀表达式,如果多元关系出现的多那就使用波兰式。