Lambda Function
2025/12/27
- Type
- Learning Resource
- Format
- Glossary Article
- Version
- General
- Subject Tags
- Created
- Updated
- 2026/02/16
- 2025/12/27
A lambda function, also known as an anonymous function, is a function that is not bound to an identifier. You can create it within other functions, pass it as an argument, or return it from a function. Contrary to methods, lambda functions are not associated with any object.
In practice, lambda functions allow you to define a function wherever you could store a value. For example, when connecting a signal, you need a function. You can define a lambda function directly in the connection call.
@onready var button: Button := %Button
func _ready() -> void:
button.pressed.connect(
func() -> void:
print("Button pressed!")
)You can create a lambda function similar to any other function by using the func keyword inside a function. You can store the lambda function in a variable and call it later. Here is an example:
func _ready() -> void:
var multiply_by_ten := func (number: int) -> int:
return number * 10To call a lambda function, you need to use the Callable.call() method:
func _ready() -> void:
# ...
var result := multiply_by_ten.call(5)
print(result) # Prints "50"In this example, the lambda function multiply_by_ten() is scoped to the _ready() function and cannot be accessed anywhere else.
Lambdas in GDScript don't always evaluate variables from the surrounding context immediately. It depends on the type of variable you are accessing:
When accessing local variables, lambdas follow the same behavior as function parameters:
You can define lambdas like any other function and give them type information all the same:
func _ready() -> void:
var multiply_by_ten := func (number: int) -> int:
return number * 10You can also name lambdas. When there is an error inside a lambda function, and you give it a name, you will see the function name in the error message. This can be helpful for debugging:
func _ready() -> void:
var multiply_by_ten := func multiply_by_ten(number: int) -> int:
return number * 10There are a few cases where lambdas are useful:
There are occasions where you know you will use a function only in that one occasion. For example, if you wanted to sort this array by age:
var characters := [
{"name": "Gimly", "age": 139 },
{"name": "Frodo Baggins", "age": 50 },
{"name": "Gandalf", "age": 2000 },
{"name": "Samwise Gamgee", "age": 33 },
]You could do this:
func _sort_by_age() -> bool:
return a["age"] < b["age"]
func _ready() -> void:
# sorting the characters by age
characters.sort_custom(_sort_by_age)This is fine, but has two issues:
_sort_by_age could be used somewhere else, so we might forget to delete it if we do not need it anymore._ready() and trying to understand what it does, you will need to jump to the function, understand it, then go back where you were. This can create confusion; we call that indirection (in this example, it doesn't create confusion, but real code is often hundreds of lines long).It's probably better to write:
func _ready() -> void:
# Sorting the characters by age
characters.sort_custom(
func (a, b) -> bool:
return a["age"] < b["age"]
)Now, if we don't want to sort the characters anymore, we can remove the entire function.
Another common use is for signals. The example below assumes a counter with three buttons, +, -, and reset:
var count := 0
@onready var button_plus: Button := %ButtonPlus
@onready var button_minus: Button := %ButtonMinus
@onready var button_reset: Label := %ButtonReset
@onready var label_counter: Label := %LabelCounter
func _ready() -> void:
button_reset.pressed.connect(
func() -> void:
count = 0
label_counter.text = "0"
)
button_plus.pressed.connect(
func() -> void:
count += 1
label_counter.text = str(count)
)
button_minus.pressed.connect(
func() -> void:
count -= 1
label_counter.text = str(count)
)Lambdas are very practical to customize behavior. By having lambda properties, you can leave "holes" to fill from somewhere else.
Here is a magical trap that does... something:
class_name MagicalTrap extends Area2D
var action := Callable()
func _ready() -> void:
body_entered.connect(_on_body_entered)
func _on_body_entered(body: CollisionObject2D) -> void:
if action.is_valid():
action.call(body)One quirk of Godot's lambdas and bound functions is that you need to explicitly call them by using the call() method.
At runtime, you can now assign any lambda to action, as long as it respects the convention (receiving a node as its unique argument).
Because lambdas can be passed around, you can also use them as function parameters:
var health := 10
func take_damage(amount: int, special: Callable) -> void:
health -= amount
if health > 0:
if special.is_valid():
special.call(self)Lambdas can use all the context that is around them, and capture it for use later.
For example, provided your player has a method like in the previous paragraph:
var health := 10
func take_damage(amount: int, special_effect: Callable) -> void:
health -= amount
if health > 0:
if special_effect.is_valid():
special_effect.call()Then an enemy could trigger a "slow" type attack like so:
var strength := 1
func attack(player):
player.take_damage(1,
func():
player.speed = player.speed / 2
)There are cases where a variable requires some processing to be generated.
In those cases, instead of doing something like:
var largest_target: Node2D = null
# ... other variables here
func _ready() -> void:
for target in get_children():
if largest_target == null or target.size > largest_target.size:
largest_target = targetYou could group the logic in a lambda function and immediately call it:
@onready var largest_target := (func() -> Node2D:
var largest_target := null
for target: Node2D in get_children():
if largest_target == null or target.size > largest_target.size:
largest_target = target
return largest_target).call()Using a lambda function groups the code together, avoiding fragmenting the logic across the script.
Wrapping the function in () creates a function expression, which we immediately invoke by calling its .call() method. This pattern is commonly called Immediately Invoked Function Expression, or IIFE for short.
This pattern is particularly useful if you need to declare one-time variables to calculate the value. Having them inside the function expression ensures they do not conflict with other scopes.
Don't stop here. Step-by-step tutorials are fun but they only take you so far.
Try one of our proven study programs to become an independent Gamedev truly capable of realizing the games you’ve always wanted to make.
Get help from peers and pros on GDQuest's Discord server!
20,000 membersJoin ServerThere are multiple ways you can join our effort to create free and open source gamedev resources that are accessible to everyone!
Sponsor this library by learning gamedev with us onGDSchool
Learn MoreImprove and build on assets or suggest edits onGithub
Contributeshare this page and talk about GDQUest onRedditYoutubeTwitter…