Skip to content
FutureBlitz

    Install

    Basics, 7 of 8

    Functions

    Parameters and results, defaults and named arguments, several results at once, ByRef, and overloads.

    What you’ll build

    The pieces of a till that prints receipts: a function that formats money, one that adds up any number of prices, one that finds the cheapest and dearest items at once, and one that applies a discount to a running total. Together they show how FutureBlitz functions take and give values.

    Parameters and a result

    A Function lists its parameters, each with its type, and its result’s type after a colon. A function with a result must Return one on every path; fb checks this when it compiles. A function whose body is one expression can write it after =>.

    till.fb
    Import std.core
    
    Function Money(cents: Int): String
        Local sign = cents < 0 ? "-" : ""
        Local whole = cents < 0 ? -cents : cents
        Return "{sign}${whole / 100}.{whole % 100:02}"
    End Function
    
    Function Line(item: String, cents: Int): String => "{item:<12}{Money(cents):>9}"
    
    Print(Line("coffee", 350))
    Print(Line("refund", -120))
    Output
    coffee          $3.50
    refund         -$1.20

    Functions are declared at a file’s top level, and can be called from anywhere in the file, above their declaration too. Every call has parentheses, even one with no arguments.

    Defaults and named arguments

    A parameter can have a default, used when the call leaves it out. A call can name an argument, like symbol: "€", to skip the parameters before it or to make the call clearer.

    till.fb
    Import std.core
    Import std.text
    
    Function Money(cents: Int, symbol: String = "$"): String
        Return "{symbol}{cents / 100}.{cents % 100:02}"
    End Function
    
    Function Line(item: String, cents: Int, width: Int = 12, symbol: String = "$"): String
        Return item.PadRight(width) + Money(cents, symbol).PadLeft(9)
    End Function
    
    Print(Line("tea", 280))
    Print(Line("tea", 280, symbol: "€"))
    Print(Line("tea", 280, 6))
    Output
    tea             $2.80
    tea             €2.80
    tea       $2.80

    A parameter can’t be assigned inside its function, unless it’s a ByRef parameter, which this page comes to below. To change a value that came in, copy it into a Local first.

    Any number of arguments

    A last parameter written prices: Int... takes the rest of a call’s arguments, however many, as an array. A call can also pass an array there as it is.

    till.fb
    Import std.core
    
    Function Total(prices: Int...): Int
        Local sum = 0
        For price In prices
            sum += price
        End For
        Return sum
    End Function
    
    Print(Total())
    Print(Total(350, 280, 425))
    Local basket = [120, 120, 999]
    Print(Total(basket))
    Print(basket)
    Output
    0
    1055
    1239
    [120, 120, 999]

    Print takes any number of values this way, of any types a string can show, which is why Print(a, b) prints both, with a space between. An array passed to Print is one value, shown as [120, 120, 999].

    Several results at once

    A function gives several values at once by returning a tuple, written in parentheses. Local can take a tuple apart into one variable for each element, and _ skips an element that isn’t needed.

    till.fb
    Import std.core
    
    Function LowHigh(prices: Int[]): (Int, Int)
        Local low = prices[0]
        Local high = prices[0]
        For price In prices
            If price < low Then low = price
            If price > high Then high = price
        End For
        Return (low, high)
    End Function
    
    Local cheapest, dearest = LowHigh([350, 120, 999, 425])
    Print("from {cheapest} to {dearest} cents")
    Local _, top = LowHigh([5, 50, 500])
    Print(top)
    Local both = LowHigh([7, 3])
    Print(both, both.0, both.1)
    Output
    from 120 to 999 cents
    500
    (3, 7) 3 7

    ByRef

    A ByRef parameter is the caller’s own variable, so assigning it changes the caller’s value. The call says ByRef too, so a reader can see which variables a call may change.

    till.fb
    Import std.core
    
    Function Discount(ByRef total: Int, percent: Int)
        total -= total * percent / 100
    End Function
    
    Local total = 2000
    Discount(ByRef total, 10)
    Print(total)
    Discount(ByRef total, 50)
    Print(total)
    Output
    1800
    900

    Only a Local, a Global, a ByRef parameter, or a field of one can be passed ByRef: not a constant, a literal, a loop variable, another parameter, an array’s element, or a computed value.

    Overloads

    Several functions can share a name when their parameter types differ. A call runs the one whose parameters fit its arguments.

    till.fb
    Import std.core
    
    Function Describe(cents: Int): String => "{cents} cents"
    Function Describe(item: String): String => "an item named {item}"
    Function Describe(item: String, cents: Int): String => "{item} at {cents} cents"
    
    Print(Describe(350))
    Print(Describe("tea"))
    Print(Describe("tea", 280))
    Output
    350 cents
    an item named tea
    tea at 280 cents

    What you learned

    • A function declares each parameter’s type and its result’s type, and returns on every path.
    • Parameters can have defaults, and a call can name its arguments.
    • values: T... takes any number of arguments as an array.
    • A tuple returns several values, and Local a, b = ... takes it apart.
    • A ByRef parameter changes the caller’s variable, and the call says ByRef too.
    • Functions with the same name and different parameter types are overloads.

    Report an issue with this page or with FutureBlitz on GitHub.