Skip to content

Lambda expressions#

Code Example

Runnable Example in Jac and JacLib

# Lambda Expressions

with entry {
    # Lambda with parameters and return hint
    add = lambda a: int, b: int -> int : a + b;
    print(add(5, 3));

    # Lambda without parameters
    get_value = lambda : 42;
    print(get_value());

    # Lambda without return hint
    multiply = lambda x: int, y: int : x * y;
    print(multiply(4, 5));

    # Lambda with only return hint
    get_default = lambda -> int : 100;
    print(get_default());

    # Lambda with default parameters
    power = lambda x: int = 2, y: int = 3 : x ** y;
    print(power());
    print(power(5));
    print(power(5, 2));

    # Lambda as argument to function
    numbers = [1, 2, 3, 4, 5];
    squared = list(map(lambda x: int : x ** 2, numbers));
    print(squared);

    # Lambda in filter
    evens = list(filter(lambda x: int : x % 2 == 0, numbers));
    print(evens);

    # Lambda with conditional expression
    max_val = lambda a: int, b: int : a if a > b else b;
    print(max_val(10, 20));
    print(max_val(30, 15));

    # Lambda returning lambda
    make_adder = lambda x: int : (lambda y: int : x + y);
    add_five = make_adder(5);
    print(add_five(10));

    # Lambda in sort key
    words = ["apple", "pie", "a", "cherry"];
    sorted_words = sorted(words, key=lambda s: str : len(s));
    print(sorted_words);
}
# Lambda Expressions

with entry {
    # Lambda with parameters and return hint
    add = lambda a: int, b: int -> int : a + b;
    print(add(5, 3));

    # Lambda without parameters
    get_value = lambda : 42;
    print(get_value());

    # Lambda without return hint
    multiply = lambda x: int, y: int : x * y;
    print(multiply(4, 5));

    # Lambda with only return hint
    get_default = lambda -> int : 100;
    print(get_default());

    # Lambda with default parameters
    power = lambda x: int = 2, y: int = 3 : x ** y;
    print(power());
    print(power(5));
    print(power(5, 2));

    # Lambda as argument to function
    numbers = [1, 2, 3, 4, 5];
    squared = list(map(lambda x: int : x ** 2, numbers));
    print(squared);

    # Lambda in filter
    evens = list(filter(lambda x: int : x % 2 == 0, numbers));
    print(evens);

    # Lambda with conditional expression
    max_val = lambda a: int, b: int : a if a > b else b;
    print(max_val(10, 20));
    print(max_val(30, 15));

    # Lambda returning lambda
    make_adder = lambda x: int : (lambda y: int : x + y);
    add_five = make_adder(5);
    print(add_five(10));

    # Lambda in sort key
    words = ["apple", "pie", "a", "cherry"];
    sorted_words = sorted(words, key=lambda s: str : len(s));
    print(sorted_words);
}
from __future__ import annotations
add = lambda a, b: a + b
print(add(5, 3))
get_value = lambda: 42
print(get_value())
multiply = lambda x, y: x * y
print(multiply(4, 5))
get_default = lambda: 100
print(get_default())
power = lambda x=2, y=3: x ** y
print(power())
print(power(5))
print(power(5, 2))
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)
max_val = lambda a, b: a if a > b else b
print(max_val(10, 20))
print(max_val(30, 15))
make_adder = lambda x: lambda y: x + y
add_five = make_adder(5)
print(add_five(10))
words = ['apple', 'pie', 'a', 'cherry']
sorted_words = sorted(words, key=lambda s: len(s))
print(sorted_words)
Jac Grammar Snippet
lambda_expr: KW_LAMBDA func_decl_params (RETURN_HINT expression)? ( COLON expression | code_block )
           | KW_LAMBDA func_decl? ( COLON expression | code_block )

Description

Lambda expressions in Jac create anonymous functions with a concise syntax, suitable for short function definitions used inline or passed as arguments.

What are Lambda Expressions?

Lambda expressions are a way to create small, unnamed functions without using the full def syntax. They are ideal for simple operations that are used once, such as transforming data in a map or filter operation.

Basic Lambda Syntax

The general structure of a lambda expression follows this pattern:

Component Description Required
lambda keyword Marks the start of a lambda expression Yes
Parameters Input parameters with optional type hints No
-> return type Type hint for the return value No
: separator Separates signature from body Yes
Expression Single expression to evaluate and return Yes

Lambda with Full Type Annotations

Line 5 shows a lambda with complete type annotations. The expression lambda a: int, b: int -> int : a + b defines a function that takes two integer parameters and returns their sum. This is equivalent to:

The lambda version is more concise and can be assigned to a variable (line 5) or passed directly as an argument.

Lambda Without Parameters

Lines 9-10 demonstrate the simplest form of lambda: one that takes no parameters and just returns a constant value. The syntax lambda : 42 creates a function that always returns 42 when called.

Lambda Without Return Type Hints

Lines 13-14 show that type hints are optional. A lambda can be written as lambda x: int, y: int : x * y without specifying the return type. Jac will infer the return type from the expression.

Lambda with Only Return Type

Lines 17-18 demonstrate specifying just the return type without parameters: lambda -> int : 100. This enables documentation of the lambda's return value even when it takes no inputs.

Default Parameter Values

Lines 21-24 show how lambdas can have default parameter values, just like regular functions:

Call Values Used Result
power() (line 22) x=2, y=3 (defaults) 8
power(5) (line 23) x=5, y=3 (y default) 125
power(5, 2) (line 24) x=5, y=2 25

Lambdas as Function Arguments

One of the most common uses for lambdas is passing them as arguments to higher-order functions.

Lines 27-29 demonstrate using a lambda with the map function to square each number in a list. The lambda lambda x: int : x ** 2 is applied to each element.

Lines 32-33 show using a lambda with filter to select only even numbers. The lambda lambda x: int : x % 2 == 0 returns true for even numbers.

Lambdas with Conditional Expressions

Lines 36-38 demonstrate that the expression body of a lambda can be a conditional (ternary) expression. The lambda lambda a: int, b: int : a if a > b else b returns the maximum of two values.

Lambda Returning Lambda

Lines 41-43 show a more advanced pattern: a lambda that returns another lambda. This creates closures where the inner lambda captures variables from the outer lambda. Line 41 creates a function that returns an "adder" function, and line 42 creates a specific adder that adds 5 to its input.

graph LR
    A[make_adder(5)] --> B[Returns: lambda y: 5 + y]
    B --> C[add_five(10)]
    C --> D[Returns: 15]

Lambda as Sort Key

Lines 46-48 demonstrate using a lambda as a key function for sorting. The sorted function uses the lambda lambda s: str : len(s) to determine the sort order, sorting strings by their length rather than alphabetically.

Lambda Limitations

Important things to know about lambdas in Jac:

Feature Supported in Lambda?
Single expression Yes
Multiple statements No
Assignments No (except walrus :=)
Type annotations Yes
Default parameters Yes
Variadic arguments (*args, **kwargs) No
Control flow statements (if/for/while as statements) No
Conditional expressions (ternary) Yes

For complex logic requiring multiple statements or control flow, use regular def functions instead.

When to Use Lambdas

Lambdas are appropriate for: - Simple, one-line operations - Inline function definitions for map, filter, sorted, etc. - Callback functions that are used only once - Closures with simple logic

Regular functions are appropriate for: - Multiple statements or complex logic - Better documentation with docstrings - Reusable code that appears in multiple places - Variadic arguments or complex parameter handling