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

nil*_*ock 10 wolfram-mathematica

例:

list:={ Plus[1,1], Times[2,3] }
Run Code Online (Sandbox Code Playgroud)

看着list,我明白了

{2,6}
Run Code Online (Sandbox Code Playgroud)

我想让他们不受评估(如上所述)以便list返回

{ Plus[1,1], Times[2,3] }
Run Code Online (Sandbox Code Playgroud)

后来我想评估列表序列中的函数来获取

{2,6}
Run Code Online (Sandbox Code Playgroud)

未评估的函数的数量list事先是未知的.此外Plus,f[x_]可以存储用户定义的功能list

我希望这个例子很清楚.

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

Leo*_*rin 10

最好的方法是存储它们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]]
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以完全控制它们.在某些时候,您可以打电话ReleaseHold来评估它们:

In[258]:= ReleaseHold@lh

Out[258]= Sequence[2, 6, 4]
Run Code Online (Sandbox Code Playgroud)

如果您希望将结果放在列表中而不是Sequence,则可以使用List@@lh.如果您需要评估特定的一个,只需使用Part它来提取它:

In[261]:= lh[[2]]

Out[261]= 6
Run Code Online (Sandbox Code Playgroud)

如果你坚持你的建设,这是一种方式:

In[263]:= l:={Plus[1,1],Times[2,3],f[2]};
Hold[l]/.OwnValues[l]

Out[264]= Hold[{1+1,2 3,f[2]}]
Run Code Online (Sandbox Code Playgroud)

编辑

如果你有一些功能/符号UpValues甚至可以在里面评估Hold,你可能想用它HoldComplete来代替Hold.

EDIT2

正如@W.Wizard在另一个答案中指出的那样,有时您会发现Hold在序列中包裹个别项目会更方便.我在这里的评论是,一旦我们意识到将这一种形式转换为另一种形式并将其转化为非常容易,两种形式的有用性就会被放大.以下函数将序列内部拆分Hold为保留项目列表:

splitHeldSequence[Hold[seq___], f_: Hold] := List @@ Map[f, Hold[seq]]
Run Code Online (Sandbox Code Playgroud)

例如,

In[274]:= splitHeldSequence[Hold[1 + 1, 2 + 2]]

Out[274]= {Hold[1 + 1], Hold[2 + 2]}
Run Code Online (Sandbox Code Playgroud)

将它们组合成一个单元Hold甚至更容易 - 只需Apply Join:

In[275]:= Join @@ {Hold[1 + 1], Hold[2 + 2]}

Out[275]= Hold[1 + 1, 2 + 2]
Run Code Online (Sandbox Code Playgroud)

这两种不同的形式在不同的情况下是有用的.您可以轻松地使用的东西,如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]
Run Code Online (Sandbox Code Playgroud)

将功能放入Hold:

In[43]:= held = Hold[Z[1], S[1]]

Out[43]= Hold[Z[1], S[1]]
Run Code Online (Sandbox Code Playgroud)

以下是该exec函数的外观:

exec[n_] := MapAt[Evaluate, held, n]
Run Code Online (Sandbox Code Playgroud)

现在,

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}]}
Run Code Online (Sandbox Code Playgroud)

请注意,原始变量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}]}
Run Code Online (Sandbox Code Playgroud)

是否需要这取决于具体需求,我只想指出这一点.此外,虽然exec上述内容是根据请求的规范实现的,但它隐含地取决于全局变量l,我认为这是一种不好的做法.

另一种存储由@ Mr.Wizard建议的功能的方法可以实现,例如

在[63]中:= listOfHeld = splitHeldSequence [持有]

Out [63] = {Hold [Z 1 ],Hold [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}}}
Run Code Online (Sandbox Code Playgroud)

关于可变性和对全局变量的依赖性的相同评论也在这里.最后一种形式也更适合查询函数类型:

getType[n_, lh_] := lh[[n]] /. {Hold[_Z] :> zType, Hold[_S] :> sType, _ :> unknownType}
Run Code Online (Sandbox Code Playgroud)

例如:

In[172]:= getType[#, listOfHeld] & /@ {1, 2}

Out[172]= {zType, sType}
Run Code Online (Sandbox Code Playgroud)


acl*_*acl 7

首先想到的是不使用List,而是使用这样的东西:

 SetAttributes[lst, HoldAll];
 heldL=lst[Plus[1, 1], Times[2, 3]]
Run Code Online (Sandbox Code Playgroud)

肯定会有更多博学的建议!


Mr.*_*ard 5

您还可以Hold在要保留的每个元素上使用:

a = {Hold[2 + 2], Hold[2*3]}
Run Code Online (Sandbox Code Playgroud)

您可以使用HoldForm在任一元素或列表,如果你想要的名单没有出现Hold明显的:

b = {HoldForm[2 + 2], HoldForm[2*3]}

c = HoldForm@{2 + 2, 2*3}
Run Code Online (Sandbox Code Playgroud)
   {2 + 2, 2 * 3}

您可以使用以下方法恢复评估表单ReleaseHold:

a // ReleaseHold
b // ReleaseHold
c // ReleaseHold

Out[8]= {4, 6}

Out[9]= {4, 6}

Out[10]= {4, 6}
Run Code Online (Sandbox Code Playgroud)

形式Hold[2+2, 2*3]或者说,ab上面是好的,因为你可以很容易地与如增加条款Append.对于b类型是逻辑上:

Append[b, HoldForm[8/4]]
Run Code Online (Sandbox Code Playgroud)

用于Hold[2+2, 2*3]:

Hold[2+2, 2*3] ~Join~ Hold[8/4]
Run Code Online (Sandbox Code Playgroud)