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上。
(未完待续)