说我有一个Rules
rules = {a -> b, c -> d};
我在整个笔记本中使用它。然后,在某一点上,在表达式中进行任何其他评估之前,希望规则应用是有意义的。通常,如果您想要这样的东西,您可以使用
In[2]:= With[{a=b,c=d}, expr[a,b,c,d]]
Out[2]= expr[b, b, d, d]
如何取rules
并将其插入With
的第一个参数?
两者一些解决方案失败了我所寻求的所有 - 但我应该更多地强调这一点。见上面的粗体部分。
例如,让我们看一下
rules = {a -> {1, 2}, c -> 1};
如果我在With
中使用这些vaules,我会
In[10]:= With[{a={1,2},c=1}, Head/@{a,c}]
Out[10]= {List,Integer}
某些版本的WithRules
会产生
In[11]:= WithRules[rules, Head/@{a,c}]
Out[11]= {Symbol, Symbol}
(实际上,我没有注意到Andrew的答案有属性HoldRest
- 所以它的工作原理就像我想要的那样。)
答案 0 :(得分:11)
您希望使用Hold来构建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的错误都会显而易见。)
答案 1 :(得分:2)
我长期使用以下WithRules
形式。与安德鲁·莫兰(Andrew Moylan)发布的相比,它会顺序绑定,这样你就可以说WithRules[{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]]
这也是answer to an unrelated question发布的,如上所述,它已经在usenet上讨论过(至少)几次:
HTH
编辑:添加了ReleaseHold
,Hold
对,以便在应用规则之前保持expr
未评估。
答案 2 :(得分:1)
Andrew解决方案的一个问题是它将问题映射回With,并且不接受下标变量。所以以下生成消息。
WithRules[{Subscript[x, 1] -> 2, Subscript[x, 2] -> 3},
Power[Subscript[x, 1], Subscript[x, 2]]]
鉴于With
在其主体上执行语法替换,我们可以按如下方式设置WithRules:
ClearAll[WithRules]; SetAttributes[WithRules, HoldRest];
WithRules[r : {(_Rule | _RuleDelayed) ..}, body_] :=
ReleaseHold[Hold[body] /. r]
然后
In[113]:= WithRules[{Subscript[x, 1] -> 2,
Subscript[x, 2] -> 3}, Subscript[x, 1]^Subscript[x, 2]]
Out[113]= 8
编辑:解决Leonid提出的有效问题,以下版本将是安全的:
ClearAll[WithRules3]; SetAttributes[WithRules3, HoldRest];
WithRules3[r : {(_Rule | _RuleDelayed) ..}, body_] :=
Developer`ReplaceAllUnheld[Unevaluated[body], r]
然后
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]
编辑2 :即使WithRules3也不完全等同于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]