local and do <commands> - what NOT to do
Mark Waddingham
mark at livecode.com
Thu Feb 18 06:52:15 EST 2016
On 2016-02-18 09:03, Kay C Lan wrote:
> The Dictionary entry for 'local' has this Example:
>
> -- To make a numbered list of variables:
> repeat with x=1 to 20
> do "local tVar_" & x & "; put empty into tVar_" & x
> end repeat
Okay so this kind of code pattern originates from HyperCard which did
not have arrays. If you wanted to manipulate multiple separate values
without restriction on their contents (e.g. elements of a list which
need to contain the delimiter) then it was probably one of the only
options.
An important thing to remember about LiveCode compared to HyperCard (as
far as I understand, at least) is that LiveCode *compiles* scripts ahead
of time; in contrast to HyperCard which operated on a line-by-line
execution basis. Strict Compilation Mode is a compilation option - it
has no effect at execution time.
If Strict Compilation Mode is turned off, then when a script is compiled
any token which is where a variable could be is treated as an 'unquoted
literal'. Such unquoted literals are implemented by the engine by
declaring a variable whose contents is the name of the variable but only
up until appoint the variable is assigned a value - at which point it is
cleared before hand. e.g.
put foobar into tVar
put barfoo after foobar
put foobar
Will result in:
- tVar containing foobar
- foobar containing barfoo
So, with that in mind let's take a look at what is happening in the
above code snippet:
repeat with x=1 to 20
do "local tVar_" & x
do "put x*x into tVar_" & x
end repeat
put tVar_5 into msg --not hidden in <do>
With Strict Compilation Mode turned off, this script will compile fine -
it will cause the handler which the code is placed in to have an
'unquoted literal variable' tVar_5 defined - at the point of
compilation. This means that when you run the script, you get a 'local
variable shadows another' parsing error when you do 'do "local tVar_5"'
as there is already a variable that exists with that name. Indeed, if
you try this (again with Strict Compilation Mode turned off):
repeat with x=1 to 20
do "local tVar_" & x
do "put x*x into tVar_" & x
end repeat
put tVar_5 into msg --not hidden in <do>
local tVar_5
You will get an error on the final line when applying the script as
tVar_5 has already been implicitly declared as an unquoted literal
variable.
With Strict Compilation Mode turned on, then neither script will compile
- as you are using 'tVar_5' on the fifth line without declaring it.
Now, whilst at first site it might seem like 'local' declarations are
superfluous for these kinds of things, they do actually serve a purpose.
Compare the following two snippets:
repeat with x = 1 to 5
if (x mod 2) is 1 then
do "put x*x into tVar_" & x
end if
end repeat
local tAllVars
repeat with x = 1 to 5
do "put tVar_" & x & " & return after tAllVars"
end repeat
put tAllVars
And:
repeat with x = 1 to 5
do "local tVar_" & x
if (x mod 2) is 1 then
do "put x*x into tVar_" & x
end if
end repeat
local tAllVars
repeat with x = 1 to 5
do "put tVar_" & x & " & return after tAllVars"
end repeat
put tAllVars
In the first snippet you will get:
1
tVar_2
9
tVar_4
25
In the second snippet you will get:
1
9
25
Basically, using 'local' ensures that any use of the variable token will
be treated as a variable and not as an unquoted literal, i.e. doing
'local tVar' essentially means add a variable to the current handler
initialized to empty. If you don't use local then any tokens which have
not previously been declared as variables (whether at compile time, or
runtime using do) will be treated as variables with the variable name as
contents.
Upshot: There's no reason to use 'local' in do if you are initializing
the variable at that point. Indeed, one could argue that it is better to
do:
do "put empty into tVar_" & x
Rather than using 'local' as then you can mix dynamic vars with those
declared at the point of compilation without issue. (As 'local' requires
that the variable has *not* been previously defined whether it be as an
unquoted literal, or as the target of an assignment).
Hope this helps!
Mark.
--
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps
More information about the use-livecode
mailing list