- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
SaveDefinitions
是Manipulate
的一个不错的选择。它使Manipulate
在“操纵”面板中存储用于创建它的所有定义。这样制作的机械手可以复制到空笔记本上,并且仍然可以单独工作。此外,您的包含许多“操作”的工作笔记本也不会变成一堆粉红色的盒子,打开后它下面会显示错误消息。大!
但是,所有这些好处都有其黑暗的一面,如果您不了解,它可能会给您带来极大的痛苦。我已经在工作了几天的笔记本中拥有此功能,但是我向您展示了一个重现玩具问题的分步玩具示例场景。
在这种情况下,您想创建一个Manipulate
来显示一个漂亮的波浪函数的图,因此您要定义它(请像这样设置窗口大小,这很重要):
该定义很好,因此我们下次将其保留,并使其成为初始化单元格。接下来,我们添加Manipulate
,并执行它。
f[x_] := x^2
Manipulate[
Plot[n f[x], {x, -3, 3}],
{n, 1, 4},
SaveDefinitions -> True
]
SaveDefinitions
来重新执行),并使用滑块进行一些操作。并向上滚动。
Information
(?)之间不会执行任何操作,根据In []数字检查(
In[1]
:f的def,
In[2]
第一个?,
In[3]
第二个)。
Manipulate
。
FullForm
揭示了其内部结构:
Manipulate[Plot[n*f[x],{x, -3, 3}],{{n, 2.44}, 1, 4},Initialization:>{f[x_] := x^2}]
Manipulate
的定义后没有重新评估它。一旦操作框出现在屏幕上,便会对其进行评估,并且您已经恢复了原来的定义。全局!
Manipulate
之外,我们还可以采取什么措施来防止Manipulate
的这种背后行为?
最佳答案
这是一个尝试。这个想法是用操纵代码中的DownValues
或其他...Values
来标识符号,并使用唯一的变量/符号代替它们来自动重命名它们。在克隆符号功能的帮助下,可以非常优雅地执行此处的想法,我有时会发现这很有用。下面的clone
函数将克隆给定的符号,从而产生具有相同全局定义的符号:
Clear[GlobalProperties];
GlobalProperties[] :=
{OwnValues, DownValues, SubValues, UpValues, NValues, FormatValues,
Options, DefaultValues, Attributes};
Clear[unique];
unique[sym_] :=
ToExpression[
ToString[Unique[sym]] <>
StringReplace[StringJoin[ToString /@ Date[]], "." :> ""]];
Attributes[clone] = {HoldAll};
clone[s_Symbol, new_Symbol: Null] :=
With[{clone = If[new === Null, unique[Unevaluated[s]], ClearAll[new]; new],
sopts = Options[Unevaluated[s]]},
With[{setProp = (#[clone] = (#[s] /. HoldPattern[s] :> clone)) &},
Map[setProp, DeleteCases[GlobalProperties[], Options]];
If[sopts =!= {}, Options[clone] = (sopts /. HoldPattern[s] :> clone)];
HoldPattern[s] :> clone]]
Manipulate
相同的参数,例如
myManipulate
。我将使用另一个:我将介绍的一些自定义包装器的
Manipulate
轻载
UpValues
。我将其称为
CloneSymbols
。这是代码:
ClearAll[CloneSymbols];
CloneSymbols /:
Manipulate[args___,CloneSymbols[sd:(SaveDefinitions->True)],after:OptionsPattern[]]:=
Unevaluated[Manipulate[args, sd, after]] /.
Cases[
Hold[args],
s_Symbol /; Flatten[{DownValues[s], SubValues[s], UpValues[s]}] =!= {} :>
clone[s],
Infinity, Heads -> True];
f[x_] := Sin[x];
g[x_] := x^2;
SaveDefinitions->True
选项包装在
CloneSymbols
包装器中:
Manipulate[Plot[ f[n g[x]], {x, -3, 3}], {n, 1, 4},
CloneSymbols[SaveDefinitions -> True]]
Manipulate
内代码中原始符号的定义,因为它们是其副本的副本,其定义已保存并现在用于初始化。我们可以查看此
FullForm
的
Manipulate
来确认:
Manipulate[Plot[f$37782011751740542578125[Times[n,g$37792011751740542587890[x]]],
List[x,-3,3]],List[List[n,1.9849999999999999`],1,4],RuleDelayed[Initialization,
List[SetDelayed[f$37782011751740542578125[Pattern[x,Blank[]]],Sin[x]],
SetDelayed[g$37792011751740542587890[Pattern[x,Blank[]]],Power[x,2]]]]]
f[x_]:=Cos[x];
g[x_]:=x;
Manipulate
的滑块,然后检查函数定义
?f
Global`f
f[x_]:=Cos[x]
?g
Global`g
g[x_]:=x
Manipulate
合理地独立于任何东西,可以安全地复制和粘贴。这里发生的事情如下:我们首先找到所有带有非平凡
DownValues
,
SubValues
或
UpValues
(也可以添加
OwnValues
)的符号,然后使用
Cases
和
clone
即时创建其克隆。然后,将所有克隆的符号用词法替换为
Manipulate
内的克隆,然后让
Manipulate
保存克隆的定义。这样,我们就可以对所涉及的功能进行“快照”,但不会以任何方式影响原始功能。
unique
函数解决。但是请注意,尽管以这种方式获得的
Manipulate
-s不会威胁到原始函数定义,但是它们通常仍将依赖于它们,因此人们不能认为它们完全独立于任何事物。人们将不得不走下依赖树并在其中克隆所有符号,然后重建它们之间的依赖关系,以在Manipulate中构造一个完全独立的“快照”。这是可行的,但更为复杂。
Manipulate
-s更新到函数的更改,但又不希望它们主动干预并更改任何全局定义时。我建议使用“指针”技术的一种变体:我们将再次用新的符号替换函数名称,但是,我们将使用
Manipulate
的
Initialization
选项简单地使这些符号成为“指针”,而不是在函数之后克隆这些新符号。到我们的函数,例如
Initialization:>{new1:=f,new2:=g}
。显然,重新评估此类初始化代码不会损害
f
或
g
的定义,与此同时,我们的
Manipulate
-s将对这些定义的更改做出响应。
Manipulate
初始化自动完成其余的工作。不幸的是,在此过程中,它遍历了依赖关系树,因此,我们的函数的定义也将包括在内,这是我们试图避免的事情。因此,相反,我们将显式构造
Initialize
选项。这是代码:
ClearAll[SavePointers];
SavePointers /:
Manipulate[args___,SavePointers[sd :(SaveDefinitions->True)],
after:OptionsPattern[]] :=
Module[{init},
With[{ptrrules =
Cases[Hold[args],
s_Symbol /; Flatten[{DownValues[s], SubValues[s], UpValues[s]}] =!= {} :>
With[{pointer = unique[Unevaluated[s]]},
pointer := s;
HoldPattern[s] :> pointer],
Infinity, Heads -> True]},
Hold[ptrrules] /.
(Verbatim[HoldPattern][lhs_] :> rhs_ ) :> (rhs := lhs) /.
Hold[defs_] :>
ReleaseHold[
Hold[Manipulate[args, Initialization :> init, after]] /.
ptrrules /. init :> defs]]]
ClearAll[f, g];
f[x_] := Sin[x];
g[x_] := x^2;
FullForm
的
Manipulate
:
In[454]:=
FullForm[Manipulate[Plot[f[n g[x]],{x,-3,3}],{n,1,4},
SavePointers[SaveDefinitions->True]]]
Out[454]//FullForm=
Manipulate[Plot[f$3653201175165770507872[Times[n,g$3654201175165770608016[x]]],
List[x,-3,3]],List[n,1,4],RuleDelayed[Initialization,
List[SetDelayed[f$3653201175165770507872,f],SetDelayed[g$3654201175165770608016,g]]]]
Manipulate
-s将响应我们函数的更新,同时对主要函数的定义无害。要付出的代价是它们不是独立的,并且如果未定义主要功能,它们将无法正确显示。因此,可以根据需要使用
CloneSymbols
包装器或
SavePointers
。
关于wolfram-mathematica - 保存定义被认为是危险的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6579644/
编辑:澄清一下,我明白为什么这段代码不起作用,我并不是要修复它,而是想了解如果这段代码可以在没有语义错误的情况下编译会有什么危险。 我发现下面的代码会导致静态语义错误。我知道这是因为 std::lis
我想知道 C# 枚举以及重复值会发生什么。我创建了以下小程序来测试: namespace ConsoleTest { enum TestEnum { FirstElem
正如我在另一个 SO 问题中指出的那样,我遇到了 this article .当我通过 MSVC7.1 编译 boost 1.40 时出现了这个问题,并且弹出了几个 C4251 警告。 现在,在阅读上
我有以下弹出窗口代码(客户端请求)。它使用 eval ,我知道这是危险的。有没有办法重写下面的脚本,使其不使用 (eval)? /* exported popup_default , popup_he
NTFS 文件可以有对象 ID。可以使用 FSCTL_SET_OBJECT_ID 设置这些 ID .然而,msdn article说: Modifying an object identifier c
我一直在学习命令行参数解析。关于这个已经有很长的线索了,我不想在这里挑起一个: Using getopts in bash shell script to get long and short com
这个问题在这里已经有了答案: How to configure ContextMenu buttons for delete and disabled in SwiftUI? (4 个回答) 4 个月
为什么在 linux 的中断处理程序中禁止 printk 或 (I/O)。?在什么情况下中断处理程序中的 I/O 会导致 linux 系统中的死锁? 最佳答案 关于 printk(),它是侵入性的。例
不是 Invoking virtual function and pure-virtual function from a constructor 的重复项: 以前的问题与 C++ 03 相关,而不是
我正在使用 lateinit 属性以避免使用 ?运算符(operator)。我有很多 View 属性是第一次在 getViews() 函数中分配的。如果该功能不存在,我的应用程序将与来自 Kotlin
我最近在使用 fputs 时遇到了问题:当使用 fputs 在文本文件中打印一些字符串时,我碰巧得到了除 A-Z、a-z、0-9 之外的其他字符(不属于字符串的字符) .我绝对确保所有字符串都以空字符
在仅包含字节数组的结构上使用 #pragma pack(1) 是否危险/有风险?例如。这个: #pragma pack(1) struct RpcMessage { uint8_t proto
我是一名优秀的程序员,十分优秀!