我们都知道Mathematica很棒,但它也经常缺乏关键功能。您对Mathematica使用什么样的外部包/工具/资源?
我将编辑(并邀请其他人也这样做)这个主要帖子包括专注于科学研究的一般适用性的资源,以及尽可能多的人会发现有用的资源。随意贡献任何东西,甚至是小代码片段(正如我在下面做的时间例程)。
此外,在Mathematica 7及其他地方,您发现自己,或从某些纸张/网站挖出来的非文档和有用的功能是非常受欢迎的。
请提供简短描述或评论为什么有什么好东西或它提供的实用程序。如果您使用联盟链接链接到亚马逊上的书籍,请提及它,例如,在链接后面加上您的姓名。
包装:
LevelScheme
是一个大大扩展Mathematica生成好看情节的能力的软件包。我使用它,如果没有其他任何东西,那么对框架/轴刻度的大大改进控制。它的最新版本称为SciDraw,它将在今年某个时候发布。Presentation Package
(50美元 - 免费更新)grassmannOps
软件包提供了使用Grassmann变量和具有非平凡换向关系的运算符进行代数和微积分的资源。GrassmannAlgebra
包和书,用于与格拉斯曼和克利福德代数合作。工具
MASH
是Daniel Reeves的优秀Perl脚本,主要为Mathematica v7提供脚本支持。 (现在使用-script
选项从Mathematica 8开始构建。)alternate Mathematica shell
(使用python,* nix)资源:
Wolfram自己的存储库MathSource
在各种应用程序的窄笔记本中有很多用处。另请参阅其他部分,例如
Current Documentation
,Courseware
讲座,Demos
,以及演示。书籍:
web
,pdf
)的高级介绍是必读的,如果你想做除之外的任何事情循环。我们很高兴Leonid
在这里回答问题。web
)Demonstrations Page
。 pdf
) - 对您需要了解的关于Mathematica编程的大部分内容的简要介绍。未记录(或几乎没有记录)的功能:
this question
。this answer
this question
。 this question
。答案 0 :(得分:56)
Mathematica笔记本界面的一个好处是它可以用任何语言来评估表达式,而不仅仅是Mathematica。举个简单的例子,考虑创建一个新的 Shell 输入单元格类型,它将包含的表达式传递给操作系统shell进行评估。
首先,定义一个将文本命令的评估委托给外部shell的函数:
shellEvaluate[cmd_, _] := Import["!"~~cmd, "Text"]
第二个论点是必要的,并且由于后来会变得明显的原因而被忽略。接下来,我们要创建一个名为 Shell 的新样式:
Shell
。使用以下单元格表达式作为步骤6文本:
Cell[StyleData["Shell"],
CellFrame->{{0, 0}, {0.5, 0.5}},
CellMargins->{{66, 4}, {0, 8}},
Evaluatable->True,
StripStyleOnPaste->True,
CellEvaluationFunction->shellEvaluate,
CellFrameLabels->{{None, "Shell"}, {None, None}},
Hyphenation->False,
AutoQuoteCharacters->{},
PasteAutoQuoteCharacters->{},
LanguageCategory->"Formula",
ScriptLevel->1,
MenuSortingValue->1800,
FontFamily->"Courier"]
此表达式的大部分内容都是直接从内置的 Program 样式复制而来。关键的变化是这些方面:
Evaluatable->True,
CellEvaluationFunction->shellEvaluate,
CellFrameLabels->{{None, "Shell"}, {None, None}},
Evaluatable
为单元格启用SHIFT + ENTER功能。评估将调用CellEvaluationFunction
传递单元格内容和内容类型作为参数(shellEvaluate
忽略后一个参数)。 CellFrameLabels
只是让用户识别出这个单元格异常的一种精确性。
完成所有这些后,我们现在可以输入并评估shell表达式:
最好将此定义的样式保存在位于中心的样式表中。此外,shellEvaluate
等评估函数最好使用init.m
中的DeclarePackage定义为存根。这两项活动的细节都超出了本回复的范围。
使用此功能,可以创建包含任何感兴趣语法的输入表达式的笔记本。评估功能可以用纯Mathematica编写,或者将评估的任何或所有部分委托给外部机构。请注意,还有其他与细胞评估相关的钩子,例如CellEpilog
,CellProlog
和CellDynamicExpression
。
常见模式包括将输入表达式文本写入临时文件,以某种语言编译文件,运行程序并捕获输出以便在输出单元格中进行最终显示。在实现这种完整解决方案时(如正确捕获错误消息),有很多细节需要解决,但是必须认识到这样的事情不仅可以做到这样,而且是可行的。
就个人而言,正是这样的功能使得笔记本界面成为我编程世界的中心。
<强>更新强>
以下辅助函数对于创建此类单元格非常有用:
evaluatableCell[label_String, evaluationFunction_] :=
( CellPrint[
TextCell[
""
, "Program"
, Evaluatable -> True
, CellEvaluationFunction -> (evaluationFunction[#]&)
, CellFrameLabels -> {{None, label}, {None, None}}
, CellGroupingRules -> "InputGrouping"
]
]
; SelectionMove[EvaluationNotebook[], All, EvaluationCell]
; NotebookDelete[]
; SelectionMove[EvaluationNotebook[], Next, CellContents]
)
因此使用:
shellCell[] := evaluatableCell["shell", Import["!"~~#, "Text"] &]
现在,如果评估shellCell[]
,输入单元格将被删除并替换为新的输入单元格,该单元格将其内容评估为shell命令。
答案 1 :(得分:33)
Todd Gayley(Wolfram Research)给我发了一个很好的黑客,它允许用任意代码“包装”内置函数。我觉得我必须分享这个有用的工具。以下是托德在question
上的答案。
一些有趣的(?)历史:用于“包装”的黑客攻击方式 内置功能是由Robby Villegas和我在1994年左右发明的, 具有讽刺意味的是,函数Message在一个名为ErrorHelp的包中 那是我当时为Mathematica期刊写的。它已被使用 很多时候,很多人,从那以后。这是一个内幕消息 诀窍,但我认为说它已成为规范是公平的 将自己的代码注入内置函数定义的方法 功能。它很好地完成了工作。当然,你可以把 $ inMsg变量到你想要的任何私有语境中。
Unprotect[Message];
Message[args___] := Block[{$inMsg = True, result},
"some code here";
result = Message[args];
"some code here";
result] /; ! TrueQ[$inMsg]
Protect[Message];
答案 2 :(得分:29)
我之前提到过this,但我发现最有用的工具是Reap
和Sow
的应用,它模仿/扩展了GatherBy
的行为:
SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:=
Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];
这允许我按任何标准对列表进行分组,并在此过程中对其进行转换。它的工作方式是标准函数(f
)标记列表中的每个项目,然后每个项目由第二个提供的函数(g
)转换,特定输出由第三个控制功能(h
)。函数h
接受两个参数:标记和具有该标记的收集项的列表。这些项目保留了原始订单,因此如果您设置了h = #1&
,那么您会得到一个未排序的Union
,就像Reap
rx ry rz i j Re[Hij] Im[Hij]
一样。但是,它可以用于二次加工。
作为其效用的一个例子,我一直在使用examples将空间相关的哈密顿量输出到一个文件中,其中每一行是矩阵中的不同元素,如下所示
SparseArray
要将该列表转换为一组矩阵,我收集了包含相同坐标的所有子列表,将元素信息转换为规则(即{i,j} - &gt; Re [Hij] + I Im [Hij ]),然后将收集的规则转换为SelectEquivalents[hamlst,
#[[;; 3]] &,
#[[{4, 5}]] -> (Complex @@ #[[6 ;;]]) &,
{#1, SparseArray[#2]} &]
所有内容:
SelectEquivalents
老实说,这是我的瑞士军刀,它使复杂的事情变得非常简单。我的大多数其他工具都是针对特定领域的,所以我可能不会发布它们。但是,大多数(如果不是全部)参考GatherBy
。
修改:它并不完全模仿Wannier90,因为它无法像Map
一样对表达式的多个级别进行分组。但是,In[1] := pts = {{-1, -1, 0}, {-1, 0, 0}, {-1, 1, 0}, {0, -1, 0}, {0, 0, 0},
{0, 1, 0}, {1, -1, 0}, {1, 0, 0}, {1, 1, 0}}
适用于我需要的大部分内容。
示例:@Yaroslav Bulatov要求提供一个独立的示例。这是我的研究中大大简化的一个。所以,假设我们在一个平面上有一组点
In[2] := rots = RotationTransform[#, {0, 0, 1}] & /@ (Pi/2 Range[0, 3]);
我们希望通过一组对称操作来减少点数。 (好奇的是,我们正在生成每个点的GatherBy
。)对于这个例子,让我们使用围绕z轴的四倍旋转轴
SelectEquivalents
使用In[3] := SelectEquivalents[ pts, Union[Through[rots[#] ] ]& ] (*<-- Note Union*)
Out[3]:= {{{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}},
{{-1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {1, 0, 0}},
{{0,0,0}}}
我们可以在这些操作下对产生相同图像集的点进行分组,即它们是等效的,使用以下
Union
生成包含等效点的3个子列表。 (注意,Sort
在这里绝对至关重要,因为它确保每个点产生相同的图像。最初,我使用Union
,但如果一个点位于对称轴上,则它在下面是不变的。围绕该轴的旋转给出了一个额外的图像。所以,GatherBy
消除了这些额外的图像。而且,Identity
会产生相同的结果。)在这种情况下,这些点已经是我的形式了将使用,但我只需要每个分组的代表点,我想要计算等效点数。因为,我不需要转换每个点,我在第二个位置使用{0,0,0}
函数。对于第三个功能,我们需要小心。传递给它的第一个参数将是旋转点下的点的图像,点{0,0,0}
是四个相同元素的列表,使用它会丢掉计数。但是,第二个参数只是包含该标记的所有元素的列表,因此它只包含In[4] := SelectEquivalents[pts,
Union[Through[rots[#]]]&, #&, {#2[[1]], Length[#2]}& ]
Out[4]:= {{{-1, -1, 0}, 4}, {{-1, 0, 0}, 4}, {{0, 0, 0}, 1}}
。在代码中,
In[5] := {#[[1]], Length[#]}& /@ Out[3]
注意,最后一步可以通过
轻松完成{{1}}
但是,通过这个和上面不太完整的例子很容易看到如何用最少的代码进行非常复杂的转换。
答案 3 :(得分:24)
这不是一个完整的资源,所以我把它放在答案部分,但我发现它在确定速度问题时非常有用(不幸的是,它是Mathematica编程的一大部分)
timeAvg[func_] := Module[
{x = 0, y = 0, timeLimit = 0.1, p, q, iterTimes = Power[10, Range[0, 10]]},
Catch[
If[(x = First[Timing[(y++; Do[func, {#}]);]]) > timeLimit,
Throw[{x, y}]
] & /@ iterTimes
] /. {p_, q_} :> p/iterTimes[[q]]
];
Attributes[timeAvg] = {HoldAll};
然后使用timeAvg@funcYouWantToTest
。
编辑:Wizard先生提供了一个更简单的版本,可以取消Throw
和Catch
,并且更容易解析:
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@
Timing @ Do[func, {5^i}]
,{i, 0, 15}]
timeIt::usage = "timeIt[expr] gives the time taken to execute expr, \
repeating as many times as necessary to achieve a total time of 1s";
SetAttributes[timeIt, HoldAll]
timeIt[expr_] := Module[{t = Timing[expr;][[1]], tries = 1},
While[t < 1., tries *= 2; t = Timing[Do[expr, {tries}];][[1]];];
t/tries]
答案 4 :(得分:20)
Internal`InheritedBlock
我最近从官方新闻组的this message of Daniel Lichtblau了解到Internal`InheritedBlock
这样有用的功能的存在。
据我了解,Internal`InheritedBlock
允许在Block
范围内传递出站函数的副本:
In[1]:= Internal`InheritedBlock[{Message},
Print[Attributes[Message]];
Unprotect[Message];
Message[x___]:=Print[{{x},Stack[]}];
Sin[1,1]
]
Sin[1,1]
During evaluation of In[1]:= {HoldFirst,Protected}
During evaluation of In[1]:= {{Sin::argx,Sin,2},{Internal`InheritedBlock,CompoundExpression,Sin,Print,List}}
Out[1]= Sin[1,1]
During evaluation of In[1]:= Sin::argx: Sin called with 2 arguments; 1 argument is expected. >>
Out[2]= Sin[1,1]
我认为这个功能对于需要暂时修改内置函数的每个人都非常有用!
让我们定义一些功能:
a := Print[b]
现在我们希望将此函数的副本传递到Block
范围。天真的试验没有给出我们想要的东西:
In[2]:= Block[{a = a}, OwnValues[a]]
During evaluation of In[9]:= b
Out[2]= {HoldPattern[a] :> Null}
现在尝试在Block
的第一个参数中使用延迟定义(它也是一个未记录的功能):
In[3]:= Block[{a := a}, OwnValues[a]]
Block[{a := a}, a]
Out[3]= {HoldPattern[a] :> a}
During evaluation of In[3]:= b
我们在这种情况下看到a
有效,但我们没有获得a
范围内原始Block
的副本。
现在让我们试试Internal`InheritedBlock
:
In[5]:= Internal`InheritedBlock[{a}, OwnValues[a]]
Out[5]= {HoldPattern[a] :> Print[b]}
我们在a
范围内获得了Block
原始定义的副本,我们可以按照我们想要的方式对其进行修改,而不会影响a
的全局定义!< / p>
答案 5 :(得分:19)
Mathematica是一个敏锐的工具,但它可以使你有点untyped behaviour和avalanches神秘的diagnostic messages。解决这个问题的一种方法是按照这个习惯用法定义函数:
ClearAll@zot
SetAttributes[zot, ...]
zot[a_] := ...
zot[b_ /; ...] := ...
zot[___] := (Message[zot::invalidArguments]; Abort[])
这是很多样板,我经常试图跳过。特别是在原型设计时,Mathematica中发生了很多。所以,我使用了一个名为define
的宏,它允许我保持纪律,而且更少的样板。
define
的基本用法是这样的:
define[
fact[0] = 1
; fact[n_ /; n > 0] := n * fact[n-1]
]
fact[5]
120
起初看起来并不多,但有一些隐藏的好处。 define
提供的第一项服务是自动将ClearAll
应用于正在定义的符号。这确保了没有剩余的定义 - 在函数的初始开发过程中经常出现。
第二项服务是所定义的功能自动“关闭”。我的意思是,如果使用与其中一个定义不匹配的参数列表调用该函数,该函数将发出消息并中止:
fact[-1]
define::badargs: There is no definition for 'fact' applicable to fact[-1].
$Aborted
这是define
的主要值,它捕获了一个非常常见的错误类。
另一个便利是在所定义的函数上指定属性的简明方法。让我们创建函数Listable
:
define[
fact[0] = 1
; fact[n_ /; n > 0] := n * fact[n-1]
, Listable
]
fact[{3, 5, 8}]
{6, 120, 40320}
除了所有常规属性外,define
还接受名为Open
的其他属性。这可以防止define
将catch-all错误定义添加到函数中:
define[
successor[x_ /; x > 0] := x + 1
, Open
]
successor /@ {1, "hi"}
{2, successor["hi"]}
可以为函数定义多个属性:
define[
flatHold[x___] := Hold[x]
, {Flat, HoldAll}
]
flatHold[flatHold[1+1, flatHold[2+3]], 4+5]
Hold[1 + 1, 2 + 3, 4 + 5]
不用多说,这里是define
:
ClearAll@define
SetAttributes[define, HoldAll]
define[body_, attribute_Symbol] := define[body, {attribute}]
define[body:(_Set|_SetDelayed), attributes_List:{}] := define[CompoundExpression[body], attributes]
define[body:CompoundExpression[((Set|SetDelayed)[name_Symbol[___], _])..], attributes_List:{}] :=
( ClearAll@name
; SetAttributes[name, DeleteCases[attributes, Open]]
; If[!MemberQ[attributes, Open]
, def:name[___] := (Message[define::badargs, name, Defer@def]; Abort[])
]
; body
;
)
def:define[___] := (Message[define::malformed, Defer@def]; Abort[])
define::badargs = "There is no definition for '``' applicable to ``.";
define::malformed = "Malformed definition: ``";
展示的实现既不支持up-value也不支持currying,也不支持比简单函数定义更通用的模式。然而,它仍然有用。
答案 6 :(得分:16)
让Mathematica开始打开空白笔记本让我感到困扰。我可以用脚本关闭这个笔记本,但它仍然会短暂地打开。我的黑客是创建一个文件Invisible.nb
,其中包含:
Notebook[{},Visible->False]
并将其添加到我的Kernel\init.m
:
If[Length[Notebooks["Invisible*"]] > 0,
NotebookClose[Notebooks["Invisible*"][[1]]]
]
SetOptions[$FrontEnd,
Options[$FrontEnd, NotebooksMenu] /.
HoldPattern["Invisible.nb" -> {__}] :> Sequence[]
]
我现在通过打开Invisible.nb
可能有更好的方法,但这对我有好处。
Fold
和FoldList
Fold[f, x]
等同于Fold[f, First@x, Rest@x]
顺便说一下,我相信这可能会进入Mathematica的未来版本。
Surprise! This has been implemented, though it is presently undocumented.我被告知,它是在2011年由Oliver Ruebenkoenig实施的,显然不久我发布了这个。谢谢Oliver Ruebenkoenig!
Unprotect[Fold, FoldList]
Fold[f_, h_[a_, b__]] := Fold[f, Unevaluated @ a, h @ b]
FoldList[f_, h_[a_, b__]] := FoldList[f, Unevaluated @ a, h @ b]
(* Faysal's recommendation to modify SyntaxInformation *)
SyntaxInformation[Fold] = {"ArgumentsPattern" -> {_, _, _.}};
SyntaxInformation[FoldList] = {"ArgumentsPattern" -> {_, _., {__}}};
Protect[Fold, FoldList]
更新以允许此操作:
SetAttributes[f, HoldAll]
Fold[f, Hold[1 + 1, 2/2, 3^3]]
f[f[1 + 1, 2/2], 3^3]
有关此功能的新版本,请参阅Mathematica.SE post #7512。
我经常想根据一系列长度对列表进行分区。
伪代码示例:
partition[{1,2,3,4,5,6}, {2,3,1}]
输出:{{1,2}, {3,4,5}, {6}}
我想出了这个:
dynP[l_, p_] :=
MapThread[l[[# ;; #2]] &, {{0} ~Join~ Most@# + 1, #} &@Accumulate@p]
然后我完成了这个,包括参数测试:
dynamicPartition[l_List, p : {_Integer?NonNegative ..}] :=
dynP[l, p] /; Length@l >= Tr@p
dynamicPartition[l_List, p : {_Integer?NonNegative ..}, All] :=
dynP[l, p] ~Append~ Drop[l, Tr@p] /; Length@l >= Tr@p
dynamicPartition[l_List, p : {_Integer?NonNegative ..}, n__ | {n__}] :=
dynP[l, p] ~Join~ Partition[l ~Drop~ Tr@p, n] /; Length@l >= Tr@p
第三个参数控制分割规范之外的元素会发生什么。
我最常使用的是粘贴表格数据调色板
CreatePalette@
Column@{Button["TSV",
Module[{data, strip},
data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
strip[s_String] :=
StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
strip[e_] := e;
If[Head[data] === String,
NotebookWrite[InputNotebook[],
ToBoxes@Map[strip, ImportString[data, "TSV"], {2}]]]]],
Button["CSV",
Module[{data, strip},
data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
strip[s_String] :=
StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
strip[e_] := e;
If[Head[data] === String,
NotebookWrite[InputNotebook[],
ToBoxes@Map[strip, ImportString[data, "CSV"], {2}]]]]],
Button["Table",
Module[{data}, data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
If[Head[data] === String,
NotebookWrite[InputNotebook[],
ToBoxes@ImportString[data, "Table"]]]]]}
Compile
最近Daniel Lichtblau展示了我以前从未见过的这种方法。在我看来,它显着扩展了Compile
ll = {2., 3., 4.};
c = Compile[{{x}, {y}}, ll[[1]] = x; y];
c[4.5, 5.6]
ll
(* Out[1] = 5.6 *)
(* Out[2] = {4.5, 3., 4.} *)
答案 7 :(得分:14)
1)它完全出乎意料且没有文档记录,但 Mathematica 使用一组样式定义导出并保存PDF和EPS格式的图形,这些样式定义与用于在屏幕上显示笔记本的样式定义不同。默认情况下,笔记本在“工作”样式环境中显示在屏幕上(这是ScreenStyleEvironment
全局$FrontEnd
选项的默认值),但是在"Printout"
样式环境中打印(默认情况下) PrintingStyleEnvironment
全局$FrontEnd
选项的值。当以光栅格式(如GIF和PNG)或EMF格式导出图形时, Mathematica 会生成与Notebook内部完全相同的图形。在这种情况下,似乎"Working"
样式环境用于渲染。但是,当您导出/保存PDF或EPS格式的任何内容时,情况并非如此!在这种情况下,"Printout"
style environment is used by default与“工作”风格环境有很大不同。首先,the "Printout"
style environment sets Magnification
to 80%。其次,它使用自己的值来表示不同样式的字体大小,这导致与原始屏幕表示相比,生成的PDF文件中的字体大小更改不一致。后者可以称为FontSize fluctuations,非常烦人。
但幸运的是,这可以避免by setting the PrintingStyleEnvironment
global $FrontEnd
option to "Working":
SetOptions[$FrontEnd, PrintingStyleEnvironment -> "Working"]
2)导出到EMF格式的常见问题是,大多数程序(不仅仅是 Mathematica )生成的文件在默认大小时看起来不错,但在放大时会变得难看。是因为metafiles are sampled at screen resolution fidelity。生成的EMF文件的质量可以通过Magnify
原始图形对象来增强,以便原始图形的采样精确度变得更加精确。比较两个文件:
graphics1 =
First@ImportString[
ExportString[Style["a", FontFamily -> "Times"], "PDF"], "PDF"];
graphics2 = Magnify[graphics1, 10];
Export["C:\\test1.emf", graphics1]
Export["C:\\test2.emf", graphics2]
如果您将这些文件插入Microsoft Word并放大它们,您会看到第一个“a”有锯齿而第二个没有(用 Mathematica 6测试)。
Chris Degnen建议了ImageResolution
的另一种方式(此选项至少从 Mathematica 8开始生效):
Export["C:\\test1.emf", graphics1]
Export["C:\\test2.emf", graphics1, ImageResolution -> 300]
3)在 Mathematica 中,我们有三种方法将图形转换为图元文件:通过Export
到"EMF"
(强烈推荐的方式:生成质量最高的图元文件),通过Save selection As...
菜单项(produces much lesser precise figure,不推荐)和Edit ► Copy As ► Metafile
菜单项(I strongly recommend against this route)。
答案 8 :(得分:13)
我发现这些函数对缓存任何表达式非常有帮助。这两个函数的有趣之处在于,保持表达式本身用作哈希表/符号Cache或CacheIndex的键,与mathematica中众所周知的memoization相比,如果函数定义为f,则只能缓存结果[x_]:= f [x] = ...所以你可以缓存代码的任何部分,如果要多次调用一个函数但是不能重新计算代码的某些部分,这很有用。
独立于其参数缓存表达式。
SetAttributes[Cache, HoldFirst];
c:Cache[expr_] := c = expr;
Ex: Cache[Pause[5]; 6]
Cache[Pause[5]; 6]
第二次表达式返回6而不等待。
使用别名表达式缓存表达式,该表达式可能取决于缓存表达式的参数。
SetAttributes[CacheIndex, HoldRest];
c:CacheIndex[index_,expr_] := c = expr;
Ex: CacheIndex[{"f",2},x=2;y=4;x+y]
如果expr需要一些时间来计算,那么评估{“f”,2}例如检索缓存结果要快得多。
要获得这些函数的变体以便拥有本地化缓存(即缓存内存在Block构造之外自动释放),请参阅此帖子Avoid repeated calls to Interpolation
当您不知道函数的定义数时,删除缓存的值。我认为定义在他们的论点中有一个空白。
DeleteCachedValues[f_] :=
DownValues[f] = Select[DownValues[f], !FreeQ[Hold@#,Pattern]&];
当您知道函数的定义数量时(稍快一些),删除缓存的值。
DeleteCachedValues[f_,nrules_] :=
DownValues[f] = Extract[DownValues[f], List /@ Range[-nrules, -1]];
这使用了一个函数定义位于其DownValues列表末尾,缓存值在之前的事实。
此外,还有一些有趣的函数可以使用像对象这样的符号。
众所周知,您可以将数据存储在符号中,并使用DownValues
快速访问它们mysymbol["property"]=2;
您可以根据本网站帖子中提交的漏洞使用这些功能访问符号的键(或属性)列表:
SetAttributes[RemoveHead, {HoldAll}];
RemoveHead[h_[args___]] := {args};
NKeys[symbol_] := RemoveHead @@@ DownValues[symbol(*,Sort->False*)][[All,1]];
Keys[symbol_] := NKeys[symbol] /. {x_} :> x;
我经常使用这个函数来显示符号DownValues中包含的所有信息:
PrintSymbol[symbol_] :=
Module[{symbolKeys},
symbolKeys = Keys[symbol];
TableForm@Transpose[{symbolKeys, symbol /@ symbolKeys}]
];
最后,这是一种创建符号的简单方法,该符号在面向对象编程中表现得像一个对象(它只是重现了OOP的最基本行为,但我发现语法优雅):
Options[NewObject]={y->2};
NewObject[OptionsPattern[]]:=
Module[{newObject},
newObject["y"]=OptionValue[y];
function[newObject,x_] ^:= newObject["y"]+x;
newObject /: newObject.function2[x_] := 2 newObject["y"]+x;
newObject
];
属性作为DownValues和方法存储为由返回的Module创建的符号中的延迟Upvalues。我发现function2的语法是Tree data structure in Mathematica中函数的常用OO语法。
有关每个符号所包含的现有值类型的列表,请参阅http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html和http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html。
例如试试这个
x = NewObject[y -> 3];
function[x, 4]
x.function2[5]
如果要使用此处提供的名为InheritRules的包模拟对象继承,可以更进一步 http://library.wolfram.com/infocenter/MathSource/671/
您也可以将函数定义存储在newObject中但不存储在类型符号中,因此如果NewObject返回类型[newObject]而不是newObject,您可以像这样定义函数和函数2 在NewObject之外(而不是在内部)并具有与之前相同的用法。
function[type[object_], x_] ^:= object["y"] + x;
type /: type[object_].function2[x_] := 2 object["y"]+x;
使用UpValues [type]查看函数和function2是否在类型符号中定义。
此处介绍了有关此最后语法的其他想法https://mathematica.stackexchange.com/a/999/66。
@rcollyer:非常感谢将SelectEquivalents带到表面,这是一个了不起的功能。 以下是上面列出的SelectEquivalents的改进版本,具有更多可能性和使用选项,这使其更易于使用。
Options[SelectEquivalents] =
{
TagElement->Identity,
TransformElement->Identity,
TransformResults->(#2&) (*#1=tag,#2 list of elements corresponding to tag*),
MapLevel->1,
TagPattern->_,
FinalFunction->Identity
};
SelectEquivalents[x_List,OptionsPattern[]] :=
With[
{
tagElement=OptionValue@TagElement,
transformElement=OptionValue@TransformElement,
transformResults=OptionValue@TransformResults,
mapLevel=OptionValue@MapLevel,
tagPattern=OptionValue@TagPattern,
finalFunction=OptionValue@FinalFunction
}
,
finalFunction[
Reap[
Map[
Sow[
transformElement@#
,
{tagElement@#}
]&
,
x
,
{mapLevel}
]
,
tagPattern
,
transformResults
][[2]]
]
];
以下是如何使用此版本的示例:
Using Mathematica Gather/Collect properly
How would you do a PivotTable function in Mathematica?
Mathematica fast 2D binning algorithm
Daniel Lichtblau在这里描述了一个有趣的内部数据结构,用于增长列表。
Implementing a Quadtree in Mathematica
这两篇文章指出了有用的调试功能:
这是另一个基于Reap和Sow的函数,用于从程序的不同部分提取表达式并将它们存储在符号中。
SetAttributes[ReapTags,HoldFirst];
ReapTags[expr_]:=
Module[{elements},
Reap[expr,_,(elements[#1]=#2/.{x_}:>x)&];
elements
];
这是一个例子
ftest[]:=((*some code*)Sow[1,"x"];(*some code*)Sow[2,"x"];(*some code*)Sow[3,"y"]);
s=ReapTags[ftest[]];
Keys[s]
s["x"]
PrintSymbol[s] (*Keys and PrintSymbol are defined above*)
以下是用于学习目的的有趣链接列表:
答案 9 :(得分:13)
根据大众需求,使用annotations生成前10个SO回复者的代码(SO API除外)。
getRepChanges[userID_Integer] :=
Module[{totalChanges},
totalChanges =
"total" /.
Import["http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <> "/reputation?fromdate=0&pagesize=10&page=1",
"JSON"];
Join @@ Table[
"rep_changes" /.
Import["http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <>
"/reputation?fromdate=0&pagesize=10&page=" <> ToString[page],
"JSON"],
{page, 1, Ceiling[totalChanges/10]}
]
]
topAnswerers = ({"display_name",
"user_id"} /. #) & /@ ("user" /. ("top_users" /.
Import["http://api.stackoverflow.com/1.1/tags/mathematica/top-\
answerers/all-time", "JSON"]))
repChangesTopUsers =
Monitor[Table[
repChange =
ReleaseHold[(Hold[{DateList[
"on_date" + AbsoluteTime["January 1, 1970"]],
"positive_rep" - "negative_rep"}] /. #) & /@
getRepChanges[userID]] // Sort;
accRepChange = {repChange[[All, 1]],
Accumulate[repChange[[All, 2]]]}\[Transpose],
{userID, topAnswerers[[All, 2]]}
], userID];
pl = DateListLogPlot[
Tooltip @@@
Take[({repChangesTopUsers, topAnswerers[[All, 1]]}\[Transpose]),
10], Joined -> True, Mesh -> None, ImageSize -> 1000,
PlotRange -> {All, {10, All}},
BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16},
DateTicksFormat -> {"MonthNameShort", " ", "Year"},
GridLines -> {True, None},
FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation",
"Top-10 answerers", ""})]
答案 10 :(得分:12)
我的实用程序功能(我将这些内置于MASH中,问题中提到):
pr = WriteString["stdout", ##]&; (* More *)
prn = pr[##, "\n"]&; (* convenient *)
perr = WriteString["stderr", ##]&; (* print *)
perrn = perr[##, "\n"]&; (* statements. *)
re = RegularExpression; (* I wish mathematica *)
eval = ToExpression[cat[##]]&; (* weren't so damn *)
EOF = EndOfFile; (* verbose! *)
read[] := InputString[""]; (* Grab a line from stdin. *)
doList[f_, test_] := (* Accumulate list of what f[] *)
Most@NestWhileList[f[]&, f[], test]; (* returns while test is true. *)
readList[] := doList[read, #=!=EOF&]; (* Slurp list'o'lines from stdin. *)
cat = StringJoin@@(ToString/@{##})&; (* Like sprintf/strout in C/C++. *)
system = Run@cat@##&; (* System call. *)
backtick = Import[cat["!", ##], "Text"]&; (* System call; returns stdout. *)
slurp = Import[#, "Text"]&; (* Fetch contents of file as str. *)
(* ABOVE: mma-scripting related. *)
keys[f_, i_:1] := (* BELOW: general utilities. *)
DownValues[f, Sort->False][[All,1,1,i]]; (* Keys of a hash/dictionary. *)
SetAttributes[each, HoldAll]; (* each[pattern, list, body] *)
each[pat_, lst_, bod_] := ReleaseHold[ (* converts pattern to body for *)
Hold[Cases[Evaluate@lst, pat:>bod];]]; (* each element of list. *)
some[f_, l_List] := True === (* Whether f applied to some *)
Scan[If[f[#], Return[True]]&, l]; (* element of list is True. *)
every[f_, l_List] := Null === (* Similarly, And @@ f/@l *)
Scan[If[!f[#], Return[False]]&, l]; (* (but with lazy evaluation). *)
答案 11 :(得分:11)
我使用过的一个技巧,它允许你模仿大多数内置函数使用错误参数的方式(通过发送消息然后返回未评估的整个表单)利用Condition
方式的怪癖在定义中使用时起作用。如果foo
只能使用一个参数:
foo[x_] := x + 1;
expr : foo[___] /; (Message[foo::argx, foo, Length@Unevaluated[expr], 1];
False) := Null; (* never reached *)
如果您有更复杂的需求,很容易将参数验证和消息生成分解为一个独立的函数。除了生成消息之外,您可以在Condition
中使用副作用来做更精细的事情,但在我看来,大多数都属于“低级黑客”类别,如果可能的话应该避免使用。
此外,在“元编程”类别中,如果您有一个Mathematica包(.m
)文件,则可以使用"HeldExpressions"
element获取包含在{{1}中的文件中的所有表达式}。这使得跟踪事物比使用基于文本的搜索更容易。不幸的是,没有简单的方法可以用笔记本做同样的事情,但你可以使用以下内容获得所有输入表达式:
HoldComplete
最后,您可以使用inputExpressionsFromNotebookFile[nb_String] :=
Cases[Get[nb],
Cell[BoxData[boxes_], "Input", ___] :>
MakeExpression[StripBoxes[boxes], StandardForm],
Infinity]
模拟词法闭包的事实来创建等效的引用类型。这是一个简单的堆栈(使用变量Module
处理错误处理作为奖励):
Condition
现在,您可以以不必要的复杂方式以相反的顺序打印列表的元素!
ClearAll[MakeStack, StackInstance, EmptyQ, Pop, Push, Peek]
With[{emptyStack = Unique["empty"]},
Attributes[StackInstance] = HoldFirst;
MakeStack[] :=
Module[{backing = emptyStack},
StackInstance[backing]];
StackInstance::empty = "stack is empty";
EmptyQ[StackInstance[backing_]] := (backing === emptyStack);
HoldPattern[
Pop[instance : StackInstance[backing_]]] /;
! EmptyQ[instance] || (Message[StackInstance::empty]; False) :=
(backing = Last@backing; instance);
HoldPattern[Push[instance : StackInstance[backing_], new_]] :=
(backing = {new, backing}; instance);
HoldPattern[Peek[instance : StackInstance[backing_]]] /;
! EmptyQ[instance] || (Message[StackInstance::empty]; False) :=
First@backing]
答案 12 :(得分:11)
下面的contextFreeDefinition[]
函数将尝试打印符号的定义,而不会添加最常见的上下文。然后可以将该定义复制到Workbench并进行格式化以便于阅读(选择它,右键单击,Source - &gt; Format)
Clear[commonestContexts, contextFreeDefinition]
commonestContexts[sym_Symbol, n_: 1] := Quiet[
Commonest[
Cases[Level[DownValues[sym], {-1}, HoldComplete],
s_Symbol /; FreeQ[$ContextPath, Context[s]] :> Context[s]], n],
Commonest::dstlms]
contextFreeDefinition::contexts = "Not showing the following contexts: `1`";
contextFreeDefinition[sym_Symbol, contexts_List] :=
(If[contexts =!= {}, Message[contextFreeDefinition::contexts, contexts]];
Internal`InheritedBlock[{sym}, ClearAttributes[sym, ReadProtected];
Block[{$ContextPath = Join[$ContextPath, contexts]},
Print@InputForm[FullDefinition[sym]]]])
contextFreeDefinition[sym_Symbol, context_String] :=
contextFreeDefinition[sym, {context}]
contextFreeDefinition[sym_Symbol] :=
contextFreeDefinition[sym, commonestContexts[sym]]
警告:此函数不会以With
和Module
的方式本地化变量,这意味着嵌套的本地化构造将无法按预期工作。 withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]]
将替换嵌套a
和b
中的With
和Rule
,而With
则不会此
这是使用规则而不是With
和=
的{{1}}的变体:
:=
我发现在清理实验期间编写的代码和本地化变量时这很有用。偶尔我会以ClearAll[withRules]
SetAttributes[withRules, HoldAll]
withRules[rules_, expr_] :=
Internal`InheritedBlock[
{Rule, RuleDelayed},
SetAttributes[{Rule, RuleDelayed}, HoldFirst];
Unevaluated[expr] /. rules
]
的形式结束参数列表。使用{par1 -> 1.1, par2 -> 2.2}
参数值很容易注入先前使用全局变量编写的代码中。
用法就像withRules
:
With
这是一种非常简单的抗锯齿3D图形技术,即使您的图形硬件本身不支持它。
withRules[
{a -> 1, b -> 2},
a+b
]
以下是一个例子:
请注意,antialias[g_, n_: 3] :=
ImageResize[Rasterize[g, "Image", ImageResolution -> n 72], Scaled[1/n]]
的较大值或较大的图片大小往往会暴露图形驱动程序错误或引入人工制品。
在n
包中提供了Notebook diff功能,并且在未记录的<<AuthorTools`
上下文中提供了(至少在版本8中)。这是一个用于区分当前打开的两个笔记本的GUI:
NotebookTools`
答案 13 :(得分:9)
递归纯函数(#0
)似乎是该语言的黑暗角落之一。以下是一些使用它们的非平凡的例子,其中这非常有用(并非如果没有它就无法完成)。以下是一个非常简洁且速度相当快的函数,可以在图中找到连接的组件,给定一个指定为顶点对的边列表:
ClearAll[setNew, componentsBFLS];
setNew[x_, x_] := Null;
setNew[lhs_, rhs_]:=lhs:=Function[Null, (#1 := #0[##]); #2, HoldFirst][lhs, rhs];
componentsBFLS[lst_List] := Module[{f}, setNew @@@ Map[f, lst, {2}];
GatherBy[Tally[Flatten@lst][[All, 1]], f]];
这里发生的是我们首先在每个顶点数上映射一个虚拟符号,然后设置一种方式,给定一对顶点{f[5],f[10]}
,然后f[5]
将评估到f[10]
。递归纯函数用作路径压缩器(以这样的方式设置memoization,而不是像f[1]=f[3],f[3]=f[4],f[4]=f[2], ...
这样的长链,只要发现组件的新“根”,就会更正记忆值。因为我们使用赋值,所以我们需要使用HoldAll,这使得这个构造更加模糊和更有吸引力)。这个函数是由线上和离线Mathgroup讨论的结果,涉及Fred Simons,Szabolcs Horvat,DrMajorBob和你的真实。例如:
In[13]:= largeTest=RandomInteger[{1,80000},{40000,2}];
In[14]:= componentsBFLS[largeTest]//Short//Timing
Out[14]= {0.828,{{33686,62711,64315,11760,35384,45604,10212,52552,63986,
<<8>>,40962,7294,63002,38018,46533,26503,43515,73143,5932},<<10522>>}}
它肯定比内置慢得多,但对于代码的大小,IMO还是相当快。
另一个例子:这是基于链表和递归纯函数的Select
的递归实现:
selLLNaive[x_List, test_] :=
Flatten[If[TrueQ[test[#1]],
{#1, If[#2 === {}, {}, #0 @@ #2]},
If[#2 === {}, {}, #0 @@ #2]] & @@ Fold[{#2, #1} &, {}, Reverse[x]]];
例如,
In[5]:= Block[
{$RecursionLimit= Infinity},
selLLNaive[Range[3000],EvenQ]]//Short//Timing
Out[5]= {0.047,{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,
<<1470>>,2972,2974,2976,2978,2980,2982,2984,2986,2988,2990,
2992,2994,2996,2998,3000}}
然而,它不是正确的尾递归,并且会使堆栈(崩溃内核)更大的列表。这是尾递归版本:
selLLTailRec[x_List, test_] :=
Flatten[
If[Last[#1] === {},
If[TrueQ[test[First[#1]]],
{#2, First[#1]}, #2],
(* else *)
#0[Last[#1],
If[TrueQ[test[First[#1]]], {#2, First[#1]}, #2]
]] &[Fold[{#2, #1} &, {}, Reverse[x]], {}]];
例如,
In[6]:= Block[{$IterationLimit= Infinity},
selLLTailRec[Range[500000],EvenQ]]//Short//Timing
Out[6]= {2.39,{2,4,6,8,10,12,14,16,18,20,22,
<<249978>>,499980,499982,499984,499986,499988,499990,499992,
499994,499996,499998,500000}}
答案 14 :(得分:8)
可以使用未记录的command-line options -batchinput
and -batchoutput
math -batchinput -batchoutput < input.m > outputfile.txt
(其中input.m
是以换行符结尾的批输入文件,outputfile.txt
是输出将被重定向到的文件。
在 Mathematica v。&gt; = 6中,MathKernel有未记录的命令行选项:
-noicon
控制MathKernel是否在任务栏上显示可见图标(至少在Windows下)。
FrontEnd(至少从第5版开始)有未记录的命令行选项
-b
禁用启动画面并允许更快地运行 Mathematica FrontEnd
和选项
-directlaunch
其中disables the mechanism which launches the most recent Mathematica version installed而不是启动与系统注册表中的.nb文件关联的版本。
另一种方法可能是is:
而不是启动 Mathematica.exe中的二进制文件 安装目录,启动 Mathematica.exe二进制文件 SystemFiles \前端\二进制\ Windows操作系统。 前者是一个简单的发射器 最努力的计划 重定向开放请求 笔记本运行的副本 用户界面。后者是 用户界面二进制本身。
将最后一个命令行选项与设置全局FrontEnd选项VersionedPreferences->True
which disables sharing of preferences between different Mathematica versions installed结合使用非常方便:
SetOptions[$FrontEnd, VersionedPreferences -> True]
(以上内容应在安装的最新 Mathematica 版本中进行评估。)
在 Mathematica 8 this is controlled in the Preferences dialog, in the System pane, under the setting "Create and maintain version specific front end preferences"。
通过使用未记录的密钥-h
(Windows代码),可以获得FrontEnd的命令行选项的不完整列表:
SetDirectory[$InstallationDirectory <>
"\\SystemFiles\\FrontEnd\\Binaries\\Windows\\"];
Import["!Mathematica -h", "Text"]
给出:
Usage: Mathematica [options] [files]
Valid options:
-h (--help): prints help message
-cleanStart (--cleanStart): removes existing preferences upon startup
-clean (--clean): removes existing preferences upon startup
-nogui (--nogui): starts in a mode which is initially hidden
-server (--server): starts in a mode which disables user interaction
-activate (--activate): makes application frontmost upon startup
-topDirectory (--topDirectory): specifies the directory to search for resources and initialization files
-preferencesDirectory (--preferencesDirectory): specifies the directory to search for user AddOns and preference files
-password (--password): specifies the password contents
-pwfile (--pwfile): specifies the path for the password file
-pwpath (--pwpath): specifies the directory to search for the password file
-b (--b): launches without the splash screen
-min (--min): launches as minimized
其他选项包括:
-directLaunch: force this FE to start
-32: force the 32-bit FE to start
-matchingkernel: sets the frontend to use the kernel of matching bitness
-Embedding: specifies that this instance is being used to host content out of process
MathKernel和FrontEnd还有其他可能有用的命令行选项吗?如果您知道,请分享。
答案 15 :(得分:8)
这是Stan Wagon的书中的配方......当内置Plot由于缺乏精确度而表现不正常时使用它
Options[PrecisePlot] = {PrecisionGoal -> 6};
PrecisePlot[f_, {x_, a_, b_}, opts___] := Module[{g, pg},
pg = PrecisionGoal /. {opts} /. Options[PrecisePlot];
SetAttributes[g, NumericFunction];
g[z_?InexactNumberQ] := Evaluate[f /. x -> z];
Plot[N[g[SetPrecision[y, \[Infinity]]], pg], {y, a, b},
Evaluate[Sequence @@ FilterRules[{opts}, Options[Plot]]]]];
当我需要来自Mathematica's downvalues的“字典式”行为时,我经常使用Kristjan Kannike的以下技巧
index[downvalue_,
dict_] := (downvalue[[1]] /. HoldPattern[dict[x_]] -> x) //
ReleaseHold;
value[downvalue_] := downvalue[[-1]];
indices[dict_] :=
Map[#[[1]] /. {HoldPattern[dict[x_]] -> x} &, DownValues[dict]] //
ReleaseHold;
values[dict_] := Map[#[[-1]] &, DownValues[dict]];
items[dict_] := Map[{index[#, dict], value[#]} &, DownValues[dict]];
indexQ[dict_, index_] :=
If[MatchQ[dict[index], HoldPattern[dict[index]]], False, True];
(* Usage example: *)
(* Count number of times each subexpression occurs in an expression *)
expr = Cos[x + Cos[Cos[x] + Sin[x]]] + Cos[Cos[x] + Sin[x]]
Map[(counts[#] = If[indexQ[counts, #], counts[#] + 1, 1]; #) &, expr, Infinity];
items[counts]
当评估结果令人困惑时,有时将评估步骤转储到文本文件中会有帮助
SetAttributes[recordSteps, HoldAll];
recordSteps[expr_] :=
Block[{$Output = List@OpenWrite["~/temp/msgStream.m"]},
TracePrint[Unevaluated[expr], _?(FreeQ[#, Off] &),
TraceInternal -> True];
Close /@ $Output;
Thread[Union@
Cases[ReadList["~/temp/msgStream.m", HoldComplete[Expression]],
symb_Symbol /;
AtomQ@Unevaluated@symb &&
Context@Unevaluated@symb === "System`" :>
HoldComplete@symb, {0, Infinity}, Heads -> True], HoldComplete]
]
(* Usage example: *)
(* puts steps of evaluation of 1+2+Sin[5]) into ~/temp/msgStream.m *)
recordSteps[1+2+Sin[5]]
答案 16 :(得分:7)
在 Mathematica 中使用PutAppend
命令是使用中间计算结果维护正在运行的日志文件的最直接方法。但是在将表达式导出到文件时它默认使用PageWith->78
设置,因此无法保证每个中间输出在日志中只占用一行。
PutAppend
本身没有任何选项,但跟踪其评估显示它基于具有OpenAppend
选项的PageWith
函数,并允许通过{{更改其默认值1}}命令:
SetOptions
因此,我们可以通过设置{/ p>让In[2]:= Trace[x>>>"log.txt",TraceInternal->True]
Out[2]= {x>>>log.txt,{OpenAppend[log.txt,CharacterEncoding->PrintableASCII],OutputStream[log.txt,15]},Null}
一次只追加一行
PutAppend
<强>更新强>
版本10中引入了bug(已在版本11.3中修复):SetOptions[OpenAppend, PageWidth -> Infinity]
不再影响SetOptions
和OpenWrite
的行为。
解决方法是使用明确的OpenAppend
选项实现您自己的PutAppend
版本:
PageWidth -> Infinity
请注意,我们也可以通过Clear[myPutAppend]
myPutAppend[expr_, pathtofile_String] :=
(Write[#, expr]; Close[#];) &[OpenAppend[pathtofile, PageWidth -> Infinity]]
实施this回答,但是在这种情况下,有必要将表达式初步转换为相应的WriteString
via {{ 1}}。
答案 17 :(得分:7)
我最喜欢的黑客是生成小代码的宏,它允许您用一个短的命令替换一堆标准样板命令。或者,您可以创建用于打开/创建笔记本的命令。
以下是我在日常Mathematica工作流程中使用了一段时间的内容。我发现自己经常做以下事情:
一遍又一遍地做这一切都很痛苦,所以让我们自动化吧!首先,一些实用程序代码:
(* Credit goes to Sasha for SelfDestruct[] *)
SetAttributes[SelfDestruct, HoldAllComplete];
SelfDestruct[e_] := (If[$FrontEnd =!= $Failed,
SelectionMove[EvaluationNotebook[], All, EvaluationCell];
NotebookDelete[]]; e)
writeAndEval[nb_,boxExpr_]:=(
NotebookWrite[nb, CellGroupData[{Cell[BoxData[boxExpr],"Input"]}]];
SelectionMove[nb, Previous, Cell];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb];
)
ExposeContexts::badargs =
"Exposed contexts should be given as a list of strings.";
ExposeContexts[list___] :=
Module[{ctList}, ctList = Flatten@List@list;
If[! MemberQ[ctList, Except[_String]],AppendTo[$ContextPath, #] & /@ ctList,
Message[ExposeContexts::badargs]];
$ContextPath = DeleteDuplicates[$ContextPath];
$ContextPath]
Autosave[x:(True|False)] := SetOptions[EvaluationNotebook[],NotebookAutoSave->x];
现在,让我们创建一个宏,它将把以下单元格放在笔记本中:
SetOptions[EvaluationNotebook[], CellContext -> Notebook]
Needs["LVAutils`"]
Autosave[True]
这是宏:
MyPrivatize[exposedCtxts : ({__String} | Null) : Null]:=
SelfDestruct@Module[{contBox,lvaBox,expCtxtBox,assembledStatements,strList},
contBox = MakeBoxes[SetOptions[EvaluationNotebook[], CellContext -> Notebook]];
lvaBox = MakeBoxes[Needs["LVAutils`"]];
assembledStatements = {lvaBox,MakeBoxes[Autosave[True]],"(*********)"};
assembledStatements = Riffle[assembledStatements,"\[IndentingNewLine]"]//RowBox;
writeAndEval[InputNotebook[],contBox];
writeAndEval[InputNotebook[],assembledStatements];
If[exposedCtxts =!= Null,
strList = Riffle[("\"" <> # <> "\"") & /@ exposedCtxts, ","];
expCtxtBox = RowBox[{"ExposeContexts", "[", RowBox[{"{", RowBox[strList], "}"}], "]"}];
writeAndEval[InputNotebook[],expCtxtBox];
]
]
现在,当我输入MyPrivatize[]
时,会创建私有上下文并加载我的标准包。现在让我们创建一个命令,它将打开一个具有自己的私有上下文的新的临时笔记本(这样你就可以放弃那里而不会有搞乱定义的风险),但是可以访问你当前的上下文。
SpawnScratch[] := SelfDestruct@Module[{nb,boxExpr,strList},
strList = Riffle[("\"" <> # <> "\"") & /@ $ContextPath, ","];
boxExpr = RowBox[{"MyPrivatize", "[",
RowBox[{"{", RowBox[strList], "}"}], "]"}];
nb = CreateDocument[];
writeAndEval[nb,boxExpr];
]
关于这一点很酷的是,由于SelfDestruct
,当命令运行时,它在当前笔记本中没有任何痕迹 - 这很好,因为否则它只会造成混乱。
对于额外的样式点,您可以使用InputAutoReplacements
为这些宏创建关键字触发器,但我会将其留作读者练习。
答案 18 :(得分:6)
困扰我关于内置作用域结构的一件事是它们一次评估所有局部变量定义,所以你不能写例如
With[{a = 5, b = 2 * a},
...
]
不久之前,我想出了一个名为WithNest的宏,它允许你这样做。我发现它很方便,因为它可以让你保持变量绑定本地,而不必像
那样Module[{a = 5,b},
b = 2 * a;
...
]
最后,我能找到的最好方法是使用一个特殊的符号来简化递归绑定列表,并将定义放入自己的包中以隐藏此符号。也许有人对这个问题有一个更简单的解决方案?
如果您想尝试一下,请将以下内容放入名为Scoping.m
的文件中:
BeginPackage["Scoping`"];
WithNest::usage=
"WithNest[{var1=val1,var2=val2,...},body] works just like With, except that
values are evaluated in order and later values have access to earlier ones.
For example, val2 can use var1 in its definition.";
Begin["`Private`"];
(* Set up a custom symbol that works just like Hold. *)
SetAttributes[WithNestHold,HoldAll];
(* The user-facing call. Give a list of bindings and a body that's not
our custom symbol, and we start a recursive call by using the custom
symbol. *)
WithNest[bindings_List,body:Except[_WithNestHold]]:=
WithNest[bindings,WithNestHold[body]];
(* Base case of recursive definition *)
WithNest[{},WithNestHold[body_]]:=body;
WithNest[{bindings___,a_},WithNestHold[body_]]:=
WithNest[
{bindings},
WithNestHold[With[List@a,body]]];
SyntaxInformation[WithNest]={"ArgumentsPattern"->{{__},_}};
SetAttributes[WithNest,{HoldAll,Protected}];
End[];
EndPackage[];
答案 19 :(得分:6)
我只是通过我的一个软件包查看其中,并找到了一些我定义的消息:Debug::<some name>
。默认情况下,它们会被关闭,因此不会产生太多开销。但是,我可以随便乱丢我的代码,如果我需要弄清楚代码的行为方式,我可以将它们打开。
答案 20 :(得分:5)
此代码生成一个调色板,将选择内容作为图像上载到Stack Exchange。在Windows上,提供了一个额外的按钮,可以更加忠实地呈现选择。
将代码复制到笔记本单元格并进行评估。然后从输出中弹出调色板,并使用Palettes -> Install Palette...
如果您遇到任何问题,请在此处发表评论。下载笔记本电脑版here。
Begin["SOUploader`"];
Global`palette = PaletteNotebook@DynamicModule[{},
Column[{
Button["Upload to SE",
With[{img = rasterizeSelection1[]},
If[img === $Failed, Beep[], uploadWithPreview[img]]],
Appearance -> "Palette"],
If[$OperatingSystem === "Windows",
Button["Upload to SE (pp)",
With[{img = rasterizeSelection2[]},
If[img === $Failed, Beep[], uploadWithPreview[img]]],
Appearance -> "Palette"],
Unevaluated@Sequence[]
]
}],
(* Init start *)
Initialization :>
(
stackImage::httperr = "Server returned respose code: `1`";
stackImage::err = "Server returner error: `1`";
stackImage[g_] :=
Module[
{getVal, url, client, method, data, partSource, part, entity,
code, response, error, result},
getVal[res_, key_String] :=
With[{k = "var " <> key <> " = "},
StringTrim[
First@StringCases[
First@Select[res, StringMatchQ[#, k ~~ ___] &],
k ~~ v___ ~~ ";" :> v],
"'"]
];
data = ExportString[g, "PNG"];
JLink`JavaBlock[
url = "http://stackoverflow.com/upload/image";
client =
JLink`JavaNew["org.apache.commons.httpclient.HttpClient"];
method =
JLink`JavaNew[
"org.apache.commons.httpclient.methods.PostMethod", url];
partSource =
JLink`JavaNew[
"org.apache.commons.httpclient.methods.multipart.\
ByteArrayPartSource", "mmagraphics.png",
JLink`MakeJavaObject[data]@toCharArray[]];
part =
JLink`JavaNew[
"org.apache.commons.httpclient.methods.multipart.FilePart",
"name", partSource];
part@setContentType["image/png"];
entity =
JLink`JavaNew[
"org.apache.commons.httpclient.methods.multipart.\
MultipartRequestEntity", {part}, method@getParams[]];
method@setRequestEntity[entity];
code = client@executeMethod[method];
response = method@getResponseBodyAsString[];
];
If[code =!= 200, Message[stackImage::httperr, code];
Return[$Failed]];
response = StringTrim /@ StringSplit[response, "\n"];
error = getVal[response, "error"];
result = getVal[response, "result"];
If[StringMatchQ[result, "http*"],
result,
Message[stackImage::err, error]; $Failed]
];
stackMarkdown[g_] :=
"![Mathematica graphics](" <> stackImage[g] <> ")";
stackCopyMarkdown[g_] := Module[{nb, markdown},
markdown = Check[stackMarkdown[g], $Failed];
If[markdown =!= $Failed,
nb = NotebookCreate[Visible -> False];
NotebookWrite[nb, Cell[markdown, "Text"]];
SelectionMove[nb, All, Notebook];
FrontEndTokenExecute[nb, "Copy"];
NotebookClose[nb];
]
];
(* Returns available vertical screen space,
taking into account screen elements like the taskbar and menu *)
screenHeight[] := -Subtract @@
Part[ScreenRectangle /. Options[$FrontEnd, ScreenRectangle],
2];
uploadWithPreview[img_Image] :=
CreateDialog[
Column[{
Style["Upload image to the Stack Exchange network?", Bold],
Pane[
Image[img, Magnification -> 1], {Automatic,
Min[screenHeight[] - 140, 1 + ImageDimensions[img][[2]]]},
Scrollbars -> Automatic, AppearanceElements -> {},
ImageMargins -> 0
],
Item[
ChoiceButtons[{"Upload and copy MarkDown"}, \
{stackCopyMarkdown[img]; DialogReturn[]}], Alignment -> Right]
}],
WindowTitle -> "Upload image to Stack Exchange?"
];
(* Multiplatform, fixed-width version.
The default max width is 650 to fit Stack Exchange *)
rasterizeSelection1[maxWidth_: 650] :=
Module[{target, selection, image},
selection = NotebookRead[SelectedNotebook[]];
If[MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]], selection],
$Failed, (* There was nothing selected *)
target =
CreateDocument[{}, WindowSelected -> False, Visible -> False,
WindowSize -> maxWidth];
NotebookWrite[target, selection];
image = Rasterize[target, "Image"];
NotebookClose[target];
image
]
];
(* Windows-only pixel perfect version *)
rasterizeSelection2[] :=
If[
MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]],
NotebookRead[SelectedNotebook[]]],
$Failed, (* There was nothing selected *)
Module[{tag},
FrontEndExecute[
FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial",
"MGF"]];
Catch[
NotebookGet@ClipboardNotebook[] /.
r_RasterBox :>
Block[{},
Throw[Image[First[r], "Byte", ColorSpace -> "RGB"], tag] /;
True];
$Failed,
tag
]
]
];
)
(* Init end *)
]
End[];
答案 21 :(得分:4)
我确信很多人遇到了他们运行某些东西的情况,意识到它不仅卡住了程序,而且他们还没有保存最后10分钟! < / p>
经过一段时间的努力,我有一天发现可以在 Mathematica 代码中创建自动保存。我认为使用这样的自动保存在过去帮助了我很多,而且我一直觉得可能性本身是很多人都不知道他们可以做的事情。
我使用的原始代码位于底部。感谢我的评论,我发现这是有问题的,并且使用ScheduledTask
(仅适用于 Mathematica 8)以另一种方式更好地执行此操作
此代码可在Sjoerd C. de Vries
的{{3}}中找到
(因为我不确定是否可以将其复制到此处,我只是将其作为链接保留。)
以下解决方案正在使用Dynamic
。它会每隔60秒保存一次笔记本,但只有当其单元格可见时才显然 。我将它留在这里只是为了完成的原因。 (以及 Mathematica 6和7的用户)
要解决这个问题,我在笔记本的开头使用这段代码:
Dynamic[Refresh[NotebookSave[]; DateString[], UpdateInterval -> 60]]
这将每60秒节省一次你的工作
我更喜欢它NotebookAutoSave[]
,因为它在处理输入之前保存,并且因为某些文件比输入更多文本。
我最初在这里找到它:this answer
请注意,一旦运行此行,即使您关闭并重新打开文件也会进行保存(只要启用了动态更新)。
此外,由于 Mathematica 中没有撤消,因此请注意不要删除所有内容,因为保存会使其不可逆转(作为预防措施,我会从每个完成的笔记本中删除此代码)
答案 22 :(得分:4)
这是由Alberto Di Lullo编写的(他似乎不在Stack Overflow上)。
CopyToClipboard
,适用于Mathematica 7(在Mathematica 8中内置)
CopyToClipboard[expr_] :=
Module[{nb},
nb = CreateDocument[Null, Visible -> False, WindowSelected -> True];
NotebookWrite[nb, Cell[OutputFormData@expr], All];
FrontEndExecute[FrontEndToken[nb, "Copy"]];
NotebookClose@nb];
原帖:http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html
我发现这个例程对于以普通的十进制形式将大的实数复制到剪贴板很有用。例如。 CopyToClipboard["123456789.12345"]
Cell[OutputFormData@expr]
整齐地删除了引号。
答案 23 :(得分:3)
我发现在开发包以将此键盘快捷方式添加到SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.tr
文件时非常有用。
(* Evaluate Initialization Cells: Real useful for reloading library changes. *)
Item[KeyEvent["i", Modifiers -> {Control, Command}],
FrontEndExecute[
FrontEndToken[
SelectedNotebook[],
"EvaluateInitialization"]]],
接下来为每个Packagename.m
我制作一个PackagenameTest.nb
笔记本进行测试,并将测试笔记本的前两个单元格设置为初始化单元格。在我放的第一个单元格中
Needs["PackageManipulations`"]
加载由Leonid编写的非常有用的PackageManipulations库。第二个单元格包含
PackageRemove["Packagename`Private`"]
PackageRemove["Packagename`"]
PackageReload["Packagename`"]
这些都是实际的包重装。请注意前两行只有Remove
所有符号,因为我希望保持上下文尽可能干净。
然后编写和测试包的工作流程就像这样。
Packagename.m
。PackagenameTest.nb
并执行CTRL + ALT + i
。这会导致初始化单元重新加载包,这使得测试变得非常简单。
答案 24 :(得分:3)
请记住,Mathematica Book也可以在http://reference.wolfram.com/legacy/v5_2/在线获取 - 虽然它被http://reference.wolfram.com
上的当前文档所取代。答案 25 :(得分:1)
以下函数format[expr_]
可用于缩进/格式化跨页面的无格式mathematica
表达式
indent[str_String, ob_String, cb_String, delim_String] :=
Module[{ind, indent, f, tab}, ind = 0; tab = " ";
indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
f[c_] := c;
f /@ Characters@str // StringJoin];
format[expr_] := indent[expr // InputForm // ToString, "[({", "])}", ";"];
(*
format[Hold@Module[{ind, indent, f, tab}, ind = 0; tab = " ";
indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
f[c_] := c;
f /@ Characters@str // StringJoin]]
*)
参考:https://codegolf.stackexchange.com/questions/3088/indent-a-string-using-given-parentheses