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:gm:ail 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