AppleScript_ The Definitive Guide - Matt Neuburg [79]
For example:
on getRam( )
set bytes to system attribute "ram "
return bytes div (2 ^ 20)
end getRam
The handler getRam returns the amount of RAM installed on the user's machine, in megabytes. On my machine, it returns the number 1024. This means that a call to getRam( ) can presently be used wherever I would use the number 1024; in effect, it is the number 1024. For example:
on getRam( )
set bytes to system attribute "ram "
return bytes div (2 ^ 20)
end getRam
display dialog "You have " & getRam( ) & "MB of RAM. Wow!"
The call to getRam( ) in the last line behaves exactly as the number 1024 would behave in this context: it is a number, it is implicitly coerced to a string and concatenated with the other two strings (as explained under "Concatenation Operator" in Chapter 15), and the full resulting string is displayed to the user.
The value returned by a handler is determined in one of two ways:
An explicit return
The handler, in the course of execution, encounters a line consisting of the keyword return, possibly followed by a value. At that point execution of the handler ceases, and the returned value is whatever follows the return keyword (which could be nothing, in which case no value is returned).
An implicit result
The handler finishes executing without ever encountering an explicit return. In that case, the returned value is the result of the last-executed line of the handler.
Tip
For the same reason that I recommend that you not use the result keyword (see "Result" in Chapter 5), I recommend that you not use a handler's ability to return an implicit result. If you're going to capture a handler's result, use an explicit return statement in the handler.
If a handler returns no value, there is no error; but in that case it is a runtime error to attempt to use the call as if it had a value. The status of such a call is similar to that of a variable that has never been assigned a value (see "Declaration and Definition of Variables" in Chapter 7). So, for example, there's nothing wrong with this:
on noValue( )
return
end noValue
set x to noValue( )
After that, even if x was previously defined, it is now undefined. That outcome is actually useful if you wanted to undefine x; there's no other way to do it. But remember, a subsequent attempt to fetch x's value will generate a runtime error:
on noValue( )
return
end noValue
set x to 1
set x to noValue( )
set x to x + 1 -- error: The variable x is not defined
The result of a handler is volatile. It is substituted for the call, but the call itself is not storage (it isn't a variable), so the result is then lost. If you wish to use the result of a handler again later, it is up to you to capture it at the time you make the call—for example, by setting a variable to it. Of course, you could just call the handler again; but there are good reasons why this strategy might not be right:
The handler might yields different results on different occasions; if you wanted the particular result of a particular call, calling it again won't do.
The handler might do other things besides return a result (side effects); to perform these side effects again might not be good, or might not make sense.
Storing a result and using it later is far more efficient than calling the handler a second time.
So, for example, this code works, but it is very poor code:
on getRam( )
set bytes to system attribute "ram "
return bytes div (2 ^ 20)
end getRam
set s to "You have " & getRam( ) & "MB of RAM. Wow! "
set s to s & getRam( ) & "MB is a lot!"
display dialog s
The handler is called twice to get the same unchanging result, which is very inefficient. The right way would be more like this:
on getRam( )
set bytes to system attribute "ram "
return bytes div (2 ^ 20)
end getRam
set myRam to getRam( )
set s to "You have " & myRam & "MB of RAM. Wow! "
set s to s & myRam & "MB is a lot!"
display dialog s
The second version calls the handler and immediately stores the result in a variable. Now it suffices to fetch the value