On this page23 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. Required Positional Parameters: A Recap
- 2. Making a Parameter Optional with [ ]
- 3. You Have Already Used One
- 4. An Optional Parameter Needs a Default
- 5. Nullable Optional Parameters
- 6. Several Optional Parameters
- 7. Passing null Does Not Skip a Parameter
- 8. Order Rule: Required First, Optional Last
- 9. The Number of Arguments Is Still Checked
- 10. Default Values Must Be Constant
- 11. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 32 — Positional Parameters
| Category | 6 — Functions |
| Lecture | 032 of 140 |
| Estimated video length | 9 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
Until now every parameter was required: miss one and the program does not compile. Optional positional parameters let the caller leave a value out, and a default value fills the gap.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.
Prerequisites
Students should already understand, from Lectures 001–031:
- nullable types (
String?), the??operator, andconst(Lectures 006 and 013–014) - the string method
substring(Lecture 008) ifstatements- functions with typed parameters and return values (Lecture 031)
Connection With Previous Lectures
In Lecture 031 we wrote a greeting function:
void greet(String name, String greeting) {
print('$greeting, $name!');
}Almost every call uses 'Hello', yet the caller must type it every single time —
greet('Ali', 'Hello'), greet('Sara', 'Hello'). Leave it out and Dart stops with
Too few positional arguments. We need a way to say: "this value is usually 'Hello';
only pass it when you want something different."
Learning Objectives
By the end of this lecture you will be able to:
- Explain what makes a parameter positional and required
- Make parameters optional with square brackets
[ ] - Give an optional parameter a default value
- Use a nullable optional parameter and handle the
nullcase - Pass some optional arguments and leave out the rest
- Follow the order rules: required parameters first, optional ones last
- Recognize the errors Dart gives when these rules are broken
1. Required Positional Parameters: A Recap
Every parameter we have written so far is positional — arguments are matched by their position — and required — each one must be passed.
void showStudent(String name, int marks) {
print('$name scored $marks');
}
void main() {
showStudent('Sara', 95);
}Sara scored 95The first argument goes to name, the second to marks. Pass only one, and Dart refuses:
Error: Too few positional arguments: 2 required, 1 given.2. Making a Parameter Optional with [ ]
Wrap a parameter in square brackets to make it optional, and give it a value with =.
That value is its default value: the one it gets when the caller leaves it out.
Analogy — ordering tea at a café. If you just say "tea", you get a regular cup; you only mention the size when you want something different. The size is optional, and "regular" is its default.
void greet(String name, [String greeting = 'Hello']) {
print('$greeting, $name!');
}
void main() {
greet('Ali');
greet('Sara', 'Good morning');
}Hello, Ali!
Good morning, Sara!name is still required. greeting is optional: the first call leaves it out and gets
'Hello'; the second passes 'Good morning', which replaces the default.
3. You Have Already Used One
In Lecture 008, substring worked with one argument or two. Its second parameter is an
optional positional parameter:
void main() {
String word = 'Notebook';
print(word.substring(0, 4));
print(word.substring(4));
}Note
bookWithout the second argument, substring goes to the end of the string. Now you can write
functions that behave the same way.
4. An Optional Parameter Needs a Default
What if we leave out the default?
void greet(String name, [String greeting]) {
print('$greeting, $name!');
}
void main() {
greet('Ali');
}Error: The parameter 'greeting' can't have a value of 'null' because of its type 'String', but the implicit default value is 'null'.
Try adding either an explicit non-'null' default value or the 'required' modifier.When an optional argument is left out, the parameter needs some value. With no default
written, Dart would use null — and String does not allow null. You have two fixes:
give it a default (Step 2), or make its type nullable (Step 5). The required modifier the
message mentions belongs to named parameters, in Lecture 033.
5. Nullable Optional Parameters
Sometimes there is no sensible default — a person may simply have no title. Make the type
nullable, and the implicit default is null:
void showName(String name, [String? title]) {
if (title == null) {
print(name);
} else {
print('$title $name');
}
}
void main() {
showName('Ali');
showName('Sara', 'Dr.');
}Ali
Dr. SaraInside the function, title is a String?, so Dart makes you handle the null case before
using it — just like any other nullable variable from Lecture 013. The ?? operator is often
the shortest way:
void showCity(String name, [String? city]) {
print('$name lives in ${city ?? 'an unknown city'}');
}
void main() {
showCity('Zayan', 'Lahore');
showCity('Ali');
}Zayan lives in Lahore
Ali lives in an unknown city6. Several Optional Parameters
All optional parameters go inside one pair of brackets, separated by commas:
void order(String item, [int quantity = 1, double price = 50]) {
print('$quantity x $item = ${quantity * price}');
}
void main() {
order('Pen');
order('Notebook', 3);
order('Bag', 2, 1200);
}1 x Pen = 50.0
3 x Notebook = 150.0
2 x Bag = 2400.0Optional arguments are still matched by position, filled from left to right. So you can pass the quantity alone, but you cannot pass the price without also passing the quantity — there is no way to skip a position.
7. Passing null Does Not Skip a Parameter
A common idea is to pass null to "use the default". It does not work: a parameter of type
String never accepts null, even an optional one.
void greet(String name, [String greeting = 'Hello']) {
print('$greeting, $name!');
}
void main() {
greet('Ali', null); // ✗
}Error: The argument type 'Null' can't be assigned to the parameter type 'String'.
greet('Ali', null); // ✗
^The default is used only when the argument is left out. To use it, simply stop before
that position: greet('Ali').
8. Order Rule: Required First, Optional Last
Required parameters always come first, and the bracket group must be the last thing in the parameter list. Putting a required parameter after it is a syntax error:
void greet([String greeting = 'Hello'], String name) {
print('$greeting, $name!');
}
void main() {
greet('Hi', 'Ali');
}Error: Expected ')' before this.
void greet([String greeting = 'Hello'], String name) {
^Dart expects the list to end right after ] (the follow-on errors it also prints vanish
with this one). The rule makes sense: if an optional parameter
came first, Dart could not tell whether your first argument was meant for it or for the
required one. Put String name first and the error is gone.
9. The Number of Arguments Is Still Checked
Optional parameters widen the range, but there is still a minimum and a maximum. With one required and one optional parameter, a call needs one or two arguments:
void greet(String name, [String greeting = 'Hello']) {
print('$greeting, $name!');
}
void main() {
greet('Ali', 'Hi', 'Sara'); // ✗
}Error: Too many positional arguments: 2 allowed, but 3 found.
Try removing the extra positional arguments.Calling greet() with nothing fails too: Too few positional arguments: 1 required, 0 given.
10. Default Values Must Be Constant
A default value is fixed when the program is compiled, so it must be a constant: a
literal like 'Hello' or 0.05, or a const variable. An ordinary variable is rejected:
double rate = 0.05;
double addTax(double price, [double tax = rate]) {
return price + price * tax;
}
void main() {
print(addTax(100));
}Error: Not a constant expression.
double addTax(double price, [double tax = rate]) {
^^^^Change the first line to const double rate = 0.05; and it compiles, printing 105.0.
11. A Real-World Example
const double standardTax = 0.05;
double finalPrice(
double price, [
int quantity = 1,
double tax = standardTax,
double? discount,
]) {
double subtotal = price * quantity;
double afterDiscount = subtotal - (discount ?? 0);
return afterDiscount + afterDiscount * tax;
}
void main() {
print(finalPrice(200));
print(finalPrice(200, 3));
print(finalPrice(200, 3, 0.10));
print(finalPrice(200, 3, 0.10, 100));
}210.0
630.0
660.0
550.0price is required. quantity and tax have defaults, the tax coming from a const
variable. discount has no sensible default, so it is nullable and handled with ??.
Each call passes one more argument, always from left to right. When the list grows this
long, dart format puts one parameter on each line, as shown.
Code Examples
Example 1 — Required Positional Parameters
int add(int a, int b) {
return a + b;
}
void main() {
print(add(7, 5));
}12Example 2 — One Optional Parameter with a Default
void welcome(String name, [String place = 'Dart class']) {
print('Welcome to $place, $name!');
}
void main() {
welcome('Zayan');
welcome('Sara', 'the library');
}Welcome to Dart class, Zayan!
Welcome to the library, Sara!Example 3 — A Default Number
int power(int base, [int exponent = 2]) {
int result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
void main() {
print(power(5));
print(power(2, 10));
}25
1024Example 4 — A Nullable Optional Parameter
void showPhone(String name, [String? phone]) {
print('$name: ${phone ?? 'no phone'}');
}
void main() {
showPhone('Ali', '0300-1234567');
showPhone('Sara');
}Ali: 0300-1234567
Sara: no phoneExample 5 — Two Optional Parameters
void line(String text, [int times = 1, String separator = ' ']) {
String result = text;
for (int i = 1; i < times; i++) {
result = '$result$separator$text';
}
print(result);
}
void main() {
line('Hi');
line('Hi', 3);
line('Hi', 3, '-');
}Hi
Hi Hi Hi
Hi-Hi-HiExample 6 — A Default from a const Variable
const String defaultCurrency = 'PKR';
String formatPrice(double amount, [String currency = defaultCurrency]) {
return '$amount $currency';
}
void main() {
print(formatPrice(499));
print(formatPrice(20, 'USD'));
}499.0 PKR
20.0 USDExample 7 — Student Marks
String result(String name, int marks, [int passMark = 50]) {
if (marks >= passMark) {
return '$name passed';
}
return '$name failed';
}
void main() {
print(result('Ali', 55));
print(result('Sara', 55, 60));
}Ali passed
Sara failedHow it works
- Most subjects use the usual pass mark, so
passMarkdefaults to50. - A harder subject passes
60, and the same55now fails.
Example 8 — Shopping Total
double total(double price, [int quantity = 1, double delivery = 150]) {
return price * quantity + delivery;
}
void main() {
print('Book: ${total(800)}');
print('Pens: ${total(40, 10)}');
print('Pickup: ${total(800, 1, 0)}');
}Book: 950.0
Pens: 550.0
Pickup: 800.0How it works
- To change
delivery, the caller must also passquantity— even when it is the default1. Positions cannot be skipped.
Example 9 — Bank Balance
int withdraw(int balance, int amount, [int fee = 0]) {
int cost = amount + fee;
if (cost > balance) {
print('Declined');
return balance;
}
return balance - cost;
}
void main() {
int balance = 1000;
balance = withdraw(balance, 300);
print('Balance: $balance');
balance = withdraw(balance, 200, 25);
print('Balance: $balance');
}Balance: 700
Balance: 475How it works
- A normal withdrawal is free, so
feedefaults to0. - An ATM withdrawal passes a fee of
25, which is added to the cost.
Example 10 — Temperature Conversion
double convert(double value, [String to = 'F']) {
if (to == 'C') {
return (value - 32) * 5 / 9;
}
return value * 9 / 5 + 32;
}
void main() {
print(convert(30));
print(convert(212, 'C'));
}86.0
100.0Converting Celsius to Fahrenheit is the common case, so it is the default.
Common Beginner Mistakes
1. An optional non-nullable parameter with no default
// void greet(String name, [String greeting]) { ... }Error: The parameter 'greeting' can't have a value of 'null' because of its type 'String', but the implicit default value is 'null'.Give it a default (= 'Hello') or make the type nullable (String?).
2. A required parameter after the optional ones
// void greet([String greeting = 'Hello'], String name) { ... }Error: Expected ')' before this.The [ ] group must come last.
3. Passing null to use the default
// void greet(String name, [String greeting = 'Hello']) { ... }
// greet('Ali', null);Error: The argument type 'Null' can't be assigned to the parameter type 'String'.Leave the argument out instead.
4. Trying to skip a position
// void order(String item, [int quantity = 1, double price = 50]) { ... }
// order('Pen', 2.5); // meant as the priceError: The argument type 'double' can't be assigned to the parameter type 'int'.The second argument always goes to quantity. Write order('Pen', 1, 2.5).
5. Using a nullable parameter without checking it
// void showName(String name, [String? title]) {
// print(title.length);
// }Error: Property 'length' cannot be accessed on 'String?' because it is potentially null.Check for null first, or use ??.
6. A non-constant default value
// double rate = 0.05;
// double addTax(double price, [double tax = rate]) { ... }Error: Not a constant expression.Make the variable const.
Best Practices
- Make a parameter optional only when most callers would pass the same value.
- Prefer a default value; use a nullable optional parameter only when there is no sensible default.
- Put the optional parameter that callers change most often first inside the brackets, so they rarely need to fill in the others.
- Keep optional positional parameters to one or two. A call like
f(200, 3, 0.10, 100)is hard to read — named parameters (Lecture 033) solve this. - Use a
constvariable for a default that appears in several functions.
Mini Challenge
Write a function reportCard that takes a required String name and int marks, plus an
optional int total that defaults to 100. It returns a String like
'Ali: 45/50 (90.0%)'. Call it for Ali (45 out of 50), Sara (88), and Zayan (72).
Your program should print exactly:
Ali: 45/50 (90.0%)
Sara: 88/100 (88.0%)
Zayan: 72/100 (72.0%)Try it yourself before opening the solution.
Show solution
String reportCard(String name, int marks, [int total = 100]) {
double percent = marks / total * 100;
return '$name: $marks/$total ($percent%)';
}
void main() {
print(reportCard('Ali', 45, 50));
print(reportCard('Sara', 88));
print(reportCard('Zayan', 72));
}Ali: 45/50 (90.0%)
Sara: 88/100 (88.0%)
Zayan: 72/100 (72.0%)How it works
totalsits in brackets with a default of100, so Sara's and Zayan's calls leave it out.- Ali's test was out of
50, so his call passes it as the third argument.
Practice Questions
Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.
Beginner
- Write
void sayHi(String name, [String punctuation = '!'])that printsHi, <name><punctuation>. Call it with'Zayan', then with'Sara'and'?'. - Write
int square(int n)and printsquare(9). Isnpositional, optional, or both? - Write
void introduce(String name, [int? age])that printsI am Aliwhen no age is given andI am Sara, 21when it is.
Application
- Write
double area(double width, [double height = 1]). Printarea(5)andarea(5, 4). - Write
int countdownSum(int from, [int to = 0])that adds every number fromfromdown totowith a loop. PrintcountdownSum(4)andcountdownSum(10, 8). - Write
String repeat(String text, [int times = 2])that returnstextjoined to itselftimestimes. Printrepeat('ab')andrepeat('ab', 3). - Using
void order(String item, [int quantity = 1, double price = 50])from Step 6, write the call that orders 1'Ruler'at price30. - Write
double deposit(double balance, [double amount = 100]). Starting from500, deposit the default, then250, printing the balance each time.
Challenge
- Write
String temperature(double celsius, [String? city])that returns'34.0°C in Karachi'when a city is given and'34.0°C'when it is not. Print both. - Write
double bill(double price, [int quantity = 1, double? coupon]). The coupon is an amount to subtract. Printbill(300),bill(300, 2), andbill(300, 2, 50).
Practice Answers
Question 1 — Solution
void sayHi(String name, [String punctuation = '!']) {
print('Hi, $name$punctuation');
}
void main() {
sayHi('Zayan');
sayHi('Sara', '?');
}Hi, Zayan!
Hi, Sara?Question 2 — Solution
int square(int n) {
return n * n;
}
void main() {
print(square(9));
}81n is positional and required — it has no brackets.
Question 3 — Solution
void introduce(String name, [int? age]) {
if (age == null) {
print('I am $name');
} else {
print('I am $name, $age');
}
}
void main() {
introduce('Ali');
introduce('Sara', 21);
}I am Ali
I am Sara, 21Question 4 — Solution
double area(double width, [double height = 1]) {
return width * height;
}
void main() {
print(area(5));
print(area(5, 4));
}5.0
20.0Question 5 — Solution
int countdownSum(int from, [int to = 0]) {
int sum = 0;
for (int i = from; i >= to; i--) {
sum += i;
}
return sum;
}
void main() {
print(countdownSum(4));
print(countdownSum(10, 8));
}10
27Question 6 — Solution
String repeat(String text, [int times = 2]) {
String result = '';
for (int i = 0; i < times; i++) {
result += text;
}
return result;
}
void main() {
print(repeat('ab'));
print(repeat('ab', 3));
}abab
abababQuestion 7 — Solution
void order(String item, [int quantity = 1, double price = 50]) {
print('$quantity x $item = ${quantity * price}');
}
void main() {
order('Ruler', 1, 30);
}1 x Ruler = 30.0The quantity must be written out, even though 1 is its default — otherwise 30 would land
in quantity.
Question 8 — Solution
double deposit(double balance, [double amount = 100]) {
return balance + amount;
}
void main() {
double balance = 500;
balance = deposit(balance);
print('Balance: $balance');
balance = deposit(balance, 250);
print('Balance: $balance');
}Balance: 600.0
Balance: 850.0Question 9 — Solution
String temperature(double celsius, [String? city]) {
if (city == null) {
return '$celsius°C';
}
return '$celsius°C in $city';
}
void main() {
print(temperature(34, 'Karachi'));
print(temperature(34));
}34.0°C in Karachi
34.0°CQuestion 10 — Solution
double bill(double price, [int quantity = 1, double? coupon]) {
return price * quantity - (coupon ?? 0);
}
void main() {
print(bill(300));
print(bill(300, 2));
print(bill(300, 2, 50));
}300.0
600.0
550.0Quick Revision
- What makes a parameter "positional"?
- How do you make a positional parameter optional?
- When is a default value used?
- Why does
[String greeting]not compile? - What is the implicit default of a
String?optional parameter? - Can you pass the second optional argument without the first?
- Where must the
[ ]group go in the parameter list? - What kind of value can a default be?
Key Takeaways
- Positional arguments are matched to parameters by position.
- Parameters without brackets are required; parameters inside
[ ]are optional. - A default value (
= 'Hello') is used only when the argument is left out. - A non-nullable optional parameter must have a default; a nullable one defaults to
null. - Handle a nullable optional parameter with an
ifcheck or??. - Optional arguments fill from left to right — you cannot skip a position, and passing
nulldoes not mean "use the default". - The
[ ]group comes last, after all required parameters. - Default values must be constants: literals or
constvariables.
What's Next?
Lecture 033 — Named Parameters. A call like finalPrice(200, 3, 0.10, 100) works, but
what do 0.10 and 100 mean? And to change the last value you must fill in every one
before it. Next we learn named parameters, which are passed by name instead of position
— in any order, skipping whichever you like — along with the required keyword from
Step 4's error message.