使用`With`和`Rules`列表 - 但不影响`With`的正常行为

时间:2011-03-04 02:03:10

标签: wolfram-mathematica

说我有一个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 - 所以它的工作原理就像我想要的那样。)

3 个答案:

答案 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

编辑:添加了ReleaseHoldHold对,以便在应用规则之前保持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]