Mathematica? 这厮不是Lisp家那痞子吗!

Mathematica?

这厮不是Lisp家那痞子吗!

最初是在数模课上介绍符号运算时知道Mathematica的。那时我还不知道她是Lisp家的小崽子,只是很好奇她是怎么做公式化简的。据说她有一个求解引擎和一麻袋变换规则,求解引擎不断地尝试各种规则,直到结构不变为止。除此之外,我对Mathematica并没多大兴趣,因为听人说Matlab才是业界的首选。现在看来,他俩之间的差别就如同C和Lisp。

后来在抽象代数课上,毛老大把群和面向对象做了一番类比。我突然想,有没有一门基于序对的编程语言呢?(后面当然不了了之了)后来发现,那不就是Lisp吗?!但这也是很久以后了,因为虽然很早就知道Lisp,但一直被灌输这样的观点:

Lisp是为人工智能而生的;

它是用链表搭建的,你看他的名字就叫“链表处理”(LISt Processor);

因为链表很适合做符号处理。

MD,链表怎么适合做符号处理了(参看徐宥的《LISP 语言是怎么来的–LISP 和 AI 的青梅竹马 A B》)?Lisp哪是用链表搭建的了?Lisp的“Lis”是代表的“list”,是序列,不是列表,更不是链表好不!序列和链表,一个数学概念,一个物理实现,两者天差地别好不!

而那时,我对Mathematica的印象非常不好:一门由函数堆起来的铜臭语言。直到我在Project Euler上看到那些精妙的Mathematica解法(之前我觉得最顺手的是Ruby),然后亲自实践,这才感受到他的气场。她就好像百依百顺的贤妻良母,不会像Ms. C那样稍有不顺就雷霆大怒,搅得你肝儿疼。

按理说,Lisp家出来的应该都是一身素颜,不做过多的粉饰(语法糖,Common Lisp那货除外)。但Mathematica不同,打扮得流里流气的,光调用函数就有四种写法:

形  式 示  例
标准形式 foo[x, y]
前缀形式 foo@x
中缀形式 x~foo~y
后缀形式 x//foo

Note

前缀和后缀形式好像都只能带一个参数。前缀形式还好,若想带多个参数,可以用Apply:Apply[f, {x, y}] 等价于f@@{x, y},即f[x, y]。后缀好像就没办法了。

这还不说她那上万号小弟(内置函数,具体多少我还真没查到,不过据说一万页写不完),数据结构也不下十种(List({...}), String("..."), Integer, Rational, Real, Array, Table, Tensors, Vectors, Matrices, ……还不算那些专业领域的。好吧,其实也就List, Number, String三种。可能吧。但翻开Mathematica的各色书籍,很难找到专门一章讲数据结构的,原因就是其实她只有序列这一种数据结构。)。可这只是她另类的外表,其实她有颗Lisbeth(龙纹身那女孩)的心。

外人可能盛赞Mac OS的华丽,但真正吸引果粉的却是它的表里如一。套用赞美Nobel那句话,Mac OS是所有带命令行的图形终端里最华丽的,也是所有图形界面里命令行支持最完整的。这就是使用Mathematica的感觉。她所有的一切都会被转换成一种统一的格式——表达式(expressions)。你可以用FullForm()来查看:

表达式 内部格式
x+y+z Plus[x,y,z]
xyz Times[x,y,z]
x^n Power[x,n]
{a,b,c} List[a,b,c]
a->b Rule[a,b]
a=b Set[a,b]

虽说它名字叫表达式,但其实不就是S-表达式(symbolic expression)么。你看,这可是Mathematica老东家自己写的The Meaning of Expressions。

同一,这可能就是Mathematica强大的原因。说到同一,就不得不说说函数式编程的一大特征:函数与其他数据类型一样平等,即俗称的函数是一等公民。比如,我可以函数赋值给一个变量:

s = Sin

然后就可以通过变量s来实际调用Sin()。
我甚至可以像字符串那样摆弄函数名:

In[1]   :=  h[x + h[y]] /. h[u_] -> u^2
Out[1] :=   (x + h[y])^2

Note

expr/.lhs->rhs 的意思是将lhs->rhs 这条规则应用到expr上。

(未完待续)

你可能感兴趣的