抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在使用Mathematica的笔记本的过程中,我们常常希望将它的代码和文档功能结合起来,例如自动将符号计算的公式、图形以文档的书写习惯展示出来,同时隐藏生成代码,使文档显示自然协调。

GeneralUtilities` 是Mathematica从版本10开始新加入的一个上下文。其中提供了大量的实用函数,包括代码生成、调试、静态分析、迭代器对象等各个领域,一定程度上弥补了Mathematica基础设施不足的状况。

背景和问题的引入

众所周知,Wolfram语言作为一个极为“高级”的编程语言,并没有提供指针这类较为底层的内存管理手段。而符号本身几乎总是充当了类似引用的作用,比如

1
2
3
4
set[sym_Symbol]:=sym=1
b=a;
set[b];
a

可以看到符号a的值通过set[b]赋为了1。在这里b形式上充当了类似其它语言中的引用的作用。但这种方式并不通用,只要a已经具有值了,这种平凡的方式就不能起作用了。有的读者可能会想到:=或者Hold封装,不过单靠这些也不能简单地对已具有本值的符号进行修改。因此,本文试图提出一种具有类似其它语言中指针语义的封装,实现对符号的间接操作。

问题的引入

ValueQ是Matheamtica中的一个非常有趣的函数,它判断一个表达式是否会进行求值,而且这种判断有时可以做到无副作用,哪怕求值本身是具有副作用的。比如

1
2
3
4
x=0;
y:=++x
v=ValueQ[y];
{v,x}

会得到{True,0}的结果。这里的ValueQ[y]显然并没有真正对y求值就作出了判断。不过很遗憾的是这其中哪怕只有略微的改动也会使其作用发生变化,例如

1
2
3
4
x=0;
y:=++x
v=ValueQ[y+0];
{v,x}

则会得到{True,1}

我曾经写过一篇关于Mathematica中下标与赋值问题的文章,不过那篇文章重点解决的是符号关联的问题。但有时,我们可能会遇到另一种问题,比如

All problems in computer science can be solved by another level of indirection. [1]

最近在拿Mathematica做一些小东西的时候发现CurrentValue等函数在动态中刷新不受Refresh等方式影响。比如

使用

1
GeneralUtilities`PrintDefinitions[symbol]

即可,如下图

众所周知,Mathematica中虽然使用下标形式非常方便,但如果对下标结构进行直接赋值,它将关联到内部符号Subscript上。这样,在我们大量清理符号定义的时候可能会漏掉一些定义。类似地,导数Derivative有同样的问题,比如对于

Mathematica在处理字符时默认总会将所有字符转换为ASCII字符表示,例如π会转化为\[Pi],而像汉字这样的一般字符会转化为\:4eea

这种设计固然可以避免某些环境对非ASCII字符不支持的困难,而且在Mathematica环境下会自动转换成原本的字符,但对于一般的文本阅读环境而言,尤其是在代码中使用一些中文文本或者注释时,这样的内容阅读起来根本无法理解。

为了方便在没有Mathematica的环境下也能方便的阅读程序包中的非ASCII的一般字符,下面脚本提供了将\:nnnn形式的转义序列转换为UTF-8编码下对应的Unicode字符的简单方法

Wolfram语言中的作用域结构主要有如下5种:

  • Module
  • Block
  • With
  • DynamicModule
  • 命名空间