【问题标题】:Variable value in foreach of Red languageRed语言foreach中的变量值
【发布时间】:2017-09-17 02:47:54
【问题描述】:

我正在使用以下代码通过 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”将被视为常量,并且不会转换为变量,因为用户没有指定它。恕我直言,如果不改变这些基本约定,其他语言的用户会更容易来到这里。

【问题讨论】:

    标签: loops user-interface rebol red


    【解决方案1】:

    每当您看到这样的内容时,就意味着您未能创建新系列并重用现有系列。

    要解决这个问题,您需要使用 copy 创建一个新系列

    例如。

    print append copy "i in loop: " i
    

    Rebol3/ren-c 不再有这个问题,因为源代码是不可变的,所以你会收到这样的代码的错误消息。

    【讨论】:

    • 点击任何按钮只会改变最后一个文本标签会怎样?
    【解决方案2】:

    Rebol 和 Red 尽可能多地重用系列(例如字符串、块),如果您没有通过使用 copymake 等重新初始化来告知它们,那么您的问题应该会消失

    append copy "message number: " i
    

    【讨论】:

      【解决方案3】:

      正如其他答案所暗示的,您的消息只使用一个字符串,需要复制。

      至于另一个问题——你应该稍微看看你正在生成的代码(正如我在其他地方建议的那样,你可以弹出一点 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 返回绑定到给定上下文(面部对象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"]
                  ]
              ]
          ]
      ]
      

      【讨论】:

      • 感谢您的好回答(我也赞成)。但是你真的认为最后 5 行只有 ']' 是在添加什么吗?
      • @rnso 是的。它在视觉上是连贯的。
      • 务实——除了遵守 Rebol/Red 风格指南外,它在文本编辑器中的阅读和折叠都很好。
      猜你喜欢
      • 2018-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多