Skip to content
AgileLogics
6 min read

Subs and Functions

Prerequisites: Arrays

Procedures let you name a piece of code and reuse it. VB has two kinds:

  • A Sub does something and returns nothing.
  • A Function computes and returns a value.
Module Program
    Sub Greet(name As String)
        Console.WriteLine($"Hello, {name}!")
    End Sub

    Function Square(x As Integer) As Integer
        Return x * x
    End Function

    Function Bmi(weightKg As Double, heightM As Double) As String
        Dim value = weightKg / (heightM * heightM)
        Dim category As String
        If value < 18.5 Then
            category = "underweight"
        ElseIf value < 25 Then
            category = "normal"
        Else
            category = "overweight"
        End If
        Return $"{value:F1} ({category})"
    End Function

    Sub Main()
        Greet("Ada")
        Console.WriteLine(Square(6))
        Console.WriteLine(Square(Square(2)))
        Console.WriteLine(Bmi(70, 1.75))
    End Sub
End Module
Hello, Ada!
36
16
22.9 (normal)
  • Parameters are written name As Type; the return type goes after the parentheses: Function Square(...) As Integer.
  • Return value ends the function and hands back the value.
  • Variables declared inside a procedure (value, category) are local to it.

Returning early

Return can appear anywhere, which keeps code flat:

Module Program
    Function Classify(age As Integer) As String
        If age < 0 Then Return "invalid"
        If age < 13 Then Return "child"
        If age < 20 Then Return "teen"
        Return "adult"
    End Function

    Sub Main()
        For Each a In {-1, 8, 15, 42}
            Console.WriteLine($"{a}: {Classify(a)}")
        Next
    End Sub
End Module
-1: invalid
8: child
15: teen
42: adult

In a Sub, Return (or the older Exit Sub) leaves early.

Recursion

A function can call itself:

Module Program
    Function Factorial(n As Integer) As Long
        If n <= 1 Then Return 1
        Return n * Factorial(n - 1)
    End Function

    Sub Main()
        Console.WriteLine(Factorial(5))
        Console.WriteLine(Factorial(20))
    End Sub
End Module
120
2432902008176640000

The old way: assigning to the function name

Older code returns a value by assigning it to the function's name:

Module Program
    Function Double2(x As Integer) As Integer
        Double2 = x * 2
    End Function

    Sub Main()
        Console.WriteLine(Double2(21))
    End Sub
End Module
42

It still works, but Return is clearer and is the modern style.

Practice

Write Function IsLeapYear(year As Integer) As Boolean (divisible by 4, except centuries unless divisible by 400) and print the result for 1900, 2000, and 2024.

Show solution
Module Program
    Function IsLeapYear(year As Integer) As Boolean
        Return (year Mod 4 = 0 AndAlso year Mod 100 <> 0) OrElse year Mod 400 = 0
    End Function

    Sub Main()
        For Each y In {1900, 2000, 2024}
            Console.WriteLine($"{y}: {IsLeapYear(y)}")
        Next
    End Sub
End Module
1900: False
2000: True
2024: True