Module 0076: Returning values

Tak Auyeung, Ph.D.

November 25, 2018

Contents

1 About this module
2 Code without return values
3 The return value
 3.1 An example
 3.2 Tracing with return values

1 About this module

2 Code without return values

The concept of return value is somewhat optional, as any algorithm that is expressed using the return value concept can also be expressed without any use of return values. However, the use of return values sometimes makes pseudocode (and real programs) easier to understand. As such, return values are important concepts to include in a programming language.

Let us consider the algorithm in listing 1. This is the same algorithm that was used to find a prime factor in module 0049.


Listing 1: Find factor algorithm without return value.
1define sub findfactor 
2  by value n 
3  by reference f 
4  f2 
5  while nmodf0 do 
6    ff+1 
7  end while 
8end define sub

To utilize the findfactor subroutine as in listing 1, we need to use the invocation code in listing 2. We can assume variable m has an integer value that is greater than 2, and we want to see if m is a prime number or not.


Listing 2: Invoke findfactor without return value.
1local g 
2invoke findfactor mngf 
3if g=m then 
4  print "m is prime" 
5else 
6  print "m is not prime" 
7end if

Note that in listing 2, we need the use of the local variable g to store the factor of m, then use it for additional code. This code works, but it is somewhat cumbersome, especially when compared to the version using a return value.

3 The return value

3.1 An example

Let us rewrite the algorithm in listing 1 using a return value. This new code is in listing 3.


Listing 3: Find factor algorithm using a return value.
1define sub findfactor 
2  by value n 
3  local f  
4  f2 
5  while nmodf0 do 
6    ff+1 
7  end while 
8  return f  
9end define sub

The changes in the algorithm in listing 3 are as follows:

The effect of this change is that the invocation of “findfactor” can now be used as an integer value, wherever an integer value can go. This change may seem minor, but it can have a major impact of the way the invoking code is structured. In our example, we can now rewrite listing 2 as listing 4.


Listing 4: Invoke findfactor with return value.
1local g 
2g (invoke findfactor mn)  
3if g=m then 
4  print "m is prime" 
5else 
6  print "m is not prime" 
7end if

The change is on line 2. The local variable g is no longer passed as a parameter. Its value is changed because of the assignment operation. The right-hand-side of the assignment is the invocation of “findfactor”. This is possible because the invocation of “findfactor” can be treated just like any integer value, and the value itself is specified by the “return” statement in listing 3. The parantheses surrounding the invocation is there to make it clear that we are using the “return value” of the invocation. In a real programming language, the parantheses are not required.

Now that we can return a value, we can actually eliminate the use of local variable g in listing 4. Consider the code in listing 5.


Listing 5: Invoke findfactor with return value in a condition.
1if m= (invoke findfactor mnthen  
2  print "m is prime" 
3else 
4  print "m is not prime" 
5end if

Note that we do not have a local variable g anymore. Instead, the value returned by the invocation of “findfactor” is immediately utilized in the equality check, which is the condition of the conditional statement on line 1.

3.2 Tracing with return values

Tracing an algorithm that uses subroutines with return values can be challenging. This is because the invocation of such a subroutine is not on a line on its own. Instead, it is usually a part of an expression. Furthermore, someone needs to allocate the storage of the return value.

As a result, we need to “enhance” the return line # column not only to indicate the line number, but also exactly where in an expression to resume execution. With a real language and debugger, this is often done by adding the column number to the line number. However, column counting is difficult with pseudocode. As a result, we will recite the expression that invokes the subroutine, with the invocation part replaced by the ? symbol to indicate that’s where the return value goes.

Listing 6 is the integration of listing 3 and listing 5. We’ll trace this listing.


Listing 6: Example to illustrate how to trace a subroutine with return value.
1define sub findfactor 
2  by value n 
3  local f 
4  f2  
5  while nmodf0 do 
6    ff+1 
7  end while 
8  return f  
9end define sub  
10local m 
11m13  
12if m= (invoke findfactor mnthen  
13  print "m is prime"  
14else 
15  print "m is not prime" 
16end if 
17

Table 1 is the trace of algorithm 6. Note that we kind of skip most of the logic in the subroutine itself, as it is not the main point of this illustration.


A B C D E F








line # comments m

Annotation








11 13

12 retinfo n f

invoke the subroutine here

12: if m = ? then 13?

one column for each of the following: return information, parameter n, and local variable f, note how “retinfo” captures not only which line to go back to, but also what else on the line is not done

we are not interested in tracing the subroutine

8 12: if m = 13 then

the placeholder of return value is replaced by the actual return value, however, the condition is not evaluated at this point

9 retinfo n f

deallocate everything that was allocation to this invocation

12: if m = 13 then m=13 is true

true because m = 13, note how the line # column is not just saying line 12, but also what needs to be done

13

conclude the number is prime

17

we are done!


Table 1: A trace of the algorithm in listing 6.