是否可以定义在给定位置保存参数的函数?

还是做类似HoldLast的事情作为HoldFirst的对应物?

最佳答案

据我所知,就没有HoldN属性而言,您不能直接执行此操作。
但是,下面有一种应根据您的要求执行的变通方法。

拟议的解决方案
一种简单的方法是定义一个辅助函数来完成主要工作,然后将您的“ main”函数(实际上将被调用的函数)定义为HoldAll,如下所示:

In[437]:=
SetAttributes[f, HoldAll];
f[a_, b_, c_] :=
   faux[a, Unevaluated[b], c];
faux[a_, b_, c_] := Hold[a, b, c]

In[440]:= f[1^2, 2^2, 3^2]
Out[440]= Hold[1, 2^2, 9]

您不必将faux暴露在顶层,而可以将所有内容包装在Module[{faux}, your definitions]中。

通过元编程实现自动化
此过程可以自动化。这是函数签名的简化解析器,用于提取模式名称(注意-确实是简化的):
splitHeldSequence[Hold[seq___], f_: Hold] := List @@ Map[f, Hold[seq]];

getFunArguments[Verbatim[HoldPattern][Verbatim[Condition][f_[args___], test_]]] :=
     getFunArguments[HoldPattern[f[args]]];

getFunArguments[Verbatim[HoldPattern][f_[args___]]] :=
     FunArguments[FName[f], FArgs @@ splitHeldSequence[Hold[args]]];

(*This is a simplistic "parser".It may miss some less trivial cases*)

getArgumentNames[args__FArgs] :=
   args //. {
     Verbatim[Pattern][tag_, ___] :> tag,
     Verbatim[Condition][z_, _] :> z,
     Verbatim[PatternTest][z_, _] :> z
   };

使用此代码,我们可以编写以下自定义定义运算符:
ClearAll[defHoldN];
SetAttributes[defHoldN, HoldFirst];
defHoldN[SetDelayed[f_[args___], rhs_], n_Integer] :=
   Module[{faux},
      SetAttributes[f, HoldAll];
      With[{heldArgs =
         MapAt[
            Unevaluated,
            Join @@ getArgumentNames[getFunArguments[HoldPattern[f[args]]][[2]]],
            n]
         },
        SetDelayed @@ Hold[f[args], faux @@ heldArgs];
        faux[args] := rhs]]

这将分析您的原始定义,提取模式名称,将感兴趣的参数包装在Unevaluated中,引入局部faux,并进行两步定义-基本上是我们手动执行的步骤。我们需要SetDelayed @@ ..愚弄With的变量重命名机制,以便它不会在l.h.s上重命名我们的模式变量。例:
In[462]:=
ClearAll[ff];
defHoldN[ff[x_,y_,z_]:=Hold[x,y,z],2]

In[464]:= ?ff
Global`ff
Attributes[ff]={HoldAll}

ff[x_,y_,z_]:=faux$19106@@Hold[x,Unevaluated[y],z]

In[465]:= ff[1^2,2^2,3^2]
Out[465]= Hold[1,2^2,9]


笔记
请注意,将其概括为需要保留参数的位置列表很简单。通常,您需要一个更好的模式解析器,但是上面的简单解析器可能是一个好的开始。还要注意,这种构造会产生一些运行时开销,并且当您使用Modulefaux main时,Clear生成的辅助功能Remove不会被垃圾收集。 -您可能需要为使用defHoldN生成的函数引入特殊的析构函数。有关此问题的另一种解决方法,请参见我在this线程中的帖子(我在其中介绍了makeHoldN函数的帖子)。

关于wolfram-mathematica - 保留任何论点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7255999/

10-09 06:47