Wolfram mathematica 在“规则”列表中使用“With”-但不影响“With”的正常行为`
假设我有一个Wolfram mathematica 在“规则”列表中使用“With”-但不影响“With”的正常行为`,wolfram-mathematica,Wolfram Mathematica,假设我有一个规则列表 rules = {a -> b, c -> d}; 我在整个笔记本中都使用它。然后,在某一点上,希望在表达式中进行任何其他求值之前应用规则是有意义的。通常,如果你想要这样的东西,你会使用 In[2]:= With[{a=b,c=d}, expr[a,b,c,d]] Out[2]= expr[b, b, d, d] 如何获取规则并将其插入With的第一个参数中 编辑 这两种解决方案都无法实现我所期望的目标,但我本应进一步强调这一点。见上面粗体部分 例如,让我
规则列表
rules = {a -> b, c -> d};
我在整个笔记本中都使用它。然后,在某一点上,希望在表达式中进行任何其他求值之前应用规则是有意义的。通常,如果你想要这样的东西,你会使用
In[2]:= With[{a=b,c=d}, expr[a,b,c,d]]
Out[2]= expr[b, b, d, d]
如何获取规则
并将其插入With
的第一个参数中
编辑 这两种解决方案都无法实现我所期望的目标,但我本应进一步强调这一点。见上面粗体部分 例如,让我们看看
rules = {a -> {1, 2}, c -> 1};
如果将中的这些值与一起使用,则
In[10]:= With[{a={1,2},c=1}, Head/@{a,c}]
Out[10]= {List,Integer}
带有规则的的某些版本产生
In[11]:= WithRules[rules, Head/@{a,c}]
Out[11]= {Symbol, Symbol}
(事实上,我没有注意到Andrew的答案具有属性HoldRest
,因此它的工作原理与我所希望的一样。)您想使用它来构建With语句。这是一种方法;可能有更简单的方法:
In[1]:= SetAttributes[WithRules, HoldRest]
In[2]:= WithRules[rules_, expr_] :=
With @@ Append[Apply[Set, Hold@rules, {2}], Unevaluated[expr]]
测试一下:
In[3]:= f[args___] := Print[{args}]
In[4]:= rules = {a -> b, c -> d};
In[5]:= WithRules[rules, f[a, c]]
During evaluation of In[5]:= {b,d}
(我使用了Print,因此任何涉及我过早地意外评估expr的错误都会变得明显。)我使用以下形式的with rules
已经很长时间了。与Andrew Moylan发布的版本相比,它是按顺序绑定的,因此您可以使用规则[{a->b+1,b->2},expr]
说,并将a
扩展到3
:
SetAttributes[WithRules, HoldRest]
WithRules[rules_, expr_] := ReleaseHold@Module[{notSet}, Quiet[
With[{args = Reverse[rules /. Rule[a_, b_] -> notSet[a, b]]},
Fold[With[{#2}, #1] &, Hold@expr, args]] /. notSet -> Set,
With::lvw]]
这也是作为一个发布的,正如上面提到的,它已经(至少)在usenet上讨论过几次:
嗯
编辑:添加了一个ReleaseHold
,Hold
对,以使expr
在应用规则之前保持未计算状态。Andrew解决方案的一个问题是,它将问题映射回with,并且不接受下标变量。因此,下面生成消息
WithRules[{Subscript[x, 1] -> 2, Subscript[x, 2] -> 3},
Power[Subscript[x, 1], Subscript[x, 2]]]
鉴于With
在其主体上执行语法替换,我们可以按如下方式交替设置规则:
ClearAll[WithRules]; SetAttributes[WithRules, HoldRest];
WithRules[r : {(_Rule | _RuleDelayed) ..}, body_] :=
ReleaseHold[Hold[body] /. r]
然后
编辑:针对Leonid提出的合理担忧,以下版本是安全的:
ClearAll[WithRules3]; SetAttributes[WithRules3, HoldRest];
WithRules3[r : {(_Rule | _RuleDelayed) ..}, body_] :=
Developer`ReplaceAllUnheld[Unevaluated[body], r]
然后
编辑2:即使使用规则3也不能完全等同于Andrew的版本:
In[206]:= WithRules3[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[206]= f[y_] :> Function[x, x + y + z]
In[207]:= WithRules[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[207]= f[y$_] :> Function[x$, x$ + y$ + 2]
谢谢Janus!既然你提到了它,我至少记得其中一个“顺序和”。你的答案与我想要的不太一样-请看编辑。@Simon,将其修改为实际答案:)如果这是所需的全部内容,就不能只做Unevaluated[Subscript[x,1]^Subscript[x,2]/。{Subscript[x,1]->2,Subscript[x,2]->3}
?@Mr.Wizard是的,这是另一种选择。With和基于规则的替换在语义上存在细微的差异,当“body”中的代码具有嵌套的作用域结构,局部变量名与规则中的某些符号冲突时,就会出现这种差异。使用With将有利于内部构造,使用规则将有利于外部规则,并破坏内部作用域构造绑定。什么是有利的,取决于所讨论的代码,但我的感觉是“With”方式通常更安全。不错。拥有一个处理非符号(如下标变量)的With版本是一个非常方便的概括。@Andrew,正如我已经评论过的,这实际上不是一个带有
的版本,而是一个将外部规则应用程序自动化到未赋值表达式的实用程序。例如,尝试使用规则[{x->y},f[y\u]:>Function[x,x+y]]
和您和@Sasha的解决方案,以查看差异。在词汇范围内,我认为规则替代更危险。尤其是Mathematica中函数抽象(函数
)中的漏洞,上面的代码片段演示了其中一个。
In[194]:= WithRules3[{Subscript[x, 1] -> 2, Subscript[x, 2] -> 3},
Subscript[x, 1]^Subscript[x, 2]]
Out[194]= 8
In[195]:= WithRules3[{x -> y}, f[y_] :> Function[x, x + y]]
Out[195]= f[y_] :> Function[x, x + y]
In[206]:= WithRules3[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[206]= f[y_] :> Function[x, x + y + z]
In[207]:= WithRules[{z -> 2}, f[y_] :> Function[x, x + y + z]]
Out[207]= f[y$_] :> Function[x$, x$ + y$ + 2]