Using 'for each' to modify a container

Jim Ault JimAultWins at yahoo.com
Wed Oct 11 19:18:04 CDT 2006


On 10/11/06 3:05 PM, "Bill Marriott" <wjm at wjm.org> wrote:
> Hi Jim,
>> I think the reason that 'for each' is so fast is that it scans the
>> "vContainer" memory space, returns those characters, and is not meant to
>> be
>> modified.  My experience is that it is unpredictable to rely on the
>> changed
>> value of 'thisLine'
> 
> Wow, this is very interesting to me. I just checked the documentation
> (2.6.1) on the "for each chunkType labelVariable" for of repeat, and was
> astonished to find:
> 
> Important! You cannot change the labelVariable in a statement inside the
> loop. Doing so will cause a script error. You can change the content of the
> container, but doing so will probably produce unexpected results.
> <<<
(disclaimer.. I do not have assembler programming, or other low-level
experience, so what follows in an amateur discussion)

I believe this stems from the way memory registers are managed.  The very
tiny bit of C and Pascal programming I read meant I had to first learn how
to manage anything I created, finally releasing it back to the operating
system.  The penalty was mucho errors and unexpected results.

My guess is that Rev is allowing speed in cases where they do not have to
munger variables in memory, therefore you cannot reliably 'redefine' them on
the fly.  A loop counter may be an offset index that is pre-set when the
loop starts, thus very fast, but not to be changed during execution.  Kinda
like re-indexing a database.

<I am ready for those who know the real story to fire away :-)
> 
> Ya learn something new every day! Sounds kind of cheesy to me, though. Why
> wouldn't it be identical to
> 

> repeat with i = 1 to the number of chunkType in theContainer
>   put chunkType i of theContainer into labelVariable
>   -- do stuff
> end repeat
The  'to the number of'   useage is much, much slower, thus not identical

> Your explanation is plausible, but if it is so then why permit ("You can
> change...") changing the contents of the container itself within the loop?
> That would seem to cause an even bigger problem.
> 
> BTW, I set up a button with the following script:
> 
> on mouseUp
>   put empty into newContainer
>   repeat for each line thisLine in fld 1
>     put thisline & "***" into thisLine
>     put thisLine & return after newContainer
>   end repeat
>     put char 1 to -2 of newContainer into fld 1
> end mouseUp
> 
> Which not only didn't generate a script error but worked perfectly as
> "expected." Is the bug in the documentation, or that it doesn't generate a
> script error, or that for each doesn't let you modify the labelVariable?
The error probably depends on what other operations are being done in the
memory stack of Rev.  Here 'memory stack' is the area of computer memory
registers the system reserves for Rev to use.   If nothing requires Rev to
'move' memory locations, then your labelVariable will be in the same
location the next time you want to access it.

Its like the coffee cup on your desk.  You reach for it without looking, and
all is well, unless someone pushed it closer to you when you were not
looking.

> And I'm *really* concerned about the second part of your report
> 
>> Further, I don't reuse the name 'thisLine' in the next instance of a
>> repeat
>> for each loop in the *same handler*, but change the name to avoid
>> conflict,
>> such as 'thisline', 'thisline1', 'thisLine2'.  Again, unpredictable
>> results
>> occasionally.
> 
> Surely THAT is a definite bug?! Have other people experienced this? Are you
> able to reproduce it? Is there a bug on it already filed? I do this all the
> time and I'd have to update a lot of code to fix it.
> 
> This would suggest to me that maybe I shouldn't use "i" more than once in a
> handler as the control variable for a repeat as well (something I always do,
> unless nesting the loops of course).
> 
> I won't even get into the idea of declaring the labelVariable as a global!
All I can say is that you are getting a tradeoff...
memory registers + speed vs controlled variables and definitions

>> --my preference is
>> put empty into newContainer
>>   repeat for each line thisLine in vContainer
>>   put doSomeFunction(item -2 of thisLine)&cr after newContainer
>> end repeat
>> put char 1 to -2 of newContainer into vContainer 





More information about the use-livecode mailing list