3.3. Return values

Up to now, returning from a method was always written using return. This sets the value to be returned and terminates execution of the method. Sometimes it is desirable to set the return value but not immediately return from the method. Such constructions are common in languages which only provide the return statement, and resemble the following code snippet:


{
  ...
  int result = [self computation];
  [self deallocateResources];
  return result;
}

Using the return assignment, the return value of a method can be set, without causing immediate termination. A return assignment is written as an assignment with an empty left-hand side. The example then becomes:


{
  ...
  = [self computation];
  [self deallocateResources];
}

which is much cleaner. It is customary to only use return when immediate termination of the method is necessary. The return assignment is otherwise preferred.

When a method does not assign a return value, either through return or a return assignment, the value returned by the method will be the default value of the return type. Thus, the following two method definitions are equal:


boolean
  constantp
{
  boolean v;
  = v;
}

boolean
  constantp
{
}

When a method returns a tuple the return value returned must be set atomically, i.e. it is only possible to set all values in the tuple at once. There are situation where this is undesirable, and a solution to this is provided by named return values.

In the following example, the return type is followed by a tuple of identifiers (valid, object). Each identifier denotes a local variable in the method, which is declared implicitly, and which is handled as a normal local variable. Upon return from the method, the value returned will be the tuple (valid, object). Intermediate assignments to any of these variables will have the expected result of affecting the return value. Also, normal return and return assignment still operate as expected, i.e. they will affect the value of these variables.


(bool, Any) (valid, object)
  next
{
  valid = [self haveMoreObjects];
  if (valid)
    object = [self getNextObject];
}

If one of the return value names is the name of an argument, be it the implicit receiver object self or the message selector cmd or a normal argument, that part of the return value will correspond to the value of the argument. The creation of a local variable is omitted in this case. The following method for example simply returns the value passed to it:


int (value)
  echo int value
{
}

Note that the return value name is enclosed in parentheses, i.e. a singleton tuple. Return value names must always be a tuple, otherwise the compiler can't discern between the name and the return value or the first method name part.

A good reason to name the return values is that any documentation or comments about the method can simply refer to parts of the return value by name.