gpt4 book ai didi

wolfram-mathematica - 将未评估的函数存储在数学列表中

转载 作者:行者123 更新时间:2023-12-04 02:48:53 29 4
gpt4 key购买 nike

例子:

list:={ Plus[1,1], Times[2,3] }

在查看 list 时,我得到
{2,6}

我想让它们不被评估(如上所述),以便 list返回
{ Plus[1,1], Times[2,3] }

稍后我想评估列表序列中的函数以获得
{2,6}
list 中未评估函数的数量事先不知道。除了 Plus , 用户定义的函数,如 f[x_]可以存储在 list
我希望这个例子很清楚。

做这个的最好方式是什么?

最佳答案

最好的方法是将它们存储在 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

如果你坚持你的 build ,这里有一个方法:
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 .

编辑2

正如@Mr.Wizard 在另一个答案中指出的那样,有时您可能会发现拥有 Hold 更方便包裹在您的序列中的各个项目上。我在这里的评论是,一旦我们意识到将一种形式转换为另一种形式并返回非常容易,这两种形式的有用性就会被放大。以下函数将分割 Hold 内的序列进入持有元素 list :
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在持有元素 list 上,而不考虑评估。完成后,您可以将它们组合成一个 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]= {保持[Z 1 ],保持[S 1 ]}

和这里
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}

关于wolfram-mathematica - 将未评估的函数存储在数学列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6254538/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com