【问题标题】:Leaving values for options unevaluated in Mathematica保留 Mathematica 中未评估的选项的值
【发布时间】:2011-02-17 23:45:57
【问题描述】:

我在编写带选项的函数时遇到了一些问题。选项值之一是函数。我想得到这个值,但不对其进行评估。我尝试了我能想到的每一件事,但到目前为止没有任何效果。

基本上,为了说明这是我尝试过的:

SetAttributes[Foo, HoldRest];
Options[Foo] = {Blah -> None}

Foo[x_, OptionsPattern[]] :=
    Module[{blah},

        blah = OptionValue[Automatic, Automatic, Blah, Hold];
        .
        .
        .

然后当我有:

func[a_, b_, c_] := a + b + c;

我希望能够通过以下方式调用 Foo:

Foo[2, Blah -> func[1, 2, 3]]

并且让“blah”变量(在 Foo 中)不被计算,即 blah = func[1, 2, 3]。

提前感谢所有帮助!

编辑:

由于太长无法详细说明的原因,我不能使用 RuleDelayed (:>)。我正在尝试编写一个将包含在包中的函数,供不真正了解 Mathematica 的其他人使用,因此他们不知道 :> 是什么。使用规则 (->) 来指定选项及其值是标准方法,他们对此很熟悉。

为了进一步说明,假设我正在尝试编写一个数字生成器函数,该函数将生成实际数字的函数作为其选项之一:

Options[GenerateNumbers] = {GeneratorFunction -> None};

GenerateNumbers[n_, OptionsPattern[]] :=
    Module[{func},

        func = OptionValue[GeneratorFunction];
        Table[func, {n}]
    ]     
]

现在,如果我使用以下值调用此函数:

GenerateNumbers[5, GeneratorFunction -> RandomReal[10]]

它将返回一个包含 5 个相同数字的列表,因为 RandomReal[10] 被评估一次,而不是在 Table 的每次迭代中。我想防止这种情况。问题比较复杂,但就是这样。

谢谢!

【问题讨论】:

    标签: wolfram-mathematica


    【解决方案1】:

    使用OptionsPattern 的名称,然后使用ListUnevaluated 包装捕获的序列对象。捕获Blah 右侧的最小方法是:

    SetAttributes[Foo, HoldRest]; Options[Foo] = {Blah -> None};
    Foo[x_, opts : OptionsPattern[]] :=
     Module[{blah},
      blah = OptionValue[Foo, Unevaluated[{opts}], Blah, Hold];
      blah]
    

    测试一下:

    In[2]:= Foo[x, Blah -> (1 + 1)]
    Out[2]= Hold[1 + 1]
    

    【讨论】:

    • Hold-attributes 和 OptionsPattern 的一个普遍问题是选项不是直接传递而是以 Sequence@@FilterRules[{opts},Options[Foo]] 表示(或任何其他需要评估的方式)不会与 @ 匹配987654330@ 在 Hold 的存在下 - 属性(我的意思是,HoldAllHoldRest)。当然,这在这个例子中是很自然的,但是这种只直接传递选项的要求是非常不明显的,并且会使函数的最终用户感到困惑。我自己的函数有几次遇到这个问题,甚至这也很令人费解。
    【解决方案2】:

    为什么不使用 RuleDelayed?

    Foo[2, Blah :> func[1, 2, 3]]
    

    在这种情况下blah=Hold[func[1, 2, 3]] 符合预期。

    【讨论】:

      【解决方案3】:

      您对选项的使用有点奇怪。如果你想传递一些用 Hold 包裹的表达式,为什么不在传递的时候把它包裹在 Hold 中,比如Blah->Hold[func[1,2,3]]?无论如何,假设Foo 的这个简单定义:

      Foo[x_, OptionsPattern[]] :=
      Module[{blah},
         blah = OptionValue[Automatic, Automatic, Blah, Hold];
         blah
      ],
      

      你可以通过RuleDelayed而不是Rule传递一个选项来完成你想要的:

      In[7]:= func[a_, b_, c_] := a + b + c;
      
      In[8]:= Foo[2, Blah :> func[1, 2, 3]]
      
      Out[8]= Hold[func[1, 2, 3]] 
      

      HTH

      编辑:

      如果您不希望 Hold 缠绕,这是摆脱它的一种方法:

      In[25]:= 
      ClearAll[setDelayedHeld];
      SetAttributes[setDelayedHeld, HoldFirst];
      setDelayedHeld[lhs_, Hold[rhs_]] := lhs := rhs
      
      In[28]:= 
      Clear[Foo];
      Foo[x_, OptionsPattern[]] :=
       Module[{blah},
         setDelayedHeld[blah, OptionValue[Automatic, Automatic, Blah, Hold]];
         OwnValues[blah]]
      
      In[30]:= Foo[2, Blah :> func[1, 2, 3]]
      
      Out[30]= {HoldPattern[blah$1018] :> func[1, 2, 3]}
      

      我返回 OwnValuesblah 以表明它被分配了 func[1,2,3] 而不评估后者 - 如果这是你想要的。

      【讨论】:

        猜你喜欢
        • 2016-09-23
        • 2021-07-23
        • 2021-03-24
        • 1970-01-01
        • 2018-07-29
        • 1970-01-01
        • 2021-05-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多