from collections.abc import Mapping
from copy import deepcopy
from typing import TypeVar
from .curry import curry
T = TypeVar("T")
R = TypeVar("R")
[docs]
@curry
def assoc(k: T, v: R, obj: Mapping[T, R] | object) -> object:
"""
Associates a value with a key in an object.
Args:
k (Hashable): The key to associate the value with.
v (Any): The value to associate with the key.
obj (dict | object): The object to associate the value with the key.
Returns:
object: A new object (dict or copy) with the key-value pair added/updated.
Example:
>>> assoc("name", "Alice", {"age": 30})
{'age': 30, 'name': 'Alice'}
>>> assoc("age", 31, {"name": "Bob", "age": 30})
{'name': 'Bob', 'age': 31}
"""
if isinstance(obj, dict):
return {**obj, k: v}
if not isinstance(k, str):
raise TypeError(f"Attribute name must be a string when modifying an object, got {type(k)}")
obj_copy = deepcopy(obj)
setattr(obj_copy, k, v)
return obj_copy