Variable value in foreach in red

I use the following code to add multiple GUI elements to a view through a foreach loop:

myRange: function [n][ ; to produce a vector of [1 2 3 4... n] vv: make vector! ni: 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] ] ] 

All GUI elements are produced. But the append "message number: " i code shows the value i as 12345678910 in all text elements, not 1, 2, 3 ... 10 for different text elements.

In addition, the print append... statement produces the following output:

 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 

In addition, pressing any button changes the text of only the last added text element.

Where is the problem and how can it be solved? Thank you for your help.


Edit: It seems the language is changing my code:

 for i 1 10 1 [ print append "i in loop: " i ] 

to:

 a_variable: "i in loop" for i 1 10 1 [ print append a_variable i ] 

This is not what I and (I think) most users want. In most languages, the string "i in loop" will be taken as a constant and not converted to a variable, since the user has not specified it. IMHO it will be easier for users of other languages ​​to come here if such basic agreements are not changed.

+2
source share
3 answers

Whenever you see something like this, it means that you were unable to create a new series and reuse an existing series.

To get around this, you need to create a new series with copy

Eg.

 print append copy "i in loop: " i 

Rebol3 / ren-c no longer has this problem because the source code is unchanged, so you get an error message with that code.

+4
source

Rebol and Red reuse series (e.g. strings, blocks) as much as possible unless you tell them otherwise by reinitializing with copy , make , etc. So your problem should disappear if you write

 append copy "message number: " i 
+3
source

As the other answers show, you only use one line for your message and should be copied.

As for the other problem - you should take a look at the code you are generating (as I suggested elsewhere, you can put a little PROBE bit to check the output of the COLLECT function):

 [ 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 ] 

As you can see, you are constantly reassigning t so that in the end it applies only to the last person.

There are several options here - the most noticeable is the creation of the name to which you assign text face to. Within the FOREACH loop:

 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 ] 

Note that to simplify the creation of the block, I used this line:

 set in (to word! rejoin ["t-" i]) 'text "clicked" 

This means (in the first case):

 set in t-1 'text "clicked" 

IN returns the given word ( 'text ) associated with the given context (object face t-1 ), which is then SET until "clicked" .

UPDATE

This method does not even use the name of the word, it simply uses a common parent to connect the button to the label:

 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"] ] ] ] ] 
+2
source

Source: https://habr.com/ru/post/1272259/


All Articles