Module 4: Functions

In this module, you'll learn how to define reusable functions in L4.

Learning Objectives

By the end of this module, you will be able to:

  • Define functions with GIVEN and GIVETH
  • Use DECIDE and MEANS appropriately
  • Create local definitions with WHERE
  • Write recursive functions
  • Understand function application

Function Basics

This is the complete working examples to work along.

-- Module 4: Functions - Complete Examples
-- All examples are validated and use natural language identifiers

IMPORT prelude

-- =============================================================================
-- SECTION 1: Basic Functions
-- =============================================================================

-- Square a number
GIVEN n IS A NUMBER
GIVETH A NUMBER
`the square of` MEANS n * n

-- Add two numbers together
GIVEN x IS A NUMBER
      y IS A NUMBER
GIVETH A NUMBER
`the sum of` MEANS x + y

-- Check if a person is an adult
GIVEN age IS A NUMBER
GIVETH A BOOLEAN
DECIDE `the person is an adult` IF age >= 18

-- =============================================================================
-- SECTION 2: Using DECIDE IF vs MEANS
-- =============================================================================

-- These are equivalent ways to define a boolean function:
GIVEN age IS A NUMBER
GIVETH A BOOLEAN
`is adult (using MEANS)` MEANS age >= 18

GIVEN age IS A NUMBER
GIVETH A BOOLEAN
DECIDE `is adult (using DECIDE IF)` IF age >= 18

GIVEN age IS A NUMBER
GIVETH A BOOLEAN
DECIDE `is adult (using DECIDE IS)` IS age >= 18

-- =============================================================================
-- SECTION 3: Local Definitions with WHERE
-- =============================================================================

-- Compound interest calculation
GIVEN principal IS A NUMBER
      rate IS A NUMBER
      years IS A NUMBER
GIVETH A NUMBER
`the compound interest` MEANS
    principal * (`power` factor years)
    WHERE
        factor MEANS 1 + rate

        -- Simple power function (integer exponents only)
        GIVEN base IS A NUMBER
              exp IS A NUMBER
        GIVETH A NUMBER
        `power` MEANS
            IF exp <= 0
            THEN 1
            ELSE base * (`power` base (exp - 1))

-- Monthly payment calculation (simplified)
GIVEN loan IS A NUMBER
      annualRate IS A NUMBER
      months IS A NUMBER
GIVETH A NUMBER
`the monthly payment` MEANS
    loan * monthlyRate / (1 - discountFactor)
    WHERE
        monthlyRate MEANS annualRate / 12
        discountFactor MEANS `power` (1 + monthlyRate) (0 - months)

        GIVEN base IS A NUMBER
              exp IS A NUMBER
        GIVETH A NUMBER
        `power` MEANS
            IF exp <= 0
            THEN 1 / (`positive power` base (0 - exp))
            ELSE `positive power` base exp

        GIVEN base IS A NUMBER
              exp IS A NUMBER
        GIVETH A NUMBER
        `positive power` MEANS
            IF exp <= 0
            THEN 1
            ELSE base * (`positive power` base (exp - 1))

-- =============================================================================
-- SECTION 4: Recursive Functions
-- =============================================================================

-- Factorial: n!
GIVEN n IS A NUMBER
GIVETH A NUMBER
`the factorial of` MEANS
    IF n <= 1
    THEN 1
    ELSE n * (`the factorial of` (n - 1))

-- Sum a list of numbers (using recursion)
GIVEN numbers IS A LIST OF NUMBER
GIVETH A NUMBER
`the sum of the list` MEANS
    CONSIDER numbers
    WHEN EMPTY THEN 0
    WHEN x FOLLOWED BY rest THEN x + `the sum of the list` rest

-- Count elements in a list
GIVEN xs IS A LIST OF NUMBER
GIVETH A NUMBER
`the length of` MEANS
    CONSIDER xs
    WHEN EMPTY THEN 0
    WHEN x FOLLOWED BY rest THEN 1 + `the length of` rest

-- =============================================================================
-- SECTION 5: Higher-Order Functions
-- =============================================================================

-- Double each number in a list
GIVEN numbers IS A LIST OF NUMBER
GIVETH A LIST OF NUMBER
`the doubled list` MEANS
    map (GIVEN n YIELD n * 2) numbers

-- Get only positive numbers
GIVEN numbers IS A LIST OF NUMBER
GIVETH A LIST OF NUMBER
`the positive numbers in` MEANS
    filter (GIVEN n YIELD n > 0) numbers

-- Check if all numbers satisfy a condition
GIVEN numbers IS A LIST OF NUMBER
      threshold IS A NUMBER
GIVETH A BOOLEAN
DECIDE `all numbers are above threshold` IF
    all (GIVEN n YIELD n > threshold) numbers

-- =============================================================================
-- SECTION 6: Test Data
-- =============================================================================

`test numbers` MEANS LIST 1, 2, 3, 4, 5
`mixed numbers` MEANS LIST -2, -1, 0, 1, 2, 3

-- =============================================================================
-- SECTION 7: Tests
-- =============================================================================

-- Basic function tests
#EVAL `the square of` 5
#EVAL `the sum of` 3 4
#EVAL `the person is an adult` 21
#EVAL `the person is an adult` 16

-- Equivalent definitions all return TRUE for age 25
#EVAL `is adult (using MEANS)` 25
#EVAL `is adult (using DECIDE IF)` 25
#EVAL `is adult (using DECIDE IS)` 25

-- WHERE clause tests
#EVAL `the compound interest` 1000 0.05 3

-- Recursive function tests
#EVAL `the factorial of` 5
#EVAL `the sum of the list` `test numbers`
#EVAL `the length of` `test numbers`

