Hashing

All values in a dependency graph must provide a hash (a unique identifier) for their state, or indicate they can't be hashed. This is used to determine if whether a value has changed since the last time it was observed.

There are three ways to define a value's hashing behaviour:

1. Default: Requires the type to implement the Hash trait.

// This type implements `Hash`, therefore it can use the default behaviour.
#[derive(Value, Hash)]
struct DefaultBehaviour {
    data: i32,
}

2. Custom Hash: Annotate a field with the #[depends(hash)] attribute to manually manage the hashing behaviour.

// This node manually manages its hash value.
#[derive(Value)]
struct CustomHashStruct {
    // You could increment a counter here, for example.
    #[depends(hash)]
    hash_value: usize,
    // ... other fields go here.
}

3. Unhashable: Mark values that can't be hashed with the #[depends(unhashable)] attribute. This type will always appear dirty to any dependents, causing them to always recalculate their own state.

// This node will _always_ be considered dirty to its dependents.
#[derive(Value)]
#[depends(unhashable)]
struct UnhashableStruct {
    // ... your fields go here.
}

It's unlikely you'll need to use the unhashable attribute and this can greatly reduce the efficiency of computations. Most nodes can use a custom hash field instead.