我正在使用Leonid的宏方法(see here)来帮助我管理Manipulate
的控制变量布局。
但我发现在宏中,我无法使用其他地方定义的另一个宏。所以我想知道是否有办法在另一个宏中使用宏?
为了解释这个问题,我将首先使用一个级别的宏显示一个非常简单的Manipulate,然后我将通过尝试使用另一个宏来显示问题。
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'宏中使用它:
操纵[文字[ “OK”],
Evaluate@With[{
checkBox = Function[{}, Checkbox[Dynamic[c]], HoldAll],
x = Function[{},
TabView[{
"x" -> checkBox[] (*=====> DOES NOT WORK, did not bind *)
}], 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'宏没有'看到'复选框宏。
但是如果我直接在'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,而不是移动宏定义的更大的代码片段。由于Manipulate没有GUI构建器,因此当需要管理大量控件时,此方法会有所帮助。
答案 0 :(得分:7)
这是因为在这种情况下你需要一个嵌套的With
。您不能在With
的同一声明列表中使用另一个变量的声明。以下是您问题的简化版本:
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]]
在您的情况下,checkBox
扮演a
角色,x
扮演c
角色。
关于如何制作允许这种连续绑定的With
版本的主题,在Mathgroup和SO上已多次讨论过。这是我的implementation这样的结构:
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
。
答案 1 :(得分:1)
我是这个网站的新手,所以你想要做的事情可能会有不同的目标,但有什么理由不能直接对此进行编码吗?
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]}
}]
]