Mathematica 符号和语法模块 [英] Mathematica Notation and syntax mods

查看:33
本文介绍了Mathematica 符号和语法模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Notation 包在 Mathematica 中试验语法模块.

I am experimenting with syntax mods in Mathematica, using the Notation package.

我对特定领域的数学符号不感兴趣,但对通用语法修改和扩展感兴趣,尤其是减少 Mathematica 的 VeryLongFunctionNames 冗长、清理笨拙的结构或以令人愉悦的方式扩展语言的符号.

I am not interested in mathematical notation for a specific field, but general purpose syntax modifications and extensions, especially notations that reduce the verbosity of Mathematica's VeryLongFunctionNames, clean up unwieldy constructs, or extend the language in a pleasing way.

一个示例修改是定义 Fold[f, x] 以评估为 Fold[f, First@x, Rest@x]
这很好用,而且很方便.

An example modification is defining Fold[f, x] to evaluate as Fold[f, First@x, Rest@x]
This works well, and is quite convenient.

另一个将定义 *{1,2} 来评估为 Sequence @@ {1,2} 受 Python 启发;这在 Mathematica 中可能有效,也可能无效.

Another would be defining *{1,2} to evaluate as Sequence @@ {1,2} as inspired by Python; this may or may not work in Mathematica.

请提供信息或链接地址:

Please provide information or links addressing:

  • 符号和语法修改的限制

  • Limits of notation and syntax modification

实施技巧和窍门

现有包、示例或实验

为什么这是一个好主意或坏主意

Why this is a good or bad idea

推荐答案

不是一个真正有建设性的答案,只是一些想法.首先,免责声明 - 我不建议将下面描述的任何方法作为良好实践(也许通常不是),它们只是一些似乎可以解决您的特定问题的可能性.关于既定目标 - 我非常支持这个想法,能够减少冗长是很棒的(至少对于独立开发人员的个人需求).至于工具:我对 Notation 包的经验很少,但是,无论是否使用它或编写一些自定义框操作预处理器,我的感觉是输入表达式必须由 Mathematica 解析器解析为框的整个事实严重限制了一些可以做的事情.此外,正如其他回复中已经提到的那样,在包中使用它可能会遇到困难.

Not a really constructive answer, just a couple of thoughts. First, a disclaimer - I don't suggest any of the methods described below as good practices (perhaps generally they are not), they are just some possibilities which seem to address your specific question. Regarding the stated goal - I support the idea very much, being able to reduce verbosity is great (for personal needs of a solo developer, at least). As for the tools: I have very little experience with Notation package, but, whether or not one uses it or writes some custom box-manipulation preprocessor, my feeling is that the whole fact that the input expression must be parsed into boxes by Mathematica parser severely limits a number of things that can be done. Additionally, there will likely be difficulties with using it in packages, as was mentioned in the other reply already.

如果有一些像 $PreRead 这样的钩子,这将是最简单的,它允许用户拦截输入字符串并将其处理成另一个字符串,然后再将其提供给解析器.这将允许人们编写一个在字符串级别上操作的自定义预处理器 - 或者如果您愿意,您可以将其称为编译器 - 它将采用您设计的任何语法的字符串并从中生成 Mathematica 代码.我不知道这样的钩子(当然可能是我的无知).缺少这一点,例如可以使用 program 样式的单元格,或者编写一些按钮,这些按钮从这些单元格中读取字符串并调用此类预处理器来生成 Mathematica 代码并将其粘贴到旁边的单元格中原始代码在哪里.

It would be easiest if there would be some hook like $PreRead, which would allow the user to intercept the input string and process it into another string before it is fed to the parser. That would allow one to write a custom preprocessor which operates on the string level - or you can call it a compiler if you wish - which will take a string of whatever syntax you design and generate Mathematica code from it. I am not aware of such hook (it may be my ignorance of course). Lacking that, one can use for example the program style cells and perhaps program some buttons which read the string from those cells and call such preprocessor to generate the Mathematica code and paste it into the cell next to the one where the original code is.

如果您想要的语言是某种简单的语言(至少在语法和语法方面),那么这种预处理器方法将最有效,以便于词法分析和解析.如果您想要 Mathematica 语言(其完整的语法模只是您想要更改的几个元素),那么在这种方法中,您很不走运,无论您的更改多么少和轻量级",您d 需要几乎完全重新实现 Mathematica 解析器,只是为了进行这些更改,如果您希望它们可靠地工作.换句话说,我想说的是,与尝试对标准 mma 进行一些语法修改相比,IMO 编写一个预处理器更容易从一些类似 Lisp 的语言生成 Mathematica 代码.

Such preprocessor approach would work best if the language you want is some simple language (in terms of its syntax and grammar, at least), so that it is easy to lexically analyze and parse. If you want the Mathematica language (with its full syntax modulo just a few elements that you want to change), in this approach you are out of luck in the sense that, regardless of how few and "lightweight" your changes are, you'd need to re-implement pretty much completely the Mathematica parser, just to make those changes, if you want them to work reliably. In other words, what I am saying is that IMO it is much easier to write a preprocessor that would generate Mathematica code from some Lisp-like language with little or no syntax, than try to implement a few syntactic modifications to otherwise the standard mma.

