最好的方法是将它们存储在Hold,而不是List,像这样:
In[255]:= f[x_] := x^2;
lh = Hold[Plus[1, 1], Times[2, 3], f[2]]
Out[256]= Hold[1 + 1, 2 3, f[2]]
通过这种方式,您可以完全控制它们。在某些时候,您可以致电ReleaseHold 来评估它们:
In[258]:= ReleaseHold@lh
Out[258]= Sequence[2, 6, 4]
如果您想要列表中的结果而不是Sequence,您可以只使用List@@lh。如果您需要评估特定的,只需使用Part 提取它:
In[261]:= lh[[2]]
Out[261]= 6
如果你坚持自己的建设,这里有一个办法:
In[263]:= l:={Plus[1,1],Times[2,3],f[2]};
Hold[l]/.OwnValues[l]
Out[264]= Hold[{1+1,2 3,f[2]}]
编辑
如果您有一些带有UpValues 的函数/符号甚至可以在Hold 内部进行计算,您可能希望使用HoldComplete 代替Hold。
EDIT2
正如@Mr.Wizard 在另一个答案中指出的那样,有时您可能会发现将Hold 包裹在序列中的各个项目周围会更方便。我在这里的评论是,一旦我们意识到将一种形式转换为另一种形式并返回非常容易,这两种形式的有用性就会被放大。以下函数会将Hold 中的序列拆分为持有项目列表:
splitHeldSequence[Hold[seq___], f_: Hold] := List @@ Map[f, Hold[seq]]
例如,
In[274]:= splitHeldSequence[Hold[1 + 1, 2 + 2]]
Out[274]= {Hold[1 + 1], Hold[2 + 2]}
将它们重新组合成一个 Hold 更加容易 - 只需 Apply Join:
In[275]:= Join @@ {Hold[1 + 1], Hold[2 + 2]}
Out[275]= Hold[1 + 1, 2 + 2]
这两种不同的形式在不同的情况下很有用。您可以轻松地在持有项目列表中使用诸如Union、Select、Cases 之类的内容,而无需过多考虑评估。完成后,您可以将它们组合回单个 Hold,例如,作为未评估的参数序列提供给某个函数。
编辑 3
根据@ndroock1 的请求,这里有一个具体的例子。设置:
l = {1, 1, 1, 2, 4, 8, 3, 9, 27}
S[n_] := Module[{}, l[[n]] = l[[n]] + 1; l]
Z[n_] := Module[{}, l[[n]] = 0; l]
将函数放入Hold:
In[43]:= held = Hold[Z[1], S[1]]
Out[43]= Hold[Z[1], S[1]]
exec 函数的外观如下:
exec[n_] := MapAt[Evaluate, held, n]
现在,
In[46]:= {exec[1], exec[2]}
Out[46]= {Hold[{0, 1, 1, 2, 4, 8, 3, 9, 27}, S[1]], Hold[Z[1], {1, 1, 1, 2, 4, 8, 3, 9, 27}]}
请注意,原始变量held 保持不变,因为我们对副本进行了操作。另请注意,原始设置包含可变状态 (l),这在 Mathematica 中不是很惯用。特别是,评估的顺序很重要:
In[61]:= Reverse[{exec[2], exec[1]}]
Out[61]= {Hold[{0, 1, 1, 2, 4, 8, 3, 9, 27}, S[1]], Hold[Z[1], {2, 1, 1, 2, 4, 8, 3, 9, 27}]}
这是否需要取决于具体需求,我只是想指出这一点。此外,虽然上面的exec 是根据请求的规范实现的,但它隐含地依赖于全局变量l,我认为它是bad practice。
可以实现存储@Mr.Wizard 建议的函数的另一种方法,例如喜欢
In[63]:= listOfHeld = splitHeldSequence[held]
输出[63]= {保持[Z1],保持[S1]}
这里
In[64]:= execAlt[n_] := MapAt[ReleaseHold, listOfHeld, n]
In[70]:= l = {1, 1, 1, 2, 4, 8, 3, 9, 27} ;
{execAlt[1], execAlt[2]}
Out[71]= {{{0, 1, 1, 2, 4, 8, 3, 9, 27}, Hold[S[1]]}, {Hold[Z[1]], {1, 1, 1, 2, 4, 8, 3, 9, 27}}}
关于可变性和对全局变量的依赖性的相同内容也出现在此处。最后一种形式也更适合查询函数类型:
getType[n_, lh_] := lh[[n]] /. {Hold[_Z] :> zType, Hold[_S] :> sType, _ :> unknownType}
例如:
In[172]:= getType[#, listOfHeld] & /@ {1, 2}
Out[172]= {zType, sType}