DekGenius.com
[ Team LiB ] Previous Section Next Section

8.1 Returned Value

When a handler is executed, it may return a value. By this we mean that it generates a value which becomes the value of the call that executed the handler. We may speak of the returned value as the result of the handler.

The term result is used here in a technical sense. A handler may do other things besides return a result, and these other things may be quite significant in the world outside of the handler; technically these are not the result of calling the handler, but its side-effects . Thus, if you call a handler that erases your hard drive and returns the number 1, you might say in ordinary conversation, "The result of calling the handler was that my hard drive was erased," but technically you'd be wrong: the result was 1; the erasure of your hard drive was a side-effect. (This shows that a side-effect can be much more important than a result.)


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 384. This means that a call to getRam( ) can presently be used wherever I would use the number 384; in effect, it is the number 384. 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 384 would behave in this context: it is implicitly coerced to a string and concatenated with the other two strings (as explained under Section 15.5), 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.

For the same reason that I recommend that you not use the result keyword (see Section 6.2), 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 wherever the handler ends execution.


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 Section 7.2). 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. Thus an attempt to fetch its 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 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. Of course, you could just call the handler again; but there are good reasons why this strategy might not be the right one:

  • The handler might be such that, when called on different occasions, it yields different results; 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 from the variable each time it is needed.

The result of a handler may be ignored if the caller doesn't care about it (or knows that no value will be returned). In this case the handler is called entirely for its side-effects. Generally the call will appear as the only thing in the line:

eraseMyHardDisk(  )
    [ Team LiB ] Previous Section Next Section