Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Variable not avilable out of a foreach

 [1/14] from: gchillemi::aliceposta::it at: 10-Dec-2007 20:30


I have the following script: rebol: [] get_data: does [ parse line [] ] main_loop: does [ file_database: request-file database: read/lines to-file file_database foreach line database [ get_data ] ] main_loop The script returns LINE has no Value, I must assign it to a temporary variable... why ? Giuseppe Chillemi

 [2/14] from: tim-johnsons:web at: 10-Dec-2007 10:39


On Monday 10 December 2007, Giuseppe Chillemi wrote:
> I have the following script: > rebol: []
<<quoted lines omitted: 11>>
> The script returns LINE has no Value, I must assign it to a temporary > variable... why ?
try changing get_data to a func and pass 'line as an argument to it tim

 [3/14] from: tim-johnsons::web::com at: 10-Dec-2007 11:48


On Monday 10 December 2007, Tim Johnson wrote:
> On Monday 10 December 2007, Giuseppe Chillemi wrote: > > I have the following script:
<<quoted lines omitted: 17>>
> try changing get_data to a func and pass 'line as an argument to it > tim
p.s. your problem stems from the way that rebol evaluates 'get_data before the loop and knows nothing about a global 'line. Just for grins, you could also put get_data as a 'does inside the loop where 'line would now be in the same scope as 'get_data. as in: b: [1 2 3 4 5] foreach line b[g: does[print line] g] but is probably not a good idea.... :-) tj

 [4/14] from: gchillemi:aliceposta:it at: 10-Dec-2007 20:46


> > The script returns LINE has no Value, I must assign it to a > temporary > > variable... why ? > try changing get_data to a func and pass 'line as an > argument to it tim
Yes, it is another solution but my question is WHY is this happening ? Giuseppe Chillemi

 [5/14] from: tim-johnsons:web at: 10-Dec-2007 17:12


On Monday 10 December 2007, Giuseppe Chillemi wrote:
> > > The script returns LINE has no Value, I must assign it to a > >
<<quoted lines omitted: 5>>
> > argument to it tim > Yes, it is another solution but my question is WHY is this happening ?
Hi Giuseppe: Because the source of get_data is first evaluated outside of the *scope* of the foreach loop. When it is called within the loop it treats 'line as a global which does not exist. If there were a global 'line, then you could have some very unpredictable results... See my second post on this question, I've got some little examples there. HTH Tim

 [6/14] from: Izkata::Comcast::net at: 10-Dec-2007 20:12


Probably for a similar reason this C code doesn't work: #include <stdlib.h> void Test() { printf("Var: %d\n", X); } int main() { for(int X = 0;X < 10;X) Test(); return 0; } In Rebol, setting a word to some value is a global action unless it's done within an object. (I may be wrong here, but that's how it seems to work, and how I understand it) So setting line to something else before calling your function is equivalent in the above C code to adding a global variable and using that instead of trying to access X where it doesn't exist. On Mon, 2007-12-10 at 20:46 +0100, Giuseppe Chillemi wrote:

 [7/14] from: anton::wilddsl::net::au at: 12-Dec-2007 2:18


Hi Giuseppe, Let me just start by saying that rebol defines no "scope". Every word can be bound and rebound dynamically (completely unlike C.) rebol [] get_data: does [ parse line [] ] main_loop: does [ database: ["hello" "buon giorno"] foreach line database [ get_data ] ] main_loop
> The script returns LINE has no Value, I must assign it to a temporary > variable... why ? > > Giuseppe Chillemi
The foreach creates a temporary context for use during evaluation of its body block. You supplied a word, 'line, which is taken literally by foreach and added as a new word in the new, temporary context. The 'line word which is written right after 'foreach word is a completely independent word from the 'line which the foreach creates in its temporary context. (The 'line word inside the get_data function body is also a completely independent word from the 'line which the foreach creates in its temporary context.) The foreach then binds its body block to the new context. Nowhere in the above body block has the 'line word been written. All that is in the body block is: [get_data] a single word (and it is not 'line). Therefore, no words in the body block have their binding changed. In summary, the foreach created a new word in a "hidden" context, instead of using the 'line word from the global context. You could work around this by different methods: 1) Set a word which is not in the foreach temporary context. foreach row database [line: row get_data] 2) Modify the function to add a parameter so you can mention 'line when passing an argument. get_data: func [line][...] ... foreach line database [get_data line] 3) Modify the function body. get_data: does [...] ... foreach line database [ bind second :get_data 'line get_data ] 4) Make your own variety of foreach which does not create its own context but uses words with existing bindings. Regards, Anton.

 [8/14] from: gchillemi:aliceposta:it at: 11-Dec-2007 17:02


> 3) Modify the function body. > get_data: does [...]
<<quoted lines omitted: 5>>
> 4) Make your own variety of foreach which does not create its > own context but uses words with existing bindings.
Solution 1 and 2 where already taken into consideration and used. I was searching for a reason and you gave it to me. Reallu thank you. Solution 3 is for PRO-develpers. I'll mark you message for a deeper study when I'll fully understand the inner working of rebol. Solution 4... Ehm.. Have already told you I am not one of the PRO-Developers ? :-) Giuseppe Chillemi

 [9/14] from: henrik::webz::dk at: 11-Dec-2007 17:17


