Skip to main content

Callbacks in EasyBite

Callbacks let you pass functions as parameters to other functions, enabling deferred execution, event handling, and highly flexible code structures. In this guide, we’ll unpack callbacks step‑by‑step, with clear examples and detailed explanations—even if you’ve never worked with callbacks before!

Table of Contents

Why Callbacks Matter

Callbacks are a cornerstone of modern programming because they let you:

  • Decouple logic: Write general-purpose functions that call back to user‑supplied code.
  • Handle events: Respond to actions (like button clicks or data arrival) by passing a handler function.
  • Control flow: Delay or sequence operations without hard‑coding every step.

With callbacks, you can build libraries and utilities that other parts of your program—or even other developers’ code—can customize by providing their own functions.

Conceptual Overview

A callback is simply a function passed as an argument to another function, which then “calls back” that function at the appropriate time. Think of it like ordering room service: you give the hotel your room number and a callback function (the bell). When your food arrives, they ring the bell to notify you.

Key points:

  • A callback is a first‑class function value.
  • You pass it just like any other parameter.
  • Inside the caller, you invoke it by using its name and parentheses (e.g., callback(data)).

Callback Syntax in EasyBite

Callbacks look like ordinary parameters in EasyBite. Here’s the generic form:

function doSomething(param1, callback)
// inside, call the callback when ready
callback(param1)
end function
  • callback is just a parameter name.
  • You call it with callback(...) as if it were a normal function.

You can also give it a default:

function doSomething(param1, callback to defaultHandler)
callback(param1)
end function

If no callback is passed, EasyBite will use defaultHandler.

Defining and Passing Callbacks

  1. Define a callback function just like any other:

    function logger(message)
    show "[LOG] " + message
    end function
  2. Define a function that accepts it:

    function processData(value, callback)
    // do some work
    set result to value * 2
    // notify via callback
    callback(result)
    end function
  3. Pass the callback by name (without parentheses):

    processData(5, logger)

    This passes the logger function itself. Inside processData, calling callback(result) invokes logger(result).

Example: Simple Callback

A minimal example to illustrate the flow:

function greetUser(name)
show "Hello, " + name + "!"
end function

function welcome(callback, userName)
show "Welcome!"
callback(userName)
end function

// Call 'welcome', passing 'greetUser' as the callback
welcome(greetUser, "Alice")
// Output:
// Welcome!
// Hello, Alice!
  • welcome prints “Welcome!” then calls greetUser("Alice").
  • The callback allows welcome to remain generic.

Example: Using Callbacks for Filtering

Build a reusable filter utility that takes a list and a predicate callback (a function returning true/false):

from array import length

function filterList(items, predicate)
declare result
set result to []
set i to 1

repeat while(i <= length(items))
if predicate(items[i])
append result with items[i]
end if
set i to i + 1
end repeat

return result
end function

function isEven(n)
return (n % 2) = 0
end function

set myNumbers to [1, 2, 3, 4, 5]
set evens to filterList(myNumbers, isEven)
show evens // Displays: [2, 4]
  • filterList doesn’t care how you decide to filter—it just calls predicate for each item.
  • You can pass different predicates (like isOdd, isPrime, etc.) to reuse filterList.

Example: Simulating Asynchronous Callbacks

Although EasyBite doesn’t have true threads or timers built‑in, you can simulate asynchronous behavior by structuring code with callbacks:

function fetchData(url, callback)
// Simulate a delay (this is conceptual)
delay 2 // wait 2 seconds
set data to "Data from " + url
callback(data)
end function

function displayData(result)
show "Fetched: " + result
end function

// Start fetch, and supply displayData as callback
fetchData("http://api.example.com", displayData)
// After ~2 seconds:
// Fetched: Data from http://api.example.com
  • Here, fetchData “returns” via calling displayData.
  • This pattern underlies real-world APIs like event handlers and network requests.

Callbacks with Recursion

You can combine recursion with callbacks for tasks like tree traversal:

from array import length

function traverse(node, visit)
visit(node)
set i to 1
repeat while(i <= length(node.children))
traverse(node.children[i], visit)
set i to i + 1
end repeat
end function

function printNode(n)
show "Node: " + n.name
end function

// Example tree:
declare root
set root to { name: "A", children: [ { name: "B", children: [] }, { name: "C", children: [] } ] }

traverse(root, printNode)
// Output:
// Node: A
// Node: B
// Node: C
  • traverse is a recursive function that calls the visit callback for each node.

Common Pitfalls

PitfallSymptomFix
Passing a call instead of functionCallback executes immediatelyPass the function name without (): processData(5, logger)
Forgetting parentheses when calling backNo callback execution or errorInvoke with callback(arg) inside the caller function
Callback parameter naming collisionConfusing codeUse clear names like onSuccess, onError, visit, predicate
Not checking callback before callingRuntime error if nilUse default or check: if callback <> nil then callback(data)

Tips & Best Practices

  • Name callbacks descriptively: onComplete, handleResult, validateItem rather than generic cb.
  • Provide defaults: Use default arguments for callbacks to avoid nil checks.
  • Keep callback signatures consistent: Decide on few parameters (e.g., (error, result)) for event-like callbacks.
  • Avoid deep nesting: Chain callbacks with care to prevent “callback hell.” Consider breaking logic into named functions.

Conclusion

Callbacks in EasyBite unlock powerful patterns:

  • Customization: Let callers plug in their own behavior.
  • Reusability: Write utilities (like filterList) that work for many cases.
  • Control flow: Sequence and delay actions elegantly.

Experiment by writing small utilities that accept callbacks—then pass in different functions to see how they shape your program’s behavior. With callbacks mastered, you’ll build more dynamic and maintainable EasyBite code!