Mr.*_*ard 6 syntax wolfram-mathematica notation
我正在使用Notation包在Mathematica中试验语法mod.
我对特定字段的数学符号不感兴趣,而是对通用语法修改和扩展感兴趣,特别是减少Mathematica的VeryLongFunctionNames的冗长,清理笨拙的构造或以令人愉快的方式扩展语言的符号.
一个示例修改是定义Fold[f, x]评估,因为Fold[f, First@x, Rest@x]
这很好,并且非常方便.
另一个是定义*{1,2}评估Sequence @@ {1,2}为受Python启发的; 这在Mathematica中可能有效,也可能无效.
请提供以下信息或链接:
符号和语法修改的限制
实施的提示和技巧
现有的包装,实例或实验
为什么这是一个好主意或坏主意
这不是一个真正有建设性的答案,只是一些想法.首先,免责声明 - 我不建议下面描述的任何方法作为良好实践(可能通常不是),它们只是一些似乎可以解决您的具体问题的可能性.关于所述目标 - 我非常支持这个想法,能够减少冗长度(至少对于个人开发者的个人需求).至于工具:我对Notation包的经验很少,但是,无论是否使用它或编写一些自定义的盒子操作预处理器,我的感觉是输入表达式必须通过Mathematica解析器解析成框的全部事实严重限制了许多可以做的事情.此外,在包装中使用它可能会有困难,正如其他回复中已经提到的那样.
如果会有一些钩子$PreRead,这将是最简单的,这将允许用户拦截输入字符串并在将其提供给解析器之前将其处理为另一个字符串.这将允许人们编写一个在字符串级别上运行的自定义预处理器 - 或者如果您愿意,可以将其称为编译器 - 这将采用您设计的任何语法字符串并从中生成Mathematica代码.我不知道这样的钩子(当然可能是我的无知).缺乏这一点,可以使用例如程序样式单元格,并且可能编程一些按钮,这些按钮从这些单元格读取字符串并调用这样的预处理器来生成Mathematica代码并将其粘贴到原始代码所在的单元格旁边.
如果您想要的语言是一种简单的语言(至少在语法和语法方面),这种预处理器方法最有效,因此很容易进行词法分析和解析.如果你想要Mathematica语言(其完整的语法模数只是你想要改变的一些元素),在这种方法中,你就是运气不好,无论你的变化有多少和"轻量级",你都是d需要重新实现几乎完全Mathematica解析器,只是为了进行这些更改,如果你希望它们可靠地工作.换句话说,我所说的是IMO编写一个预处理器要容易得多,这个预处理器会从一些类似Lisp的语言生成Mathematica代码,语法很少或没有语法,而不是尝试对标准的mma实现一些语法修改.
从技术上讲,编写这样一个预处理器的一种方法是使用Lex(Flex)和Yacc(Bison)等标准工具来定义语法并生成解析器(比如C).这样的解析器可以通过MathLink或LibraryLink(在C的情况下)插回Mathematica.它的最终结果是一个字符串,在解析时,它将成为一个有效的Mathematica表达式.此表达式将表示已解析代码的抽象语法树.例如,像这样的代码(Fold这里介绍了新的语法)
"((1|+|{2,3,4,5}))"
Run Code Online (Sandbox Code Playgroud)
可以解析成类似的东西
"functionCall[fold,{plus,1,{2,3,4,5}}]"
Run Code Online (Sandbox Code Playgroud)
这种预处理器的第二个组件将用Mathematica编写,可能是基于规则的样式,用于从AST生成Mathematica代码.生成的代码必须以某种方式保持不被评估.对于上面的代码,结果可能看起来像
Hold[Fold[Plus,1,{2,3,4,5}]]
Run Code Online (Sandbox Code Playgroud)
如果在Mathematica中可以使用像Lex(Flex)/ Yacc(Bison)这样的工具类似物(我的意思是绑定,这需要只在Mathematica中编写代码,并自动生成C语言解析器,将其重新插入)通过MathLink或LibraryLink到内核.我可能只希望它们在将来的某些版本中可用.缺乏这一点,我所描述的方法需要大量的低级工作(如果您愿意,可以使用C或Java).我认为它仍然可行.如果你可以写C(或Java),你可以尝试做一些相当简单的(在语法/语法方面)语言 - 这可能是一个有趣的项目,并会给出一个更复杂的事情的想法一.我从一个非常基本的计算器示例开始,并且可能将那里的标准算术运算符更改为Mathematica无法正确解析的一些更奇怪的算子,以使其更有趣.为了首先避免MathLink/LibraryLink复杂性并且只是测试,您可以从Mathematica调用生成的可执行文件Run,将代码作为命令行参数之一传递,并将结果写入临时文件,然后将其导入Mathematica.对于计算器示例,整个过程可以在几个小时内完成.
当然,如果您只想缩写某些长函数名称,那么有一个更简单的替代方法 - 您可以使用它With来做到这一点.这是一个实际的例子 - 我的Peter Norvig的拼写纠正器端口,我以这种方式欺骗以减少行数:
Clear[makeCorrector];
makeCorrector[corrector_Symbol, trainingText_String] :=
Module[{model, listOr, keys, words, edits1, train, max, known, knownEdits2},
(* Proxies for some commands - just to play with syntax a bit*)
With[{fn = Function, join = StringJoin, lower = ToLowerCase,
rev = Reverse, smatches = StringCases, seq = Sequence, chars = Characters,
inter = Intersection, dv = DownValues, len = Length, ins = Insert,
flat = Flatten, clr = Clear, rep = ReplacePart, hp = HoldPattern},
(* body *)
listOr = fn[Null, Scan[If[# =!= {}, Return[#]] &, Hold[##]], HoldAll];
keys[hash_] := keys[hash] = Union[Most[dv[hash][[All, 1, 1, 1]]]];
words[text_] := lower[smatches[text, LetterCharacter ..]];
With[{m = model},
train[feats_] := (clr[m]; m[_] = 1; m[#]++ & /@ feats; m)];
With[{nwords = train[words[trainingText]],
alphabet = CharacterRange["a", "z"]},
edits1[word_] := With[{c = chars[word]}, join @@@ Join[
Table[
rep[c, c, #, rev[#]] &@{{i}, {i + 1}}, {i, len[c] - 1}],
Table[Delete[c, i], {i, len[c]}],
flat[Outer[#1[c, ##2] &, {ins[#1, #2, #3 + 1] &, rep},
alphabet, Range[len[c]], 1], 2]]];
max[set_] := Sort[Map[{nwords[#], #} &, set]][[-1, -1]];
known[words_] := inter[words, keys[nwords]]];
knownEdits2[word_] := known[flat[Nest[Map[edits1, #, {-1}] &, word, 2]]];
corrector[word_] := max[listOr[known[{word}], known[edits1[word]],
knownEdits2[word], {word}]];]];
Run Code Online (Sandbox Code Playgroud)
您需要一些训练文本,其中包含大量单词作为字符串作为第二个参数传递,第一个参数是校正器的函数名称.这是Norvig使用的那个:
text = Import["http://norvig.com/big.txt", "Text"];
Run Code Online (Sandbox Code Playgroud)
你说它叫一次
In[7]:= makeCorrector[correct, text]
Run Code Online (Sandbox Code Playgroud)
然后在某些单词上使用它任意次
In[8]:= correct["coputer"] // Timing
Out[8]= {0.125, "computer"}
Run Code Online (Sandbox Code Playgroud)
您可以制作With类似于自定义的控制结构,在这里您可以为一些最烦人的mma名称硬编码短名称,然后将其包裹在您的代码周围(但是您将失去代码突出显示).请注意,我一般不提倡这种方法 - 我这样做只是为了好玩并减少行数.但至少,这是通用的,因为它将以交互方式和包装方式工作.不能做中缀运算符,不能改变优先级等,但几乎为零工作.
不是完整的答案,只是为了展示我在这里学到的一个技巧(我认为与符号重新定义比与表示法更相关):
Unprotect[Fold];
Fold[f_, x_] :=
Block[{$inMsg = True, result},
result = Fold[f, First@x, Rest@x];
result] /; ! TrueQ[$inMsg];
Protect[Fold];
Fold[f, {a, b, c, d}]
(*
--> f[f[f[a, b], c], d]
*)
Run Code Online (Sandbox Code Playgroud)
编辑
感谢@rcollyer 的以下贡献(请参阅下面的评论)。
您可以使用 $inMsg 变量根据需要打开或关闭定义:
$inMsg = False;
Fold[f, {a, b, c, d}]
(*
->f[f[f[a,b],c],d]
*)
$inMsg = True;
Fold[f, {a, b, c, d}]
(*
->Fold::argrx: (Fold called with 2 arguments; 3 arguments are expected.
*)
Fold[f, {a, b, c, d}]
Run Code Online (Sandbox Code Playgroud)
这在测试时非常有价值
| 归档时间: |
|
| 查看次数: |
1411 次 |
| 最近记录: |