Skip to content
Lesson 4 of 6

Step 1 of 5 · Reading · ~4 min

Learn

Subs, Functions, Arrays

Subs and Functions

By the end of this lesson you can split a program into named pieces: a SUB that does something, a FUNCTION that hands back a value, and a recursive function that solves a problem by calling itself on a smaller one.

SUB

A SUB is a named block of statements that returns nothing.

SUB Banner(title AS STRING)
    PRINT "== " & title & " =="
END SUB

Banner "Report"
Banner "Totals"
== Report ==
== Totals ==

You call a SUB by writing its name followed by the arguments, with no parentheses needed (CALL Banner("Report") also works). The definition must come before the first call, or be announced with DECLARE as shown below.

FUNCTION and RETURN

A FUNCTION produces a value. Its return type follows the parameter list, and RETURN hands the value back and leaves the function at once:

FUNCTION Square(n AS INTEGER) AS INTEGER
    RETURN n * n
END FUNCTION

PRINT STR(Square(7) + 1)     ' 50

Older code assigns to the function's own name (Square = n * n) instead; it still works, but RETURN says plainly what happens. A function that returns a number is still a number, so the sign column from the Variables lesson applies: PRINT Square(7) writes " 49", and PRINT STR(Square(7)) writes "49".

DECLARE for forward references

If you call a procedure above the place where it is defined, announce its signature first:

DECLARE FUNCTION Square(n AS INTEGER) AS INTEGER

PRINT STR(Square(5))         ' 25

FUNCTION Square(n AS INTEGER) AS INTEGER
    RETURN n * n
END FUNCTION

Variables are local to a procedure

A variable declared inside a SUB or FUNCTION, including its parameters, exists only while that procedure runs. The reverse is also true: a variable declared at the top of the file is not visible inside a procedure unless it was declared DIM SHARED. Using it anyway gives "variable not declared", the same error as a typo. The clean way to get data into a procedure is a parameter, and the clean way out is RETURN.

BYVAL and BYREF

By default a numeric parameter is passed BYVAL: the procedure receives a copy, so changing it does not touch the caller's variable. Mark a parameter BYREF and the procedure works on the caller's own variable:

SUB Bump(BYREF n AS INTEGER)
    n = n + 10
END SUB

DIM x AS INTEGER = 5
Bump x
PRINT STR(x)                 ' 15

Remove the word BYREF and x stays 5, because Bump added 10 to its private copy.

Recursion

A function may call itself. The idea is to express the answer for a problem in terms of the answer for a smaller one, until the problem is small enough to answer directly:

FUNCTION SumTo(n AS INTEGER) AS INTEGER
    IF n = 1 THEN RETURN 1
    RETURN n + SumTo(n - 1)
END FUNCTION

Trace SumTo(3). Each call waits for the one below it:

SumTo(3) = 3 + SumTo(2)
                  SumTo(2) = 2 + SumTo(1)
                                  SumTo(1) = 1      <- base case, no more calls
SumTo(2) = 2 + 1 = 3
SumTo(3) = 3 + 3 = 6

Two parts are mandatory. The base case returns without recursing, and the recursive step moves the argument toward that base case. Leave the base case out, or call with an argument that never shrinks, and the calls never stop: each one uses stack memory until the program crashes.

Common mistakes

  • Printing a function result with a bare PRINT. The arithmetic is right and a leading space fails the test.
  • A recursive step that does not shrink the problem, or shrinks it the wrong way, so the base case is never reached.
  • A base case that returns the wrong value for the smallest input. The smallest inputs are exactly what the hidden tests try first.
  • Using a file-level variable inside a procedure instead of passing it in.
  • Dividing with / when a whole-number step is needed. / gives a fraction, and storing it in an integer rounds instead of cutting, so the digits change.

Your exercise

Write a recursive function that adds up the decimal digits of a number. The starter already contains a SUB that prints the result line, reads the number, and calls your function; its body is a placeholder that always answers 0. Think about what the last digit of a number is, what remains when you remove it, and what the smallest number is.

Up nextArraysSubs, Functions, Arrays

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…