views:

41

answers:

1

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, scnd: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}}
+1  A: 

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}}
outis