Lesson 10 of 51 beginner

Functions

Reusable Blocks of Power

Open interactive version (quiz + challenge)

Real-world analogy

Functions are like recipes in a cookbook. Instead of explaining how to make pancakes every time someone asks, you write the recipe ONCE and just say 'follow the pancake recipe.' In code, instead of writing the same logic over and over, you put it in a function and call it by name whenever you need it. Write once, use everywhere!

What is it?

Functions are reusable blocks of code that take inputs (parameters), perform operations, and optionally return outputs. Dart supports positional and named parameters, optional parameters with defaults, arrow functions for concise syntax, first-class functions (functions as values), anonymous functions (lambdas), and typedefs for function type aliases.

Real-world relevance

Functions are the building blocks of all software. In the team_mvp_kit project, every API call, every state update, every UI builder is a function. Well-designed functions are small, do one thing, and have clear names. The best code reads like a story: fetchUser(), validateEmail(), showError().

Key points

Code example

void main() {
  // Basic function with return type
  print(greet('Flutter'));        // Hello, Flutter!
  print(greet('Dart'));           // Hello, Dart!

  // Arrow function
  print(square(5));               // 25
  print(square(12));              // 144

  // Named parameters
  printInfo(name: 'Alice', age: 25);
  printInfo(name: 'Bob');         // uses default age

  // Optional positional parameters
  print(buildUrl('api.com', 'users'));  // https://api.com/users
  print(buildUrl('api.com'));           // https://api.com

  // Functions as values
  var numbers = [1, 2, 3, 4, 5];
  var result = applyToAll(numbers, (n) => n * n);
  print(result);                  // [1, 4, 9, 16, 25]

  // Higher-order function usage
  var evens = numbers.where(isEven).toList();
  print('Evens: $evens');         // [2, 4]

  // Chaining functional methods
  var total = numbers
      .where((n) => n > 2)
      .map((n) => n * 10)
      .reduce((a, b) => a + b);
  print('Total: $total');         // 120 (30 + 40 + 50)
}

// Named function with return type
String greet(String name) {
  return 'Hello, $name!';
}

// Arrow function
int square(int n) => n * n;

// Named parameters with defaults
void printInfo({required String name, int age = 0}) {
  print('Name: $name, Age: $age');
}

// Optional positional parameters
String buildUrl(String host, [String? path]) {
  var url = 'https://$host';
  if (path != null) url += '/$path';
  return url;
}

// Higher-order function (takes a function as parameter)
List<int> applyToAll(List<int> items, int Function(int) transform) {
  return items.map(transform).toList();
}

// Can be passed as a value
bool isEven(int n) => n % 2 == 0;

Line-by-line walkthrough

  1. 1. The main function starts
  2. 2. A comment for basic functions
  3. 3. Calling greet('Flutter') and printing the result
  4. 4. Calling greet('Dart') and printing the result
  5. 5.
  6. 6. A comment for arrow functions
  7. 7. Calling square(5) -- returns 25
  8. 8. Calling square(12) -- returns 144
  9. 9.
  10. 10. A comment for named parameters
  11. 11. Calling printInfo with both name and age specified
  12. 12. Calling printInfo with only name -- age uses default value 0
  13. 13.
  14. 14. A comment for optional positional parameters
  15. 15. buildUrl with both host and path -- returns full URL
  16. 16. buildUrl with only host -- path is null, returns base URL
  17. 17.
  18. 18. A comment for functions as values
  19. 19. Creating a list of numbers 1 through 5
  20. 20. applyToAll takes the list and an anonymous squaring function
  21. 21. Printing the result -- each number squared
  22. 22.
  23. 23. A comment for higher-order function usage
  24. 24. where() takes the isEven function by name (no parentheses!) to filter
  25. 25. Printing the even numbers
  26. 26.
  27. 27. A comment for chaining functional methods
  28. 28. Starting with the numbers list
  29. 29. where keeps only numbers greater than 2
  30. 30. map multiplies each by 10
  31. 31. reduce adds them all together
  32. 32. Printing the total: 30 + 40 + 50 = 120
  33. 33. Closing the main function
  34. 34.
  35. 35. A comment for the greet function definition
  36. 36. greet takes a String name and returns a String
  37. 37. Returns 'Hello, ' plus the name with an exclamation mark
  38. 38. Closing the function
  39. 39.
  40. 40. A comment for the arrow function
  41. 41. square takes an int and returns its square using => syntax
  42. 42.
  43. 43. A comment for named parameters
  44. 44. printInfo has a required name and optional age with default 0
  45. 45. Printing the formatted info string
  46. 46. Closing the function
  47. 47.
  48. 48. A comment for optional positional parameters
  49. 49. buildUrl takes a required host and optional path
  50. 50. Building the base URL with https
  51. 51. If path is provided, append it with a slash
  52. 52. Returning the complete URL
  53. 53. Closing the function
  54. 54.
  55. 55. A comment for the higher-order function
  56. 56. applyToAll takes a list and a transform function
  57. 57. Uses map to apply the transform to each item and returns a list
  58. 58. Closing the function
  59. 59.
  60. 60. A comment for the function value
  61. 61. isEven is a named function that returns true if n is even

Spot the bug

void main() {
  print(add(3, 5));
}

String add(int a, int b) {
  return a + b;
}
Need a hint?
Look at the return type of the function versus what it actually returns...
Show answer
The function add() is declared to return String, but a + b (where a and b are int) returns an int. Fix: change the return type from String to int: int add(int a, int b) { return a + b; }

Explain like I'm 5

Functions are like magic spells with names. You create a spell once: 'Abracadabra -- double any number!' Then whenever you need to double a number, you just say the spell name instead of explaining the whole magic trick again. The ingredients you give the spell (like the number to double) are parameters. What the spell gives back (the doubled number) is the return value. And the cool part? You can teach one spell to another spell -- that is first-class functions!

Fun fact

The concept of functions in programming comes from mathematics (f(x) = x + 1). But the idea of 'first-class functions' -- treating functions as values -- was invented in the 1950s with the LISP programming language. Dart, JavaScript, Python, and many modern languages all support this, making code more flexible and powerful!

Hands-on challenge

Write three functions: (1) A function 'celsiusToFahrenheit' that converts Celsius to Fahrenheit (F = C * 9/5 + 32). (2) A function 'isPositive' that returns true if a number is greater than 0. (3) A function 'applyDiscount' with named parameters: price (required) and percent (default 10). Test all three!

More resources

Open interactive version (quiz + challenge) ← Back to course: Flutter & Dart