【问题标题】:Why does Default behave like this?为什么默认行为会这样?
【发布时间】:2011-06-14 00:01:10
【问题描述】:

可以为函数的参数设置Default 值:

Default[f] = 5;

然后使用:

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

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

这将创建以下值:

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

由此可能会认为5 的值在f 的定义中并不固定,而是针对DefaultValues 赋值。但是,如果我们直接更改DefaultValues,或者使用:

Default[f] = 9;

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

并再次使用f

f[1]
 {1, 5}

我们看到新值没有被使用。

因此,我的问题是:

  • 为什么f[a_, b_.] := {a, b}使用的默认值不随DefaultValues变化?

  • 真正的默认值 (5) 存储在哪里,因为它既没有出现在 DownValuesDefaultValues 中?

【问题讨论】:

  • +1 很好很清晰。让我们希望得到同样的答案!
  • W:您没有将默认值定义为 f[a_,b_:5]:=... 的任何原因?
  • @yoda:因为idea 能够在需要时更改默认值。
  • @yoda 另外,如果Default 值很长和/或经常使用,那么写_. 会更简洁。
  • 我正在添加 [bugs] 标签。如果其中一位 WRI 开发人员想解释为什么这不是错误,我会删除它。

标签: wolfram-mathematica


【解决方案1】:

不是答案,而是:
使用在重新定义函数之前保持原始默认值的行为建议快速解决方法:

在进行任何其他定义之前,为Default 定义一个全局变量。

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

这也适用于Optional

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

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

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

【讨论】:

    【解决方案2】:

    来自documentation

    必须始终在将_. 用作f 的参数之前定义Default[f] 的必要值。

    在设置Default[f] = 9; 后重新定义f 使用新的默认值。所以我的猜测是它是第一次在内部定义的,f 是定义的,即使DefaultValue@f 存储了新值也不会改变。

    【讨论】:

    • 但是它内部存储在哪里?旧的默认值似乎没有出现在任何*Values...
    • @Mr.W:我很抱歉,但这更多的是一种可能的解释,而不是一个具体的答案(以防你错过了文档中的这一部分)。此外,由于这是记录在案的行为,我看不出第一个问题的意义(它是什么)。但是第二个,我真的不知道,我也没有试图回答。我想我应该清楚地表达我的意图。
    • 很抱歉,如果出现粗鲁。我知道其他人(除了版主)看不到我的投票,但不知何故,我觉得我需要解释为什么我不投票支持这个,而且我担心它听起来很贬义。至于Default,对我来说,您回答中的引用并不排除Default[f] 以后可以更改并且该更改将影响早期使用的可能性。 (对DownValues 的检查表明这应该起作用。)相反,它告诉我在没有定义Default 的情况下使用_. 可能会或将在分配期间注册为错误.
    • @yoda 问题似乎出在 global 规则上。您可以在本地使用f 尝试您的示例:f[1] /. f[a_, b_.] :> {a, b}(首先删除了其全局定义),并查看它对Default[f] 的更改敏感。我的猜测是全局规则(定义)在定义时可能会进行一些内部优化,这需要在定义时 Default 的值。定义完成后,它会被优化并对Default[f] 的更改不敏感,除非我们有一定程度的间接性,如@Simon 的回答。
    • @Alexey 我不清楚这是否发生在一般评估或仅与SetSetDelayed 的评估以及分配过程有关。因为我怀疑后者(否则不清楚为什么在f[1] /. f[a_, b_.] :> {a, b} 中的本地规则中对可选模式的评估不会导致相同的Default-insensitive 行为),并且因为SetSetDelayed 产生全局规则,我称之为“全局规则效应”。
    【解决方案3】:

    我发现在本地规则的情况下这种行为是由于specifics of internals of RuleDelayed

    比较:

    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}]
    

    可以看到Blocking RuleDelayed 使本地 规则的行为符合人们的预期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2018-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多