A function is a reusable block of code that performs a specific task.
If variables are the data, Functions are the action. They are blocks of code that we can call when we need them.
If you come from other languages, the concept will be familiar. However, Dart has a very particular way of handling parameters that is different from Java or C#, and it turns out to be the cornerstone of how code is written in Flutter.
Today we will see not only how to create functions, but how to do it “the Dart way”.
Basic Structure
A function in Dart is defined by indicating the return type, the name, and the parameters.
// Return type - Name - Parameters
int sum(int a, int b) {
return a + b;
}
void main() {
var result = sum(5, 10);
print(result); // 15
}
If the function returns nothing, we use void. Nothing new under the sun so far.
Arrow Functions
Programmers like to write less code (as long as it’s readable). When a function contains a single instruction that returns a value, we can use the arrow syntax =>.
This is what we call “Syntactic Sugar”. Look at the difference:
// Classic form
int multiply(int a, int b) {
return a * b;
}
// Arrow form (Equivalent)
int multiplyArrow(int a, int b) => a * b;
The arrow => replaces both the curly braces {} and the return keyword. It’s very common to use it in Flutter for simple callbacks (for example, when a button is pressed).
Parameter Types
This is where Dart shines. We have two ways to define function parameters: Positional and Named.
Positional Parameters
These are the mandatory ones and depend on the order in which you pass them. This is what we saw in the sum(int a, int b) example.
- Advantage: They are concise.
- Disadvantage: If you have a function with 5 parameters, it’s impossible to remember what goes where.
createUser("Luis", 30, true, "Madrid", null)is hard to read.
Named Parameters
This is the native syntax of Flutter. To define named parameters, we enclose the arguments in curly braces { }.
When calling the function, we must specify the parameter name followed by a colon. The order no longer matters.
// Definition using curly braces { }
void createUser({String? name, int? age}) {
print("User: $name, Age: $age");
}
void main() {
// Super readable call (order doesn't matter)
createUser(age: 30, name: "Luis");
}
Notice that when using {} the parameters become optional by default (that’s why I used String? and int?, because they could be null if we don’t send them).
required and Default Values
As we said, named parameters {} are optional by nature. But what if we want the readability of names but the mandatory nature of data?
For that we have the required keyword and default values.
The required keyword
It tells the compiler: “This parameter is named (called by its name), but it is MANDATORY to pass it”.
void configureWifi({required String ssid, required String password}) {
print("Connecting to $ssid with $password");
}
// configureWifi(); // ❌ Error: Missing required parameters
configureWifi(ssid: "MyHome", password: "123"); // ✅ Correct
Default Values
If a parameter is optional but we don’t want to deal with nulls, we can assign it an initial value.
void greet({String name = "Guest"}) {
print("Hello, $name");
}
greet(); // Prints: Hello, Guest
greet(name: "Ana"); // Prints: Hello, Ana
Mixed Arguments
We can mix both worlds. Dart allows having first positional parameters (mandatory by order) and then named parameters (optional or mandatory by name).
It’s important to know that positionals always come first.
// 'message' is positional, 'times' is named
void repeatMessage(String message, {int times = 1}) {
for (int i = 0; i < times; i++) {
print(message);
}
}
void main() {
repeatMessage("Hello"); // Uses default value
repeatMessage("Hello", times: 5); // Specifies repetitions
}
Functions as Values
In Dart, functions are objects. This means that you can store a function in a variable or pass a function as a parameter to another function.
This sounds abstract, but it’s what you do every time you configure a button in Flutter:
void myAction() {
print("Button pressed");
}
// Imagine this is a Flutter widget
TextButton(
onPressed: myAction, // We pass the function WITHOUT parentheses
child: Text("Press me"),
)