Wolfram mathematica 如何定义控制变量定义的一部分以减少代码重复

Wolfram mathematica 如何定义控制变量定义的一部分以减少代码重复,wolfram-mathematica,Wolfram Mathematica,这和这个问题有点关系 但是上面的问题并没有回答我的问题,因为它涉及到完全控制的定义。(我也尝试了上面展示的一些技巧,但它们对我的问题不起作用) 我现在只询问部分控件的定义。(使用这种论坛形式也很难跟进一个老问题。因为使用很小的评论区域,当问一个空间更大的新问题时,很难提问并表现得更像,而且可以粘贴代码和图像) 我所有的尝试都不起作用。我将从一个简单的例子开始解释这个问题 假设一个人想写作 Clear["Global`*"]; Manipulate[Plot[f*g, {x, -1, 1}],

这和这个问题有点关系

但是上面的问题并没有回答我的问题,因为它涉及到完全控制的定义。(我也尝试了上面展示的一些技巧,但它们对我的问题不起作用)

我现在只询问部分控件的定义。(使用这种论坛形式也很难跟进一个老问题。因为使用很小的评论区域,当问一个空间更大的新问题时,很难提问并表现得更像,而且可以粘贴代码和图像)

我所有的尝试都不起作用。我将从一个简单的例子开始解释这个问题

假设一个人想写作

Clear["Global`*"];

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], 
    PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny]},{Style["g(x)="], 
    PopupMenu[Dynamic[g], {x, x^2, x^3}, ImageSize -> Tiny]}
   }]
 ]
您可以看到在每个控件定义中都有代码重复分配。(像ImageSize、Spacings->和许多其他装饰设置之类的内容会对每个控件反复进行

如果我能写这样的东西,有什么好呢

Manipulate[Plot[f*g, {x, -1, 1}],
 Grid[{
   {Style["f(x)="], PopupMenu[Dynamic[f], Evaluate@Sequence@v]},
   {Style["g(x)="], PopupMenu[Dynamic[g], Evaluate@Sequence@v]}
   }],

 Initialization :>
  (
   v = {{x, x^2, x^3}, ImageSize -> Tiny}
   )
 ]
但是这不起作用。我尝试了很多其他的方法,但是没有任何效果。比如

{Style["f(x)="], PopupMenu[Dynamic[f], v]},

不能让它工作

但游戏规则如下:这将用于演示,因此,代码必须以操纵开始。不能让模块外部操纵。此外,不能使用Hold及其朋友。但可以使用未评估的

我希望这里的专家们能想出一个窍门来做到这一点。如果可能的话,它将减少代码的大小,就像我拥有的许多控件一样,包含许多与上面相同的“选项”,并且能够完成上面的操作将使代码更易于阅读和管理

谢谢

注:我所要求的,有点类似于我们对绘图选项所做的,在这里我们可以使用SetOptions来设置一些常见的默认选项,这样他们就不必每次为每个绘图命令复制它们。但在这种情况下,没有这样的事情

更新

使用下面Leonid所示的方法(宏技巧),我想用它来帮助我定义控件的数量,所有这些都使用一个公共设置。这就是我尝试的:

Manipulate[{x, y},

 Evaluate@With[
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      {
       {{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}
       }
      ,
      HoldAll
      ]
    },

   {
      First@control1[x, 0, "x=", 0, 1, .1],
      First@control1[y, 0, "y=", 0, 2, .1],
      First@control1[z, 0, "z=", 0, 10, .1]
    }, 

   ]
 ]
这个问题只是整个事情周围的一个额外的{},否则它会起作用。我会继续尝试解决这个问题。但是越来越近。尝试了序列[],和平坦[],1]等等,但还不能做到。多煮些咖啡应该会有帮助

更新2

下面是一个使用Simon方法来帮助跨多个控件定义公共定义的示例。通过这种方式,可以使用它来减少一组单独控件上公共选项的代码重复

注意,必须使用
Control[]
来控制它

Manipulate[{x, y, z},

 Dynamic[Grid[{
    {control1[x, 0, "x=", 0, 1, .1]},
    {control1[y, 0, "y=", 0, 2, .1]},
    {control1[z, 0, "z=", 0, 10, .1]}
    }]],

 {{control1, 
   Function[{var, initialValue, str, from, to, incr}, 
    Control[{{var, initialValue, str}, from, to, incr, 
      ImageSize -> Tiny}], HoldFirst]}, None}

 ]

更新3

并且让Leonid方法也可以在多个控件上工作。诀窍是使用
控件[]
。不能使用普通的
{{x,0,“x”},…}
[编辑,是的,您可以,只需要Leonid update下面显示的Sequence@方法。]

这是:

Manipulate[{x, y, z},

 Evaluate@With[
   {
    control1 = Function[{var, initialValue, str, from, to, incr},
      Control[{{var, initialValue, str}, from, to, incr, 
        ImageSize -> Tiny}]
      , HoldAll
      ]
    },

   Grid[{
     {control1[x, 0, "x=", 0, 1, .1]},
     {control1[y, 0, "y=", 0, 2, .1]},
     {control1[z, 0, "z=", 0, 10, .1]}
     }]

   ]
 ]

