# apfel.container.once

*module*

Primitives for containers that can be written only once. Inspired by [:rust `OnceCell`](https://doc.rust-lang.org/std/cell/struct.OnceCell.html) and [:rust `LazyCell`](https://doc.rust-lang.org/std/cell/struct.LazyCell.html).

The [`Once`][apfel.container.once.Once] and [`Lazy`][apfel.container.once.Lazy] classes, are exposed in the [package namespace](../prelude.md#package-namespace).

## Implementation

[`Once`][apfel.container.once.Once] takes reference from [:rust `OnceCell`](https://doc.rust-lang.org/std/cell/struct.OnceCell.html) and the current status is as follows:

| Reference [:rust `OnceCell`](https://doc.rust-lang.org/std/cell/struct.OnceCell.html) | Counterpart |
| --- | --- |
| `get` | [`get`][apfel.container.once.Once.get] |
| `get_mut` | / |
| `get_mut_or_init` | / |
| `get_mut_or_try_init` | / |
| `get_or_init` | [`get_or_init`][apfel.container.once.Once.get_or_init] |
| `get_or_try_init` | - |
| `into_inner` | - |
| `new` | - |
| `set` | [`set`][apfel.container.once.Once.set] |
| `take` | - |
| `try_insert` | - |

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L1-L1)

## apfel.container.once.Lazy

*class*

```python
class Lazy
```

A container that can be lazily initialized only once.
The stored function will be actually called only on the first retrieval, and the result will be cached for consequent calls.
See [:rust `LazyCell`](https://doc.rust-lang.org/std/cell/struct.LazyCell.html) for more information.

This class is exposed in the [package namespace](../prelude.md#package-namespace).

```python
from apfel.container.once import Lazy

@Lazy
def func():
    print("called")
    return object()

obj = func.value()
# print "called"
# here, the function `func` will be called and the result will be cached.

func.value() is obj # the function `func` will not be called again.
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L237-L330)

### apfel.container.once.Lazy.__slots__

*attribute* · *class attribute* · *instance attribute*

```python
__slots__ = ('_value', '_has_value', '_init')
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L261-L261)

### apfel.container.once.Lazy.__bool__

*method*

```python
def __bool__() -> bool
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L277-L278)

### apfel.container.once.Lazy.__call__

*method*

```python
def __call__() -> T
```

An alias for [`Lazy.value`][apfel.container.once.Lazy.value].
Notice that this operator overloading might be slower than calling `value` directly.

```python
@Lazy
def func():
    return object()

obj = func()
assert func() is obj
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L280-L299)

### apfel.container.once.Lazy.__class_getitem__

*method*

```python
def __class_getitem__(item: U) -> Lazy[U]
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L274-L275)

### apfel.container.once.Lazy.__init__

*method*

```python
def __init__(func: Callable[[], T], /) -> None
```

Create a lazily initialized `Lazy` container.

**Parameters**

- `func` (`Callable[[], T]`) — The function to be lazily initialized.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L263-L272)

### apfel.container.once.Lazy.unwrap

*method*

```python
def unwrap() -> T
```

Get the inner value of the `Lazy` container.
If no value has been set, this method raises a `ValueError`.

**Returns**

- `T` (`T`) — The lazily initialized value of the `Lazy` container.

**Raises**

- `ValueError` — If no value has been set.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L301-L315)

### apfel.container.once.Lazy.value

*method*

```python
def value() -> T
```

Get the inner value of the `Lazy` container.
If no value has been set, this method initializes the value with the stored function.

**Returns**

- `T` (`T`) — The lazily initialized value of the `Lazy` container.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L317-L330)

## apfel.container.once.LazyLock

*class*

```python
class LazyLock
```

A thread-safe version of [`Lazy`][apfel.container.once.Lazy].
See [:rust `LazyCell`](https://doc.rust-lang.org/std/cell/struct.LazyCell.html) for more information.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L333-L413)

### apfel.container.once.LazyLock.__slots__

*attribute* · *class attribute* · *instance attribute*

```python
__slots__ = ('_value', '_has_value', '_init', '_lock')
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L339-L339)

### apfel.container.once.LazyLock.__bool__

*method*

```python
def __bool__() -> bool
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L358-L360)

### apfel.container.once.LazyLock.__call__

*method*

```python
def __call__() -> T
```

An alias for [`LazyLock.value`][apfel.container.once.LazyLock.value].
Notice that this operator overloading might be slower than calling `value` directly.

```python
from apfel.container.once import LazyLock

lazy_lock = LazyLock(lambda: object())
obj = lazy_lock()
assert lazy_lock() is obj
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L362-L381)

### apfel.container.once.LazyLock.__class_getitem__

*method*

```python
def __class_getitem__(item: U) -> LazyLock[U]
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L355-L356)

### apfel.container.once.LazyLock.__init__

*method*

```python
def __init__(func: Callable[[], T], /) -> None
```

Create a thread-safe lazily initialized `LazyLock` container.

**Parameters**

- `func` (`Callable[[], T]`) — The function to be lazily initialized.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L341-L353)

### apfel.container.once.LazyLock.unwrap

*method*

```python
def unwrap() -> T
```

Get the inner value of the `LazyLock` container.
If no value has been set, this method raises a `ValueError`.

**Returns**

- `T` (`T`) — The inner value of the `LazyLock` container.

**Raises**

- `ValueError` — If no value has been set.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L383-L397)

### apfel.container.once.LazyLock.value

*method*

```python
def value() -> T
```

Get the inner value of the `LazyLock` container.
If no value has been set, this method initializes the value with the stored function.

**Returns**

- `T` (`T`) — The lazily initialized value of the `LazyLock` container.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L399-L413)

## apfel.container.once.Once

*class*

```python
class Once
```

A container that can be written only once.
See [:rust `OnceCell`](https://doc.rust-lang.org/std/cell/struct.OnceCell.html) for more information.

This class is exposed in the [package namespace](../prelude.md#package-namespace).

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L29-L134)

### apfel.container.once.Once.__slots__

*attribute* · *class attribute* · *instance attribute*

```python
__slots__ = ('_value', '_has_value')
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L37-L37)

