Wolfram mathematica 如何在定义操纵控件时从宏内部使用宏?
我正在使用Leonid的宏方法()来帮助我管理Wolfram mathematica 如何在定义操纵控件时从宏内部使用宏?,wolfram-mathematica,Wolfram Mathematica,我正在使用Leonid的宏方法()来帮助我管理操作的控制变量布局 但我发现,在宏中,我无法使用其他地方定义的另一个宏。所以我想知道是否有一种方法可以从另一个宏中使用一个宏 为了解释这个问题,我将首先展示一个使用一级宏的非常简单的操作,然后通过尝试从另一级宏中使用宏来展示问题 Manipulate[Text["ok"], Evaluate@With[{ x = Function[{}, (*----> macro x *) TabView[{ "x
操作的控制变量布局
但我发现,在宏中,我无法使用其他地方定义的另一个宏。所以我想知道是否有一种方法可以从另一个宏中使用一个宏
为了解释这个问题,我将首先展示一个使用一级宏的非常简单的操作,然后通过尝试从另一级宏中使用宏来展示问题
Manipulate[Text["ok"],
Evaluate@With[{
x = Function[{}, (*----> macro x *)
TabView[{
"x" -> "working on x"
}], HoldAll
],
y = Function[{}, (*----> macro y *)
TabView[{
"y" -> "working on y"
}], HoldAll
]
},(*WITH*)
(* now use the above macros *)
Grid[{
{SetterBar[Dynamic[choice], {1, 2}]},
{Dynamic[Which[choice == 1, x[], choice == 2, y[]] ]}
}]
],
{{choice, 1}, None},
ContentSize -> 300
]
现在为复选框添加一个宏,然后尝试从上面的“x”宏内部使用它:
操纵[文本[“确定”]
我们看到它不起作用。“x”宏没有“看到”复选框宏
但是,如果我将复选框的代码直接添加到“x”宏中,它当然会起作用:
Manipulate[Text["ok"],
Evaluate@With[{
x = Function[{},
TabView[{
"x" -> Checkbox[Dynamic[c]] (* add the definition directly *)
}], HoldAll
],
y = Function[{},
TabView[{
"y" -> "working on y"
}], HoldAll
]
},(*WITH*)
Grid[{
{SetterBar[Dynamic[choice], {1, 2}]},
{Dynamic[Which[choice == 1, x[], choice == 2, y[]] ]}
}]
],
{{choice, 1}, None},
{{c, True}, None},
ContentSize -> 300
]
因此,问题是:是否可以从“x”宏内部使用上面的复选框宏
为了更简单,我没有向宏传递任何参数。我只是使用宏作为较大代码片段(控制变量定义)的“速记”名称,如上所示
这只是为了让我更容易通过只移动宏名称来布局UI,而不是移动宏定义的较大的代码段。因为没有用于操纵的GUI生成器,所以当有许多控件要管理时,这种方法会有所帮助。这是因为在这种情况下,您需要一个带有
的嵌套。您可以在的同一声明列表中,不要将一个变量的声明用于另一个变量。以下是问题的简化版本:
In[3]:= With[{a=b,c=f[a]},g[c]]
Out[3]= g[f[a]]
这正是您需要的:
In[5]:=
With[{a=b},
With[{c=f[a]},g[c]]]
Out[5]= g[f[b]]
在您的情况下,复选框
扮演a
的角色,x
扮演c
的角色
关于如何使用
制作一个版本的
,以允许这种连续绑定的主题,在Mathgroup和SO上讨论了多次。下面是我对这种构造的看法:
ClearAll[LetL];
SetAttributes[LetL, HoldAll];
LetL /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] :=
Block[{With}, Attributes[With] = {HoldAll};
lhs := Evaluate[rhs]];
LetL[{}, expr_] := expr;
LetL[{head_}, expr_] := With[{head}, expr];
LetL[{head_, tail__}, expr_] :=
Block[{With}, Attributes[With] = {HoldAll};
With[{head}, Evaluate[LetL[{tail}, expr]]]];
如果你愿意使用它,你所要做的就是在你的代码中将
With
更改为LetL
。这是因为在这种情况下你需要一个嵌套的With
。你不能在With
的同一声明列表中使用另一个变量的声明。这是你的问题的简化版本m:
In[3]:= With[{a=b,c=f[a]},g[c]]
Out[3]= g[f[a]]
这正是您需要的:
In[5]:=
With[{a=b},
With[{c=f[a]},g[c]]]
Out[5]= g[f[b]]
在您的情况下,复选框
扮演a
的角色,x
扮演c
的角色
关于如何使用制作一个版本的,以允许这种连续绑定的主题,在Mathgroup和SO上讨论了多次。下面是我对这种构造的看法:
ClearAll[LetL];
SetAttributes[LetL, HoldAll];
LetL /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] :=
Block[{With}, Attributes[With] = {HoldAll};
lhs := Evaluate[rhs]];
LetL[{}, expr_] := expr;
LetL[{head_}, expr_] := With[{head}, expr];
LetL[{head_, tail__}, expr_] :=
Block[{With}, Attributes[With] = {HoldAll};
With[{head}, Evaluate[LetL[{tail}, expr]]]];
如果你愿意使用它,你所要做的就是在你的代码中将
With
更改为LetL
。我是这个网站的新手,所以你尝试做的事情可能有不同的目标,但你有没有理由不能直接编写代码
DynamicModule[{choice = 1, c = False},
Grid[{
{SetterBar[Dynamic[choice], {1, 2}]},
{Dynamic[
Which[choice == 1, TabView[{"x" -> Checkbox[Dynamic[c]]}],
choice == 2, TabView[{"y" -> "working on y"}]]]},
{Dynamic[choice], Dynamic[c]}
}]
]
我是这个网站的新手,所以你尝试做的事情可能有不同的目标,但是有什么原因不能直接编写代码呢
DynamicModule[{choice = 1, c = False},
Grid[{
{SetterBar[Dynamic[choice], {1, 2}]},
{Dynamic[
Which[choice == 1, TabView[{"x" -> Checkbox[Dynamic[c]]}],
choice == 2, TabView[{"y" -> "working on y"}]]]},
{Dynamic[choice], Dynamic[c]}
}]
]
重点是,更大/更复杂的动态接口往往包含大量类型的代码重复,这不容易排除,因为,特别是通过常规方法,我们可能会将一些动态符号带出范围。你可以看看这篇文章:,其中给出了这样的示例。我在那里倡导的方法是基于在运行时代码生成上,因此生成的
操作
与手写的完全相同。这个新的…问题是该讨论的逻辑延续,处理希望使用嵌套宏的情况。OP给出了他认为可以说明该问题的最小示例(这是一件非常正确的事情),这可能就是为什么这个问题让你感到困惑的原因。在更大的动态接口环境中,它会变得更有意义。作为一个如何做这件事或那件事的练习,这是很公平的,但如果构建复杂的接口是一个目标,那么对于初学者来说,我不知道为什么会使用操纵。换句话说,像这样的需要是可能的y由于操纵的刚性。使用DynamicModule,这些问题将在很大程度上消失。@MikeHoneychurch,要发布WRI网站的演示,不允许直接使用Dynamics构建它,但必须使用操纵[]。即,演示CDF必须都在操纵[]内.嗨,纳赛尔,是的,我知道,所以如果在演示网站上发布是你的目标,那么不言而喻,你必须使用操纵。问题中没有说明这一目标,所以我是回应Leonid提到的“更大的动态界面”Wolfram自己的更大的动态接口,例如其CDF示例,不使用Operate。问题是,更大/更复杂的动态接口往往包含大量类型的代码重复,这不容易排除,因为,特别是通过常规方法,我们可能会将一些动态符号带出范围。您可以查看这篇文章:,这里有这样的例子。我提倡的方法是基于运行时代码生成的,因此产生的操作
与手写的完全相同。这个新的…问题是该讨论的逻辑延续,处理希望使用嵌套宏的情况。OP介绍了在会议上,他考虑了一个简单的例子来说明这个问题(在国际海事组织,这是一件非常正确的事情),这可能就是为什么这个问题让你感到困惑的原因。在更大的动态接口环境中,它会变得更有意义。作为一个如何做这件事或那件事的练习,这是很公平的,但如果构建复杂的接口是一个目标,那么对于初学者来说,我不知道为什么会使用操纵。换句话说,像这样的需要是可能的由于刚度的原因