In Applescript, why do local variables in handlers capture "with" labeled parameters?
In Applescript, if you declare a handler using "with" labeled parameters, local variables get the values of the arguments and the parameters themselves are undefined. For example:
on bam of thing with frst and scnd
local eat_frst
return {thing: thing, frst:frst, scnd:scnd} -- this line throws an error
end bam
bam of "bug-AWWK!" with frst without scnd
results in an error message that "scnd" isn't defined in the second line of bam
. thing
and frst
are both defined, getting the arguments passed in the call to bam
. Why is this happening? Why is scnd
undefined?
Note: I know that declaring variables as "local" within a handler is unnecessary. It's done in the examples for illustrative purposes.
Here are some more examples that don't throw errors, illustrating what variable gets what value. To distinguish between the first and second given parameters, each handler is invoked with
the first given parameter and without
the second given parameter. Note that using the given userLabel:userParamName
syntax has no problems with value capturing.
on foo of thing given frst:frst_with, scnd:scnd_with
local eat_nothing
return {frst:frst_with, scnd:scnd_with}
end foo
on bar of thing with frst and scnd
local eat_frst
return {frst:eat_frst, scnd:scnd}
end bar
on baz of thing with frst and scnd
eat_frst
local eat_scnd, eat_others
return {frst:eat_frst, sc开发者_运维知识库nd:eat_scnd}
end baz
{foo:(foo of "foo" with frst without scnd), ¬
bar:(bar of "bar" with frst without scnd), ¬
baz:(baz of "baz" with frst without scnd)}
Result:
{ foo:{frst:true, scnd:false}, bar:{frst:true, scnd:false}, baz:{frst:true, scnd:false}}
After playing with it for a bit, the answer appears to be that using with
labeled parameters doesn't introduce variables. Instead, the values are assigned to local variables in the order they're encountered in the handler body.
Illustrative examples:
on baa of thing with frst and scnd
scnd
frst
return {frst:scnd, scnd:frst}
end baa
on bas of thing with frst and scnd
-- note that eat_frst gets the value of the frst parameter,
-- then gets set to "set"
set eat_frst to "set"
eat_scnd
return {frst:eat_frst, scnd:eat_scnd}
end bas
on qux of thing with frst and scnd
if scnd then
end if
local eat_scnd, eat_others
return {frst:scnd, scnd:eat_scnd}
end qux
on quux of thing with frst and scnd
if frst then
end if
if eat_scnd then
end if
return {frst:frst, scnd:eat_scnd}
end quux
{ baa: (baa of "baa" with frst without scnd), ¬
bas: (bas of "bas" with frst without scnd), ¬
qux: (qux of "qux" with frst without scnd), ¬
quux: (qux of "qux" with frst without scnd) }
Result:
{ baa:{frst:true, scnd:false}, bas:{frst:"set", scnd:false}, qux:{frst:true, scnd:false}, quux:{frst:true, scnd:false}}
精彩评论