### apfel.container.once.Once.__bool__

*method*

```python
def __bool__() -> bool
```

Check if the `Once` container has been set.

**Returns**

- `bool` (`bool`) — `True` if the `Once` container has been set, `False` otherwise.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L65-L72)

### apfel.container.once.Once.__class_getitem__

*method*

```python
def __class_getitem__(item: U) -> Once[U]
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L49-L50)

### apfel.container.once.Once.__init__

*method*

```python
def __init__()
```

Create an unpopulated `Once` container.

**Returns**

- `Once` — An unpopulated `Once` container.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L39-L47)

### apfel.container.once.Once.get

*method*

```python
def get() -> _maybe.Maybe[T]
```

Get the inner value of the `Once` container if it has been set.

**Returns**

- (`_maybe.Maybe[T]`) — Maybe[T]: A `Just`-wrapped inner value of the `Once` container if it has been set, a `Nothing` otherwise.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L74-L83)

### apfel.container.once.Once.get_or_init

*method*

```python
def get_or_init(func: Callable[[], T], /) -> T
```

Get the inner value of the `Once` container, or initialize it with the given function if no value has been set.

**Parameters**

- `func` (`Callable[[], T]`) — The function to initialize the `Once` container with if no value has been set.

**Returns**

- `T` (`T`) — The inner value (maybe newly set) of the `Once` container.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L85-L99)

### apfel.container.once.Once.of_hint

*method* · *classmethod*

```python
def of_hint(type: type[U], /) -> Once[U]
```

Create a `Once` container hinting the given type.

**Parameters**

- `type` (`Type[T]`) — The type of the value to be stored in the `Once` container.

**Returns**

- (`Once[U]`) — Once[T]: A `Once` container hinting the given type.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L52-L63)

### apfel.container.once.Once.set

*method*

```python
def set(value: T) -> _result.Result[None, T]
```

Set the inner value of the `Once` container.
If a value has already been set, this method returns an `Err` containing the existing value.

**Parameters**

- `value` (`T`) — The value to set the `Once` container to.

**Returns**

- (`_result.Result[None, T]`) — Result[None, T]: `Ok(None)` if the value was set successfully. `Err(value)` if the value has already been set, containing the existing value.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L101-L118)

### apfel.container.once.Once.unwrap

*method*

```python
def unwrap() -> T
```

Get the inner value of the `Once` container.
If no value has been set, this method raises a `ValueError`.

**Returns**

- `T` (`T`) — The inner value of the `Once` container.

**Raises**

- `ValueError` — If no value has been set.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L120-L134)

## apfel.container.once.OnceLock

*class*

```python
class OnceLock
```

A thread-safe version of [`Once`][apfel.container.once.Once].
See [:rust `OnceLock`](https://doc.rust-lang.org/std/sync/struct.OnceLock.html) for more information.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L137-L234)

### apfel.container.once.OnceLock.__slots__

*attribute* · *class attribute* · *instance attribute*

```python
__slots__ = ('_value', '_has_value', '_lock')
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L143-L143)