-- Higher-order function tests
#EVAL `the doubled list` `test numbers`
#EVAL `the positive numbers in` `mixed numbers`
#EVAL `all numbers are above threshold` `test numbers` 0

The Structure of a Function

Every L4 function has these parts:

GIVEN x IS A NUMBER           -- Parameters (inputs)
      y IS A NUMBER
GIVETH A NUMBER               -- Return type (output)
`the sum of x and y` MEANS    -- Name and definition
    x + y

DECIDE vs MEANS

Both define the same thing—use whichever reads better:

-- These are equivalent
DECIDE `the person is an adult` IF age >= 18
`the person is an adult` MEANS age >= 18
DECIDE `the person is an adult` IS age >= 18
Syntax Best for
DECIDE name IS expr Rules, decisions, conditions
DECIDE name IF expr Boolean predicates
name MEANS expr Definitions, computations

Type Signatures

The GIVETH clause declares what type the function returns:

  • GIVETH A NUMBER — Returns a number
  • GIVETH A STRING — Returns a string
  • GIVETH A BOOLEAN — Returns true/false
  • GIVETH A Person — Returns a Person record
  • GIVETH A LIST OF NUMBER — Returns a list of numbers
  • GIVETH A MAYBE NUMBER — Returns a number or nothing

Function Parameters

Multiple Parameters

List parameters with GIVEN, separated by newlines or commas:

GIVEN firstName IS A STRING
      lastName IS A STRING
      age IS A NUMBER
GIVETH A Person
`create person` MEANS Person firstName lastName age

Polymorphic Functions

Use TYPE for functions that work with any type:

GIVEN a IS A TYPE
      x IS AN a
      y IS AN a
GIVETH AN a
`the first of` MEANS x

Calling Functions

Simple Function Calls

-- Define a function
GIVEN n IS A NUMBER
GIVETH A NUMBER
`the square of` MEANS n * n

-- Call it
#EVAL `the square of` 5        -- Result: 25
#EVAL `the square of` (3 + 2)  -- Result: 25

Multi-Argument Calls

-- Arguments separated by spaces
#EVAL `add` 3 5       -- Result: 8

Local Definitions with WHERE

Use WHERE to define helper values and functions:

GIVEN principal IS A NUMBER
      rate IS A NUMBER
      years IS A NUMBER
GIVETH A NUMBER
`the compound interest` MEANS
    principal * (factor ^ years)
    WHERE
        factor MEANS 1 + rate

Multiple Local Definitions

`the monthly payment` MEANS
    loan * (monthlyRate * compoundFactor) / (compoundFactor - 1)
    WHERE
        monthlyRate MEANS annualRate / 12
        compoundFactor MEANS (1 + monthlyRate) ^ months

Recursive Functions

L4 supports recursion—functions that call themselves:

Simple Recursion

GIVEN n IS A NUMBER
GIVETH A NUMBER
`the factorial of` MEANS
    IF n <= 1
    THEN 1
    ELSE n * `the factorial of` (n - 1)

#EVAL `the factorial of` 5  -- Result: 120

List Recursion

GIVEN xs IS A LIST OF NUMBER
GIVETH A NUMBER
`the sum of` MEANS
    CONSIDER xs
    WHEN EMPTY THEN 0
    WHEN x FOLLOWED BY rest THEN x + `the sum of` rest

Higher-Order Functions

Functions that take or return other functions.

Note: You must IMPORT prelude to use map, filter, all, any, etc.

Anonymous Functions (Lambdas)

Use GIVEN ... YIELD:

-- Double each number
map (GIVEN n YIELD n * 2) (LIST 1, 2, 3)
-- Result: LIST 2, 4, 6

-- Filter positive numbers
filter (GIVEN n YIELD n > 0) (LIST -1, 2, -3, 4)
-- Result: LIST 2, 4

Exercises

Exercise 1: Simple Function

Write a function that calculates the area of a rectangle.

Exercise 2: Function with WHERE

Write a function that calculates the area of a circle using π ≈ 3.14159.

Exercise 3: Recursive Function

Write a recursive function to calculate the sum of a list of numbers.

Exercise 4: Higher-Order Function

Use filter to get all numbers greater than 10 from a list. (Remember to IMPORT prelude.)


Common Mistakes

1. Missing Return Type

-- ❌ Wrong: No GIVETH
GIVEN n IS A NUMBER
`the square of` MEANS n * n

-- ✅ Right: Include GIVETH
GIVEN n IS A NUMBER
GIVETH A NUMBER
`the square of` MEANS n * n

2. Wrong Argument Order in Calls

-- Definition
GIVEN x IS A NUMBER
      y IS A NUMBER
GIVETH A NUMBER
`subtract` MEANS x - y

-- ❌ Wrong: Gets 3 - 10 = -7, not 10 - 3
#EVAL `subtract` 3 10

-- ✅ Right: Match the order in GIVEN
#EVAL `subtract` 10 3  -- Gets 10 - 3 = 7

3. Missing Parentheses in Function Calls

-- ❌ Wrong: f applied to g, not to result of g x
f g x

-- ✅ Right: Apply g to x, then f to result
f (g x)

Summary

Concept Syntax
Function definition GIVEN params GIVETH Type name MEANS expr
Decision function DECIDE name IF condition
Local definitions expr WHERE localDef MEANS value
Recursion Function calls itself in definition
Lambda GIVEN x YIELD expression
Function application functionName arg1 arg2

What's Next?

In Module 5: Regulative Rules, you'll learn how to model legal obligations, permissions, and prohibitions using L4's deontic constructs.