I am a big fan of Stephen Wolfram,but he is definitely one not shy of tooting his own horn.In many references,he pastols Mathematica as a different symbolic programming paradigm.I am not a Mathematica user.
我的问题是:这是什么符号编程?它与函数式语言(如 Haskell)相比如何?
当我听到“符号编程”一词时,LISP,Prolog 和(是的)Mathematica 立即浮现在脑海中。我会将符号编程环境描述为一种环境,其中用于表示程序文本的表达式也恰好是主要的数据结构。结果,在抽象的基础上构建抽象变得非常容易,因为数据可以很容易地转换为代码,反之亦然。
Mathematica 大量利用了这一能力,甚至比 LISP 和 Prolog(IMHO)还要多。
作为符号编程的示例,请考虑以下事件序列。我有一个 CSV 文件,如下所示:
r,1,2
g,3,4
我读了该文件:
Import["somefile.csv"]
--> {{r,1,2},{g,3,4}}
结果数据还是代码?两者都是。它是读取文件产生的数据,但它也恰好是构造该数据的表达式。然而,随着代码的发展,这个表达式是惰性的,因为评估它的结果只是它本身。
所以现在我对结果应用转换:
% /. {c_, x_, y_} :> {c, Disk[{x, y}]}
--> {{r,Disk[{1,2}]},{g,Disk[{3,4}]}}
在不考虑细节的情况下,所有发生的事情都是Disk[{...}]
被包裹在每个输入行的最后两个数字周围。结果仍然是数据 / 代码,但仍然是惰性的。另一个转换:
% /. {"r" -> Red, "g" -> Green}
--> {{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}
是的,仍然是惰性的。然而,由于一个惊人的巧合,这最后一个结果恰好是 Mathematica 内置的特定于领域的图形语言中的有效指令列表。最后一个转换,事情开始发生:
% /. x_ :> Graphics[x]
--> Graphics[{{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}]
实际上,您不会看到最后的结果。在史诗般的语法糖展示中,Mathematica 会显示这张红色和绿色圆圈的图片:
但是乐趣不止于此。在所有语法糖的,我们仍然有一个象征性的表达。我可以应用另一个转换规则:
% /. Red -> Black
快点。红色圆圈变成了黑色。
正是这种“符号推送”表征了符号编程。绝大多数 Mathematica 编程都具有这种性质。
功能性与象征性
我不会详细讨论符号和函数式编程之间的区别,但我将提供一些评论。
可以将符号编程视为以下问题的答案:“如果我尝试仅使用表达式转换对所有内容进行建模,会发生什么?”相比之下,功能编程可以看作是以下问题的答案:“如果我尝试仅使用函数对所有内容进行建模,将会发生什么?”就像符号编程一样,函数编程使快速构建抽象函数层变得容易。我在这里给出的示例可以很容易地在 Haskell 中重现,例如,使用有关函数的
Mathematica 显然针对符号编程进行了优化。可以以函数式编写代码,但是 Mathematica 中的功能特性实际上只是一个薄薄的转换(以及一个泄漏的抽象,请参见的脚注)。
Haskell 显然针对函数式编程进行了优化,可以用符号风格编写代码,但我会怀疑程序和数据的语法表示是完全不同的,这使得体验不是最优的。
结束语
总之,我主张函数式编程(由 Haskell 概括)和符号式编程(由 Mathematica 概括)之间是有区别的。我认为,如果一个人同时研究两者,那么一个人将学到的东西远远超过仅仅研究一个-对独特性的最终检验。
Mathematica 中的漏函数抽象?
是的,漏水。试试这个,例如:
f[x_] := g[Function[a, x]];
g[fn_] := Module[{h}, h[a_] := fn[a]; h[0]];
f[999]
向 WRI 报告并确认。响应:避免使用Function[var, body]
(Function[body]
可以)。
您可以将 Mathematica 的符号编程视为一个搜索和替换系统,您可以通过指定搜索和替换规则进行编程。
例如,您可以指定以下规则
area := Pi*radius^2;
下次使用area
时,它将替换为Pi*radius^2
。现在,假设您定义新规则
radius:=5
现在,每当您使用radius
时,它将被重写为5
。如果您评估area
,它将被重写为Pi*radius^2
,这将触发radius
的重写规则,并且您将获得Pi*5^2
作为中间结果。此新表单将触发内置的重写规则。
您可以通过使用替换规则作为函数来模拟函数编程。例如,如果要定义一个添加的函数,则可以执行
add[a_,b_]:=a+b
现在add[x,y]
被重写为x+y
。如果您想添加仅适用于数字 a,b,则可以改为
add[a_?NumericQ, b_?NumericQ] := a + b
现在,add[2,3]
使用您的规则重写为2+3
,然后使用+
的内置规则重写为5
,而add[test1,test2]
保持不变。
是一个交互式替换规则的示例
a := ChoiceDialog["Pick one", {1, 2, 3, 4}]
a+1
在这里,a
被替换为ChoiceDialog
,然后被替换为用户在弹出的对话框中选择的数字,这使得数量都是数字并触发了+
的替换规则。
可以使用条件定义规则,这些条件本身需要经过规则重写才能产生True
或False
。例如,假设您发明了一种新的方程式求解方法,但您认为它仅在方法的最终结果为正时才有效。您可以执行以下规则
solve[x + 5 == b_] := (result = b - 5; result /; result > 0)
在这里,solve[x+5==20]
被替换为 15,但solve[x + 5 == -20]
不变,因为没有适用的规则。阻止此规则应用的条件是/;result>0
。评估器本质上查看规则应用程序的潜在输出以决定是否继续使用它。
Mathematica 的评估者贪婪地使用适用于该符号的规则之一重写每个模式。有时您希望有更好的控制,在这种情况下,您可以定义自己的规则并像这样手动应用它们
myrules={area->Pi radius^2,radius->5}
area//.myrules
这将应用myrules
中定义的规则,直到结果停止更改。这与默认的计算器非常相似,但是现在您可以有几组规则并有选择地应用它们。更高级的example显示了如何创建一个类似 Prolog 的计算器来搜索规则应用程序序列。
当您需要使用 Mathematica 的默认评估器(使用Integrate
,Solve
等)时,当前 Mathematica 版本的一个缺点出现了和想要更改评估的默认顺序。这是可能的,但是complicated,我想认为符号编程的某些未来实现将具有更优雅的控制评估序列的方式
正如其他人已经提到的那样,Mathematica 进行了很多术语重写。也许 Haskell 不是最好的比较,但是Pure是一种很好的功能术语重写语言(对于具有 Haskell 背景的人来说应该很熟悉)。也许阅读有关术语重写的 Wiki 页面会为您清除一些东西:
http://code.google.com/p/pure-lang/wiki/RewritingMathematica 大量使用术语重写。该语言为各种形式的重写提供了特殊的语法,为规则和策略提供了特殊的支持。范式不是那么“新”,当然也不是唯一的,但是与 Axiom 等其他强大的参与者一样,它们绝对处于这种“符号编程”事物的最前沿。
至于与 Haskell 的比较,好吧,你可以在那里重写,从报废你的样板库得到一些帮助,但它并不像动态类型的 Mathematica 那么容易。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(80条)