### apfel.container.once.OnceLock.__bool__

*method*

```python
def __bool__() -> bool
```

Check if the `OnceLock` container has been set.

**Returns**

- `bool` (`bool`) — `True` if the `OnceLock` container has been set, `False` otherwise.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L161-L169)

### apfel.container.once.OnceLock.__class_getitem__

*method*

```python
def __class_getitem__(item: U) -> OnceLock[U]
```

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L158-L159)

### apfel.container.once.OnceLock.__init__

*method*

```python
def __init__() -> None
```

Create an unpopulated `OnceLock` container.

**Returns**

- `OnceLock` (`None`) — An unpopulated `OnceLock` container.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L145-L156)

### apfel.container.once.OnceLock.get

*method*

```python
def get() -> _maybe.Maybe[T]
```

Get the inner value of the `OnceLock` container if it has been set.

**Returns**

- (`_maybe.Maybe[T]`) — Maybe[T]: A `Just`-wrapped inner value of the `OnceLock` container if it has been set, a `Nothing` otherwise.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L171-L181)

### apfel.container.once.OnceLock.get_or_init

*method*

```python
def get_or_init(func: Callable[[], T], /) -> T
```

Get the inner value of the `OnceLock` container, or initialize it with the given function if no value has been set.

**Parameters**

- `func` (`Callable[[], T]`) — The function to initialize the `OnceLock` container with if no value has been set.

**Returns**

- `T` (`T`) — The inner value (maybe newly set) of the `OnceLock`

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L183-L198)

### apfel.container.once.OnceLock.set

*method*

```python
def set(value: T) -> _result.Result[None, T]
```

Set the inner value of the `OnceLock` container.
If a value has already been set, this method returns an `Err` containing the existing value.

**Parameters**

- `value` (`T`) — The value to set the `OnceLock` container to.

**Returns**

- (`_result.Result[None, T]`) — Result[None, T]: `Ok(None)` if the value was set successfully. `Err(value)` if the value has already been set, containing the existing value.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L200-L218)

### apfel.container.once.OnceLock.unwrap

*method*

```python
def unwrap() -> T
```

Get the inner value of the `OnceLock` container.
If no value has been set, this method raises a `ValueError`.

**Returns**

- `T` (`T`) — The inner value of the `OnceLock` container.

**Raises**

- `ValueError` — If no value has been set.

[View source](https://github.com/Yixuan-Wang/apfel/blob/main/src/apfel/container/once.py#L220-L234)
