Wolfram mathematica Mathematica模块与With或Block-指南,使用经验法则?
Leonid在他的书的第四章中写道:“……模块、块和With。这些构造在Mathematica书和Mathematica帮助中有详细的解释,所以我将在这里就它们说几句……” 从我所读到的(能找到的)来看,我仍然一无所知。对于打包函数,我(简单地)使用模块,因为它可以工作,而且我知道其构造。但这可能不是最好的选择。我(从文档中)不完全清楚何时、何地以及为什么要使用With(或Block)Wolfram mathematica Mathematica模块与With或Block-指南,使用经验法则?,wolfram-mathematica,Wolfram Mathematica,Leonid在他的书的第四章中写道:“……模块、块和With。这些构造在Mathematica书和Mathematica帮助中有详细的解释,所以我将在这里就它们说几句……” 从我所读到的(能找到的)来看,我仍然一无所知。对于打包函数,我(简单地)使用模块,因为它可以工作,而且我知道其构造。但这可能不是最好的选择。我(从文档中)不完全清楚何时、何地以及为什么要使用With(或Block) 问题。对于何时使用模块、With或Block(对于包中的函数),是否有经验法则/指南?与模块相比是否存在限制?
问题。对于何时使用模块、With或Block(对于包中的函数),是否有经验法则/指南?与模块相比是否存在限制?医生们说,使用智能手机速度更快。我希望能够保护Me=选择=模块(或另一个构造)。
正如你提到的,有很多事情要考虑,并且详细的讨论是可能的。但这里有一些经验法则,我大部分时间都会用到:
Module[{x},…]
是最安全的,如果其中一个
Integrate[…,x]
)Block[{x},…]
通常会更快。(请注意,在完全由您编写的项目中,对这些条件充满信心是一个合理的“封装”标准,您可能希望强制执行,因此在这些情况下,块通常是一个合理的选择。)
With[{x=…},expr]
是唯一在Hold[…]内注入x值的作用域构造。这是有用和重要的<带
的代码>可以比块快或慢,具体取决于expr和所采用的特定计算路径<但是,使用的code>灵活性较低,因为您无法在expr内更改x的定义。这里可以看到块
和模块
之间更实际的区别:
Module[{x}, x]
Block[{x}, x]
(*
-> x$1979
x
*)
因此,如果希望返回egx
,可以使用Block
。比如说,
Plot[D[Sin[x], x], {x, 0, 10}]
不起作用;要使它发挥作用,可以使用
Plot[Block[{x}, D[Sin[x], x]], {x, 0, 10}]
(当然这并不理想,这只是一个例子)
另一种用法类似于块[{$RecursionLimit=1000},…]
,它临时更改$RecursionLimit
(模块
在重命名$RecursionLimit
时不会工作)
人们也可以使用Block
来阻止对某物的评估,例如
Block[{Sin}, Sin[.5]] // Trace
(*
-> {Block[{Sin},Sin[0.5]],Sin[0.5],0.479426}
*)
也就是说,它返回Sin[0.5]
,该值仅在块
完成执行后计算。这是因为块中的Sin
只是一个符号,而不是正弦函数。你甚至可以这样做
Block[{Sin = Cos[#/4] &}, Sin[Pi]]
(*
-> 1/Sqrt[2]
*)
(使用Trace
查看其工作原理)。因此,您也可以使用Block
在本地重新定义内置函数:
Block[{Plus = Times}, 3 + 2]
(*
-> 6
*)
安德鲁已经提供了一个非常全面的答案。我只想总结一下,Module
用于定义可以在函数定义范围内重新定义的局部变量,而With
用于定义不能被定义的局部常量。您也不能基于在同一With
语句中设置的另一个局部常数的定义来定义局部常数,或者在定义的左侧有多个符号。也就是说,以下方法不起作用
With[{{a,b}= OptionValue /@ {opt1,opt2} }, ...]
我倾向于用模块
来设置复杂的函数定义,并用封装一个。我首先使用
在中设置所有本地常量,例如传递给函数的数据的长度
,如果需要,然后根据需要设置其他本地变量。原因是,与
的结合要快一点,因为你确实有常数而不是变量。我想提一提关于块
和模块
之间区别的官方文档,可在上找到。根据你的例子,我尝试了这一点。清除[x];x=1;模块[{x},x]-它返回了(对我来说)意外的结果x$114。带有$RecursionLimit的示例非常有用。关于您带有绘图的示例
。我相信Plot
有一些启发性的方法来决定是在数值被x
替换之前还是之后才对其参数求值。使用块
的唯一区别在于,当绘图
将计算其参数时,会发生变化。它没有说明块
是如何工作的。您可以通过在Plot
的参数中包含Print[x]
语句来验证这一点。(在Plot
中将未记录的Evaluated
选项设置为False
似乎不起作用。)我的观点是Plot
的问题在于参数的计算。使其工作的正确方法是Plot[Evaluate[…],…]
。将参数包装在块
中也解决了这一问题,这只是偶然的,是由于绘图
的内部试探法决定了求值顺序。@ndroock1是什么让这件事出乎意料?其思想是,Module
重命名其参数,因此它们不受Module
正文外定义的影响实际上,(至少在v7中)您也不能根据Module
中的其他变量定义局部变量,至少在定义阶段,即Module[{a=1,b=a},b]
返回a
而块[{a=1,b=a},b]