从技术上讲,编写这种预处理器的一种方法是使用标准工具,如 Lex(Flex) 和 Yacc(Bison) 来定义语法并生成解析器(比如用 C 语言).这样的解析器可以通过 MathLink 或 LibraryLink(在 C 的情况下)插入到 Mathematica.它的最终结果将是一个字符串,解析后将成为有效的 Mathematica 表达式.这个表达式将代表你解析代码的抽象语法树.比如这样的代码(这里引入了Fold的新语法)

Technically, one way to write such a preprocessor is to use standard tools like Lex(Flex) and Yacc(Bison) to define your grammar and generate the parser (say in C). Such parser can be plugged back to Mathematica either through MathLink or LibraryLink (in the case of C). Its end result would be a string, which, when parsed, would become a valid Mathematica expression. This expression would represent the abstract syntax tree of your parsed code. For example, code like this (new syntax for Fold is introduced here)

"((1|+|{2,3,4,5}))"

可以解析成类似

"functionCall[fold,{plus,1,{2,3,4,5}}]"

这种预处理器的第二个组件将用 Mathematica 编写,可能是基于规则的风格,以从 AST 生成 Mathematica 代码.结果代码必须以某种方式保持未评估.对于上面的代码,结果可能看起来像

The second component for such a preprocessor would be written in Mathematica, perhaps in a rule-based style, to generate Mathematica code from the AST. The resulting code must be somehow held unevaluated. For the above code, the result might look like

Hold[Fold[Plus,1,{2,3,4,5}]]

最好在 Mathematica 中提供类似 Lex(Flex)/Yacc(Bison) 之类的工具(我的意思是绑定,这需要一个人只在 Mathematica 中编写代码,然后自动生成 C 解析器,通过 MathLink 或 LibraryLink 将其插回内核).我可能只希望它们会在未来的某些版本中可用.缺少这一点,我描述的方法将需要大量低级工作(C 或 Java,如果您愿意).不过我觉得还是可行的.如果你会写 C(或 Java),你可以尝试做一些相当简单的(在语法/语法方面)语言——这可能是一个有趣的项目,并且会给出一个更复杂的想法一.我将从一个非常基本的计算器示例开始,也许将那里的标准算术运算符更改为一些更奇怪的 Mathematica 无法正确解析的运算符,以使其更有趣.为了首先避免 MathLink/LibraryLink 复杂性并进行测试,您可以使用 Run 从 Mathematica 调用生成的可执行文件,将代码作为命令行参数之一传递,并将结果写入临时文件,然后您将导入到 Mathematica 中.以计算器为例,整个过程可以在几个小时内完成.

It would be best if analogs of tools like Lex(Flex)/Yacc(Bison) were available within Mathematica ( I mean bindings, which would require one to only write code in Mathematica, and generate say C parser from that automatically, plugging it back to the kernel either through MathLink or LibraryLink). I may only hope that they will become available in some future versions. Lacking that, the approach I described would require a lot of low-level work (C, or Java if your prefer). I think it is still doable however. If you can write C (or Java), you may try to do some fairly simple (in terms of the syntax / grammar) language - this may be an interesting project and will give an idea of what it will be like for a more complex one. I'd start with a very basic calculator example, and perhaps change the standard arithmetic operators there to some more weird ones that Mathematica can not parse properly itself, to make it more interesting. To avoid MathLink / LibraryLink complexity at first and just test, you can call the resulting executable from Mathematica with Run, passing the code as one of the command line arguments, and write the result to a temporary file, that you will then import into Mathematica. For the calculator example, the entire thing can be done in a few hours.

当然,如果您只想缩写某些长函数名,还有一个更简单的替代方法 - 您可以使用 With 来做到这一点.这是一个实际示例 - 我的 Peter Norvig 的 拼写校正器 的端口,我在此作弊减少行数的方法:

Of course, if you only want to abbreviate certain long function names, there is a much simpler alternative - you can use With to do that. Here is a practical example of that - my port of Peter Norvig's spelling corrector, where I cheated in this way to reduce the line count:

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}]];]];

您需要一些带有大量单词的训练文本作为字符串作为第二个参数传递,第一个参数是校正器的函数名称.这是 Norvig 使用的:

You need some training text with a large number of words as a string to pass as a second argument, and the first argument is the function name for a corrector. Here is the one that Norvig used:

text = Import["http://norvig.com/big.txt", "Text"];

你调用一次,说

In[7]:= makeCorrector[correct, text]

然后在某些单词上多次使用它

And then use it any number of times on some words

In[8]:= correct["coputer"] // Timing

Out[8]= {0.125, "computer"}

您可以自定义With-like控制结构,您可以在其中硬编码一些最让您烦恼的长mma名称的短名称,然后将其包裹在您的代码段中(但是,您将丢失代码突出显示).请注意,我通常不提倡这种方法 - 我这样做只是为了好玩并稍微减少行数.但至少,这是通用的,因为它将以交互方式和包的方式工作.不能做中缀操作符,不能改变优先级等等,但几乎零工作.

You can make your custom With-like control structure, where you hard-code the short names for some long mma names that annoy you the most, and then wrap that around your piece of code ( you'll lose the code highlighting however). Note, that I don't generally advocate this method - I did it just for fun and to reduce the line count a bit. But at least, this is universal in the sense that it will work both interactively and in packages. Can not do infix operators, can not change precedences, etc, etc, but almost zero work.

这篇关于Mathematica 符号和语法模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