我遇到了一个场景,我需要在{*}
命令中使用参数扩展。使用Tcl8.5,我使用的是eval
,它就像魅力一样。
但是,使用Tcl8.4,我尝试了% set x "This is stackoverflow"
This is stackoverflow
% format "%10s %5s %20s" {*}$x
This is stackoverflow
% eval format "%10s %5s %20s" $x
%5s
% eval list format "%10s %5s %20s" $x
format %10s %5s %20s This is stackoverflow
% eval [list format "%10s %5s %20s" $x]
not enough arguments for all format specifiers
% eval format "%10s %5s %20s" [list $x]
%5s
% eval format "%10s %5s %20s" [concat $x]
%5s
。但是,没有运气。
var obj = editor.selected;
var tex = obj.material.map.;
var materials = [];
materials.push(new THREE.MeshBasicMaterial({ map: tex }));
materials.push(new THREE.MeshBasicMaterial({}));
var material = new THREE.MeshFaceMaterial(materials);
var objHeight = obj.geometry.parameters.height;
var objWidth = obj.geometry.parameters.width;
var texHeight = tex.image.height;
var texWidth = tex.image.width;
tex.repeat = new THREE.Vector2(3, 3);
tex.offset = new THREE.Vector2(0, 0);
var geometry = new THREE.PlaneGeometry(objWidth, objHeight, 3, 3);
var v = geometry.vertices;
var facesNum = geometry.faces.length;
v[1] = new THREE.Vector3(-texWidth / 2, objHeight / 2, 0);
v[2] = new THREE.Vector3(texWidth / 2, objHeight / 2, 0);
v[5] = new THREE.Vector3(-texWidth / 2, (objHeight / 2) - texHeight, 0);
v[6] = new THREE.Vector3(texWidth / 2, (objHeight / 2) - texHeight, 0);
v[9] = v[13];
v[10] = v[14];
v[4] = v[8] = v[12];
v[7] = v[11] = v[15];
for (var i = 0; i < facesNum; i++) {
if (i !== 2 && i !== 3) geometry.faces[i].materialIndex = 1;
}
obj.material = material;
obj.geometry = geometry;
editor.signals.materialChanged.dispatch(obj);
这里我的错误是什么?
答案 0 :(得分:3)
请参阅本文的eval and double substitution部分。
正确的方法是:
eval "format {%10s %5s %20s} $x"
这里eval
无法连接任何参数,因此获取解释器的是替换形式:format {%10s %5s %20s} This is stackoverflow
。你当然可以使用eval "format \"%10s %5s %20s\" $x"
,但我更愿意尽可能避免使用反斜杠转义。
eval format "%10s %5s %20s" $x
错误是因为eval首先将字符串连接在一起,所以最终得到:
eval format %10s %5s %20s $x
这就像说format %10s %5s %20s $x
,这就是为什么你得到你得到的东西)
eval list format "%10s %5s %20s" $x
变为:
eval list format %10s %5s %20s $x
这就像说list format %10s %5s %20s $x
并且没有让format
真正做某事。
eval [list format "%10s %5s %20s" $x]
方向正确,但$x
没有扩展,所以你正在做format "%10s %5s %20s" $x
。
其他人只将$x
放入更深的列表中,或者在这种情况下不会改变任何内容。
答案 1 :(得分:3)
8.4成语是使用linsert
来创建要评估的命令
set x "This is stackoverflow"
set args [split $x]
set cmd [linsert $args 0 format "%10s %5s %20s"]
set formatted [eval $cmd]
或嵌套在一行
set formatted [eval [linsert [split $x] 0 format "%10s %5s %20s"]]
答案 2 :(得分:1)
如果编写concat-and-evaluate命令(如eval
)的调用方式不明确,那么用concat
替换命令通常会有助于查看将要执行的操作评估,例如concat format "%10s %5s %20s" $x
代替eval format "%10s %5s %20s" $x
。
这些表单展平格式化字符串,使第二个格式说明符成为第一个值参数(前两个是等价的,$x
是一个平面列表,因此与[concat $x
相同]:)
concat format "%10s %5s %20s" $x
# -> format %10s %5s %20s This is stackoverflow
concat format "%10s %5s %20s" [concat $x]
# -> format %10s %5s %20s This is stackoverflow
concat format "%10s %5s %20s" [list $x]
# -> format %10s %5s %20s {This is stackoverflow}
此表单还插入了不属于该列表的列表命令:
concat list format "%10s %5s %20s" $x
# -> list format %10s %5s %20s This is stackoverflow
此表单保留格式化字符串的列表结构,但遗憾的是还保留了$x
的列表结构:
concat [list format "%10s %5s %20s" $x]
# -> format {%10s %5s %20s} {This is stackoverflow}
这两种形式做正确的事情:它们保留格式化字符串,但展平参数列表:
concat "format {%10s %5s %20s} $x"
# -> format {%10s %5s %20s} This is stackoverflow
concat [list format {%10s %5s %20s}] $x
# -> format {%10s %5s %20s} This is stackoverflow