我将尝试将这些方法中的一种集成到我的主演示中(到目前为止,仅针对控件布局的代码就超过600行,并且每分钟都在增长,希望这些方法能够将其压缩很多)

更新日期:2011年9月26日下午7点

我想我发布了一个关于代码保存的“鸟瞰”视图,通过使用“宏”来定义包含许多常见锅炉板代码的控件

再次感谢所有的回答和帮助

这个怎么样

Manipulate[Plot[f*g, {x, -1, 1}],
 Evaluate@
  With[{styleAndpopup = 
      Function[{st, fun}, 
         {
           Style[st], 
           PopupMenu[Dynamic[fun], {x, x^2, x^3}, ImageSize -> Tiny]
         }, 
         HoldAll]},
    Grid[{styleAndpopup["f(x)=", f], styleAndpopup["g(x)=", g]}]]]
这实际上是工作中代码生成的一个小例子,因为如果您查看所生成的
操作
完整形式
,您将看到与最初使用的表达式相同的表达式。
样式和弹出式
实际上不是一个函数,而是一个使用
with
本地定义的宏

编辑

根据OP的请求-推广到许多控件。最简单的修复方法是插入
Sequence@…
as
Sequence@@@{First@control1[…
。但是,也可以删除一些无关的内容:

Manipulate[{x, y}, 
 Evaluate@With[{control1 = 
     Function[{var, initialValue, str, from, to, incr}, 
       Unevaluated@{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}, 
       HoldAll]}, 
   Sequence @@ {
     control1[x, 0, "x=", 0, 1, .1], 
     control1[y, 0, "y=", 0, 2, .1], 
     control1[z, 0, "z=", 0, 10, .1]}]]

我本打算给出一个与Leonid几乎相同的解决方案,并使用
With
插入代码,但他抢先给了我,所以这里有一个替代方法。使用
ControlType->None定义一个动态局部函数,该函数可以进行样式设置:

Manipulate[Plot[{f, g + 1}, {x, -1, 1}], 
 Dynamic[Grid[{{Style["f(x)="], pu[f]}, 
       {Style["g(x)="], pu[g]}}]], 
{{pu, Function[{f}, PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny], 
        HoldFirst]}, None}]
顺便说一下,
Style[“f(x)=“]
中的
Style[]
是多余的,因为您实际上没有设置任何样式…

可以这样做:

Manipulate[
  Plot[f*g, {x, -1, 1}]
, Grid[
    { {Style["f(x)="], PopupMenu[Dynamic[f], opts]}
    , {Style["g(x)="], PopupMenu[Dynamic[g], opts]}
    }
  ]
] /. opts -> Sequence[{x, x^2, x^3}, ImageSize -> Tiny]
如果一个人习惯于将值分配给名称不以
$
开头的符号,那么如果
x
opts
具有全局定义的值,则谨慎地将整个内容包装在
块[{x,opts},…]

对于多个控件的情况,也可以使用类似的技术:

Manipulate[
  {x, y, z}
, Grid[
    { {control1[x, 0, "x=", 0, 1, .1]}
    , {control1[y, 0, "y=", 0, 2, .1]}
    , {control1[z, 0, "z=", 0, 10, .1]}
    }
  ]
] /. control1[var_, initialValue_, str_, from_, to_, incr_] :>
       Control[{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}]

一个不错的选择-+1.实际上,在我的解决方案中,
With
并不重要,可以用
模块
来代替(虽然,
With
在这里看起来更干净,但这是一个品味问题)@Simon,我不确定我是否理解,上面的代码不起作用,我在V8.01上。是否有丢失的代码?我复制并运行了它,请参阅编辑1以了解我计算机上的结果。(windows 7)。(我确实从新内核开始)谢谢。@Simon,谢谢。我得到了你的方法,可以在多个单独的控件中使用它。请参阅更新2。我现在正在使用Leonid方法进行相同的操作。你知道如何使用你的方法使用“通用”定义定义多个控件吗?请参阅我的编辑2了解我的尝试。我想我已经接近了。谢谢,Seq这就是诀窍。我还在更新中添加了另一种方法。现在我们有3种方法可以做到这一点。@Nasser请注意,我的更新中有一个范围错误/评估漏洞:如果执行
Manipulate[
  Plot[f*g, {x, -1, 1}]
, Grid[
    { {Style["f(x)="], PopupMenu[Dynamic[f], opts]}
    , {Style["g(x)="], PopupMenu[Dynamic[g], opts]}
    }
  ]
] /. opts -> Sequence[{x, x^2, x^3}, ImageSize -> Tiny]
Manipulate[
  {x, y, z}
, Grid[
    { {control1[x, 0, "x=", 0, 1, .1]}
    , {control1[y, 0, "y=", 0, 2, .1]}
    , {control1[z, 0, "z=", 0, 10, .1]}
    }
  ]
] /. control1[var_, initialValue_, str_, from_, to_, incr_] :>
       Control[{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}]