On 11/12/2007, at 17.02, Giuseppe Chillemi wrote:
>> 3) Modify the function body. >>
<<quoted lines omitted: 17>>
> ? :-) > Giuseppe Chillemi
Learn about REBOL bindings and contexts. That lets you do some neat tricks. The FOREACH line creates its own context inside the loop block and LINE for FOREACH is bound to that context. If you begin using a function that holds its own LINE as well, that LINE is not bound to the same context, but is global: line: none ; global LINE print-line: does [print line] foreach line database [ ; a different LINE in its own context print-line ; will not work, just prints "none" ] Solution 1 and 2 work because you are feeding a value from the FOREACH context into the function directly, instead of using the word. Solution 3 alters the context of the function, which is probably (?) slower than 1. Solution 4 I wouldn't do. :-) -- Regards, Henrik Mikael Kristensen

 [10/14] from: edoconnor::gmail at: 11-Dec-2007 13:20


With rebol, one often hears the (adapted) Einstein quote, "Make things as simple as possible, but no simpler." The act of explaining something can make it seem more complicated than it is. I think this is the case with foreach and contexts. foreach LINE database [get_data] I think of LINE as a local function variable, owned by foreach. You can use the variable only within the foreach expression. To use it outside the scope of foreach, you need to assign the value of LINE to a global variable. Anton's comments for techniques #1 and #2 provide the common ways of doing this. Ed

 [11/14] from: tim-johnsons:web at: 11-Dec-2007 11:53


On Tuesday 11 December 2007, Anton Rolls wrote:
> Hi Giuseppe,
I must defer to Anton's grasp of rebol - I believe his knowledge of theory runs deeper than mine, but I must differ with what he says here:
> Let me just start by saying that rebol defines no "scope".
because at http://www.rebol.com/docs/core23/rebolcore-9.html#section-9 scope is indeed a topic here.... to say otherwise is to further confuse the newcomer.
> Every word can be bound and rebound dynamically
Indeed! And 'bind is a powerful tool that enables us to manipulate scope... but first one must understand how rebol uses "definitional scoping". respectfully Tim

 [12/14] from: anton:wilddsl:au at: 12-Dec-2007 14:25


Hi Tim, Tim Johnson wrote:
> On Tuesday 11 December 2007, Anton Rolls wrote: >> Hi Giuseppe,
<<quoted lines omitted: 12>>
> respectfully > Tim
Fair enough. Let me add that bind is how scope in rebol is implemented. Knowledge of bind is how one understands scope in rebol better. Regards, Anton.

 [13/14] from: henrik::webz::dk at: 12-Dec-2007 17:04


On 12/12/2007, at 04.25, Anton Rolls wrote:
> Hi Tim, > Tim Johnson wrote:
<<quoted lines omitted: 19>>
> rebol is implemented. Knowledge of bind is how one > understands scope in rebol better.
Let me add that if you experience issues with words not containing the correct values where they should, BIND? can offer an explanation. It shows the context (object) that the word is bound to. -- Regards, Henrik Mikael Kristensen

 [14/14] from: tim-johnsons::web::com at: 12-Dec-2007 15:01


On Wednesday 12 December 2007, Henrik Mikael Kristensen wrote:
> Let me add that if you experience issues with words not containing the > correct values where they should, BIND? can offer an explanation. It > shows the context (object) that the word is bound to.
amen... :-) http://www.fm.vslib.cz/~ladislav/rebol/contexts.html http://www.fm.vslib.cz/~ladislav/rebol/contexts.html#section-7 tj

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted