快速方式在具有保持参数的函数中键入检查符号

Mr.*_*ard 7 wolfram-mathematica typechecking

可以使用以下方法测试参数是否为没有显式值的符号:

func[s_Symbol] = ...
Run Code Online (Sandbox Code Playgroud)

但是,如果函数具有Hold属性,则该模式将匹配所有符号,而不仅仅是那些没有显式值的符号.我可以用:

func[s_] /; Head[s] === Symbol = ...
Run Code Online (Sandbox Code Playgroud)

但这会带来比我想要的更高的性能损失.添加规则_Symbol对性能的影响相当小,并且HoldFirst似乎没有任何性能损失,但是Head[s] === Symbol在一个简单的函数上有很大的开销.与测试ValueQMatchQ[s, _Symbol]甚至更慢.

为了澄清,我希望有两个不同的定义 func ,一个用于未分配的符号,另一个用于其他参数.

有更快的方法吗?


时序:

f[x_] = 0;

f /@ Range@1*^6; // Timing

f[s_Symbol] = 1;

f /@ Range@1*^6; // Timing
Run Code Online (Sandbox Code Playgroud)
   {0.391, Null}
   {0.531, Null}
Remove[f]
SetAttributes[f, HoldFirst]

f[x_] = 0;

f /@ Range@1*^6; // Timing

f[s_] /; Head[s] === Symbol = 1;

f /@ Range@1*^6; // Timing
Run Code Online (Sandbox Code Playgroud)
   {0.39, Null}
   {1.157, Null}

WRe*_*ach 6

通过将持有的符号参数委托给非持有的辅助函数,您可以获得与最快的运行时间相媲美的性能g:

Remove[f, g]
SetAttributes[f, HoldFirst]
f[_] = 0;
f[s_Symbol] := g[s]
g[_Symbol] = 1;
g[_] = 0;
Run Code Online (Sandbox Code Playgroud)


Sas*_*sha 4

s_Symbol在带有属性的代码中使用模式HoldFirst将提高性能:

In[121]:= Remove[f]
SetAttributes[f, HoldFirst]
f[s_Symbol] /; Head[s] === Symbol = 1;
f[_] = 0;

In[125]:= f /@ Range@1*^6; // Timing

Out[125]= {1.217, Null}

In[130]:= Remove[f2]
f2[s_Symbol] = 1;
f2[_] = 0;

In[133]:= f2 /@ Range@1*^6; // Timing

Out[133]= {1.123, Null}
Run Code Online (Sandbox Code Playgroud)