Why does Default behave like this?

落花浮王杯 提交于 2019-11-29 06:44:52

问题


One may set a Default value for the arguments of a function:

Default[f] = 5;

And then use:

f[a_, b_.] := {a, b}

f[1, 2]
f[1]
   {1, 2}
   {1, 5}

This creates the following Values:

DefaultValues[f]
DownValues[f]
   {HoldPattern[Default[f]] :> 5}
   {HoldPattern[f[a_, b_.]] :> {a, b}}

From this one might think that the value 5 is not fixed in the definition of f, but addresses the DefaultValues assignment. However, if we change the DefaultValues, either directly or using:

Default[f] = 9;

DefaultValues[f]
   {HoldPattern[Default[f]] :> 9}

and use f again:

f[1]
   {1, 5}

we see that the new value is not used.

Therefore, my questions are:

  • Why does the default value used by f[a_, b_.] := {a, b} not change with DefaultValues?

  • Where is the real default value (5) stored, since it does not appear in either DownValues or DefaultValues?


回答1:


Not an answer, but:
Using the behaviour that the original default is kept until the function is redefined suggests a quick work-around:

Define a global variable for the Default before any other definitions are made.

In[1]:= Default[f]:=$f
In[2]:= f[a_.]:=a

In[3]:= f[]
Out[3]= $f

In[4]:= $f=5; f[]
Out[5]= 5
In[6]:= $f=6; f[]
Out[7]= 6
In[8]:= $f=.; f[]
Out[9]= $f

This also works for Optional

In[1]:= g[a_:$g] := a

In[2]:= g[]
Out[2]= $g

In[3]:= $g=1; g[]
Out[4]= 1



回答2:


From the documentation,

The necessary values for Default[f] must always be defined before _. is used as an argument of f.

Redefining f after setting Default[f] = 9; uses the new default value. So my guess is it is defined internally the first time, f is defined, and doesn't change even if DefaultValue@f stores the new value.




回答3:


I have found that this behavior in the case of local rules is due to specifics of internals of RuleDelayed.

Compare:

In[1]:= Default[f] = 5;
replaceAll[f[1], 
  f[a_, b_.] :> Unevaluated@{a, b}] /. (Default[f] = 9; replaceAll) ->
   ReplaceAll

Default[f] = 5;
Block[{RuleDelayed}, 
 replaceAll[f[1], 
   f[a_, b_.] :> Unevaluated@{a, b}] /. (Default[f] = 9; 
    replaceAll) -> ReplaceAll]

Out[2]= {1, 5}

Out[4]= Unevaluated[{1, 9}]

One can see that Blocking RuleDelayed makes local rules to behave as one could expect.



来源:https://stackoverflow.com/questions/6337753/why-does-default-behave-like-this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!