Understanding Closures
Part of the Logic & Flow section of Coddy's Dart journey — lesson 46 of 65.
A closure is a special type of function that "remembers" variables from the place where it was created, even after that original context has finished running. Think of it as a function that carries a piece of its birthplace with it wherever it goes.
When you create a function inside another function, the inner function has access to the outer function's variables. What makes this a closure is that this access persists even after the outer function has completed its execution.
Function createGreeting(String name) {
return () {
return "Hello, $name!";
};
}In this example, the anonymous function returned by createGreeting is a closure. It captures the name parameter from its surrounding scope. Even after createGreeting finishes running, the returned function still remembers what name was.
Closures are incredibly useful for creating specialized functions or maintaining state in a clean way. They allow you to build functions that are customized based on the environment where they were created, making your code more flexible and powerful.
Challenge
EasyCreate a program that demonstrates closures by building a personalized message generator system. Your program will create functions that "remember" specific information and use that information to generate customized messages even after the original context has finished.
- Read a string input representing a person's name
- Read a string input representing a greeting type (
"formal","casual", or"friendly") - Read a string input representing a company name
- Create a function called
createMessageGeneratorthat takes a name and greeting type as parameters - The
createMessageGeneratorfunction should return another function (a closure) that: - Takes a company name as its parameter
- Uses the name and greeting type from the outer function's scope
- Returns a formatted message based on the greeting type:
- For
"formal":"Dear [name], we are pleased to welcome you to [company]." - For
"casual":"Hey [name]! Welcome to [company]!" - For
"friendly":"Hi [name], so glad you joined [company]!" - Call the
createMessageGeneratorfunction with the name and greeting type inputs to get your closure function - Call the returned closure function with the company name input to generate the message
- Display the results in the exact format shown below
For example, if the inputs are "Alice", "formal", and "TechCorp", your program should output:
Message Generator System
========================
Creating message generator for: Alice
Greeting type: formal
Company: TechCorp
========================
Generated message: Dear Alice, we are pleased to welcome you to TechCorp.
Message generation completed successfullyIf the inputs are "Bob", "casual", and "StartupXYZ", your program should output:
Message Generator System
========================
Creating message generator for: Bob
Greeting type: casual
Company: StartupXYZ
========================
Generated message: Hey Bob! Welcome to StartupXYZ!
Message generation completed successfullyIf the inputs are "Carol", "friendly", and "InnovateLab", your program should output:
Message Generator System
========================
Creating message generator for: Carol
Greeting type: friendly
Company: InnovateLab
========================
Generated message: Hi Carol, so glad you joined InnovateLab!
Message generation completed successfullyYour program must demonstrate closures by creating a function that returns another function. The returned function (closure) should have access to the variables from the outer function's scope (name and greeting type) even after the outer function has finished executing. Use conditional statements to determine the appropriate message format based on the greeting type input.
Cheat sheet
A closure is a function that "remembers" variables from the place where it was created, even after that original context has finished running.
When you create a function inside another function, the inner function has access to the outer function's variables. This access persists even after the outer function has completed its execution.
Function createGreeting(String name) {
return () {
return "Hello, $name!";
};
}In this example, the anonymous function returned by createGreeting is a closure. It captures the name parameter from its surrounding scope. Even after createGreeting finishes running, the returned function still remembers what name was.
Closures are useful for creating specialized functions or maintaining state in a clean way. They allow you to build functions that are customized based on the environment where they were created.
Try it yourself
import 'dart:io';
void main() {
// Read input
String? name = stdin.readLineSync();
String? greetingType = stdin.readLineSync();
String? company = stdin.readLineSync();
// Display system header
print("Message Generator System");
print("========================");
print("Creating message generator for: $name");
print("Greeting type: $greetingType");
print("Company: $company");
print("========================");
// TODO: Write your code below
// Create the createMessageGenerator function that returns a closure
// Call the function and generate the message
// Output the final results
print("Generated message: \$message");
print("Message generation completed successfully");
}This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Advanced List Manipulation
List Properties: first & lastList State: isEmpty & isNotEmpReversing a ListAdding to a List: insertList Removal: removeWhereFinding in a List: indexOfSorting a ListShuffling a ListRecap - List Organizer4Advanced Map Manipulation
Iterating Over a MapChecking for Keys and ValuesMap Properties: keys & valuesConditional Add: putIfAbsentRemoving Entries from a MapNested MapsRecap - Inventory Update7Advanced Functions
Anonymous FunctionsPassing Functions as ArgumentsUnderstanding ClosuresIntroduction to RecursionRecursive Function: CountdownRecursive Function: FactorialRecap - List Processor2Functional List Operations
Transforming with 'map'Filtering with 'where'Using '.toList()'Checking Conditions with 'any'Conditions with 'every'Finding with 'firstWhere'Recap - Data Filtering5Project: Shopping Cart Calc
Project SetupAdding Items to the Cart3Sets
What is a Set?Creating a SetAdding and Removing from SetsChecking for Elements in a SetConverting a List to a SetSet UnionSet IntersectionSet DifferenceRecap - Unique Guest List