Skip to content

Unpack expressions#

Code Example

Runnable Example in Jac and JacLib

"""Unpack expressions: Unpacking with * (iterable) and ** (mapping)."""

def compute(a: int, b: int, c: int, d: int) -> int {
    return a + b + c + d;
}

with entry {
    # List unpacking with *
    list1 = [1, 2, 3];
    list2 = [4, 5, 6];
    combined = [*list1, *list2];

    # Dictionary unpacking with **
    dict1 = {'a': 1, 'b': 2};
    dict2 = {'c': 3, 'd': 4};
    merged = {**dict1, **dict2};

    # Unpacking in function calls
    result1 = compute(**merged);
    result2 = compute(**dict1, **dict2);

    print(combined, merged, result1, result2);
}
"""Unpack expressions: Unpacking with * (iterable) and ** (mapping)."""

def compute(a: int, b: int, c: int, d: int) -> int {
    return a + b + c + d;
}

with entry {
    # List unpacking with *
    list1 = [1, 2, 3];
    list2 = [4, 5, 6];
    combined = [*list1, *list2];

    # Dictionary unpacking with **
    dict1 = {'a': 1, 'b': 2};
    dict2 = {'c': 3, 'd': 4};
    merged = {**dict1, **dict2};

    # Unpacking in function calls
    result1 = compute(**merged);
    result2 = compute(**dict1, **dict2);

    print(combined, merged, result1, result2);
}
"""Unpack expressions: Unpacking with * (iterable) and ** (mapping)."""
from __future__ import annotations
from jaclang.runtimelib.builtin import *

def compute(a: int, b: int, c: int, d: int) -> int:
    return a + b + c + d
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = [*list1, *list2]
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
merged = {**dict1, **dict2}
result1 = compute(**merged)
result2 = compute(**dict1, **dict2)
print(combined, merged, result1, result2)
Jac Grammar Snippet
unpack: STAR_MUL? ref

Description

Unpack Expressions

Unpack expressions use the * and ** operators to expand collections inline, enabling concise collection composition and flexible function calls.

Function Definition

Lines 3-5 define a function that takes four integer parameters (a, b, c, d) and returns their sum. This function will be used to demonstrate unpacking in function calls.

List Unpacking with Asterisk

Lines 9-11 demonstrate list unpacking using *. Line 11 shows [*list1, *list2], which unpacks both lists into a new list: - *list1 expands to elements: 1, 2, 3 - *list2 expands to elements: 4, 5, 6 - Combined result: [1, 2, 3, 4, 5, 6]

This provides a clean way to concatenate lists without using the + operator or extend() method.

Dictionary Unpacking with Double Asterisk

Lines 14-16 demonstrate dictionary unpacking using **. Line 16 shows {**dict1, **dict2}, which unpacks both dictionaries into a new dictionary: - **dict1 expands to key-value pairs: 'a': 1, 'b': 2 - **dict2 expands to key-value pairs: 'c': 3, 'd': 4 - Merged result: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

If both dictionaries had the same key, the rightmost dictionary's value would take precedence.

Unpacking in Function Calls

Lines 19-20 demonstrate unpacking dictionaries as keyword arguments. Line 19: result1 = compute(**merged); - merged is {'a': 1, 'b': 2, 'c': 3, 'd': 4} - **merged unpacks to keyword arguments: a=1, b=2, c=3, d=4 - Calls: compute(a=1, b=2, c=3, d=4) - Returns: 1 + 2 + 3 + 4 = 10

Line 20: result2 = compute(**dict1, **dict2); - **dict1 provides: a=1, b=2 - **dict2 provides: c=3, d=4 - Same result: 10

This allows you to pass collected arguments to functions without explicitly naming each parameter.

Unpacking Operators

Operator Works With Use Case Example
* Sequences (lists, tuples) Expand elements [*list1, *list2]
** Mappings (dictionaries) Expand key-value pairs {**dict1, **dict2}

Multiple Unpacking

You can unpack multiple collections in a single expression: - Lists: [*a, *b, *c] combines three lists - Dicts: {**x, **y, **z} merges three dictionaries - Function calls: func(**d1, **d2) passes arguments from two dicts

Literal Collection Building

Unpacking is powerful for building collections with mixed content:

Common Use Cases

Use Case Example Benefit
Concatenate lists [*list1, *list2] Cleaner than list1 + list2
Merge configs {**defaults, **overrides} Override precedence
Pass collected args func(**kwargs) Flexible function calls
Copy with modifications {**original, 'key': new_val} Update while copying

Example Execution

Line 22 prints all results from lines 11, 16, 19, and 20: - combined = [1, 2, 3, 4, 5, 6] - merged = {'a': 1, 'b': 2, 'c': 3, 'd': 4} - result1 = 10 - result2 = 10

Shallow Copy Semantics

When unpacking creates a new collection, it performs a shallow copy: - New outer collection is created - Elements/values themselves are not copied (references are copied) - Modifying nested objects affects both collections

Practical Examples

Combining configuration:

Building lists with interspersed values:

Passing function arguments:

These unpacking operators make collection manipulation more concise and expressive in Jac.