Red语言foreach中的变量值
Variable value in foreach of Red language
我正在使用以下代码通过 foreach 循环将多个 GUI 元素添加到视图:
myRange: function [n][ ; to produce a vector of [1 2 3 4... n]
vv: make vector! n
i: 1
foreach j vv [
vv/:i: i
i: i + 1
if i > n [break]]
vv ]
view collect[
foreach i myRange 10 [
print append "i in loop: " i
keep [ t: text ] keep append "message number: " i
keep [field "entry" button "Click" [t/text: "clicked"] return]
] ]
正在制作所有 GUI 元素。但是代码 append "message number: " i
在所有文本元素中显示 i 的值是 12345678910
而不是 1, 2, 3... 10 对于不同的文本元素。
此外,print append...
语句产生以下输出:
i in loop: 1
i in loop: 12
i in loop: 123
i in loop: 1234
i in loop: 12345
i in loop: 123456
i in loop: 1234567
i in loop: 12345678
i in loop: 123456789
i in loop: 12345678910
此外,单击任何按钮只会更改最后添加的文本元素的文本。
问题出在哪里,如何解决?感谢您的帮助。
编辑:似乎语言正在转换我的代码:
for i 1 10 1 [
print append "i in loop: " i ]
至:
a_variable: "i in loop"
for i 1 10 1 [
print append a_variable i ]
这不是我和(我认为)大多数用户想要的。在大多数语言中,字符串 "i in loop" 将被视为常量而不是转换为变量,因为用户没有指定它。恕我直言,如果不改变这些基本约定,其他语言的用户会更容易来到这里。
Rebol 和 Red 尽可能多地重用系列(例如字符串、块),如果您不通过 copy
、make
等重新初始化来告诉它们的话。所以您的问题应该会消失如果你写
append copy "message number: " i
每当您看到这样的内容时,就意味着您未能创建新系列并正在重复使用现有系列。
要解决这个问题,您需要使用 copy
创建一个新系列
例如
print append copy "i in loop: " i
Rebol3/ren-c 不再有此问题,因为源代码是不可变的,因此您会收到此类代码的错误消息。
正如其他答案所暗示的那样,您的消息只使用了一个字符串,需要复制。
至于另一个问题——你应该看一下你正在生成的代码(正如我在别处建议的那样,你可以弹出一点 PROBE
来检查 COLLECT
函数):
[
t: text "message number: 1" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 2" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 3" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 4" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 5" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 6" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 7" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 8" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 9" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 10" field "entry" button "Click" [t/text: "clicked"] return
]
如您所见,您不断地重新分配 t
,所以最后它只引用最后一张脸。
这里有几个选项——最突出的是生成您要分配 text
面孔的名称。在你的 FOREACH
循环中:
keep compose/deep [
(to set-word! rejoin ["t-" i])
text (rejoin ["Message Number: " i])
field "entry"
button "Click" [
set in (to word! rejoin ["t-" i]) 'text "clicked"
]
return
]
请注意,为了简化块创建,我使用了这一行:
set in (to word! rejoin ["t-" i]) 'text "clicked"
这构成(在第一个实例中):
set in t-1 'text "clicked"
IN
returns 绑定到给定上下文(面部对象 t-1
)的给定单词 ('text
) 然后 SET
到 "clicked"
.
更新
此方法甚至不使用单词名称,仅使用公共父级将按钮连接到标签:
view collect [
keep [below space 0x0]
foreach i myRange 10 [
keep compose/deep [
panel [
origin 0x0
text (rejoin ["Message Number: " i])
field "entry"
button "Click" [face/parent/pane/1/text: "clicked"]
]
]
]
]
我正在使用以下代码通过 foreach 循环将多个 GUI 元素添加到视图:
myRange: function [n][ ; to produce a vector of [1 2 3 4... n]
vv: make vector! n
i: 1
foreach j vv [
vv/:i: i
i: i + 1
if i > n [break]]
vv ]
view collect[
foreach i myRange 10 [
print append "i in loop: " i
keep [ t: text ] keep append "message number: " i
keep [field "entry" button "Click" [t/text: "clicked"] return]
] ]
正在制作所有 GUI 元素。但是代码 append "message number: " i
在所有文本元素中显示 i 的值是 12345678910
而不是 1, 2, 3... 10 对于不同的文本元素。
此外,print append...
语句产生以下输出:
i in loop: 1
i in loop: 12
i in loop: 123
i in loop: 1234
i in loop: 12345
i in loop: 123456
i in loop: 1234567
i in loop: 12345678
i in loop: 123456789
i in loop: 12345678910
此外,单击任何按钮只会更改最后添加的文本元素的文本。
问题出在哪里,如何解决?感谢您的帮助。
编辑:似乎语言正在转换我的代码:
for i 1 10 1 [
print append "i in loop: " i ]
至:
a_variable: "i in loop"
for i 1 10 1 [
print append a_variable i ]
这不是我和(我认为)大多数用户想要的。在大多数语言中,字符串 "i in loop" 将被视为常量而不是转换为变量,因为用户没有指定它。恕我直言,如果不改变这些基本约定,其他语言的用户会更容易来到这里。
Rebol 和 Red 尽可能多地重用系列(例如字符串、块),如果您不通过 copy
、make
等重新初始化来告诉它们的话。所以您的问题应该会消失如果你写
append copy "message number: " i
每当您看到这样的内容时,就意味着您未能创建新系列并正在重复使用现有系列。
要解决这个问题,您需要使用 copy
例如
print append copy "i in loop: " i
Rebol3/ren-c 不再有此问题,因为源代码是不可变的,因此您会收到此类代码的错误消息。
正如其他答案所暗示的那样,您的消息只使用了一个字符串,需要复制。
至于另一个问题——你应该看一下你正在生成的代码(正如我在别处建议的那样,你可以弹出一点 PROBE
来检查 COLLECT
函数):
[
t: text "message number: 1" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 2" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 3" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 4" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 5" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 6" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 7" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 8" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 9" field "entry" button "Click" [t/text: "clicked"] return
t: text "message number: 10" field "entry" button "Click" [t/text: "clicked"] return
]
如您所见,您不断地重新分配 t
,所以最后它只引用最后一张脸。
这里有几个选项——最突出的是生成您要分配 text
面孔的名称。在你的 FOREACH
循环中:
keep compose/deep [
(to set-word! rejoin ["t-" i])
text (rejoin ["Message Number: " i])
field "entry"
button "Click" [
set in (to word! rejoin ["t-" i]) 'text "clicked"
]
return
]
请注意,为了简化块创建,我使用了这一行:
set in (to word! rejoin ["t-" i]) 'text "clicked"
这构成(在第一个实例中):
set in t-1 'text "clicked"
IN
returns 绑定到给定上下文(面部对象 t-1
)的给定单词 ('text
) 然后 SET
到 "clicked"
.
更新
此方法甚至不使用单词名称,仅使用公共父级将按钮连接到标签:
view collect [
keep [below space 0x0]
foreach i myRange 10 [
keep compose/deep [
panel [
origin 0x0
text (rejoin ["Message Number: " i])
field "entry"
button "Click" [face/parent/pane/1/text: "clicked"]
]
]
]
]