---
title: "SnapshotMutationPolicy"
description: "A policy to control how the result of [mutableStateOf] report and merge changes to the state
object.

A mutation policy can be passed as an parameter to [mutableStateOf], and [compositionLocalOf].

Typically, one of the stock policies should be used such as [referentialEqualityPolicy],
[structuralEqualityPolicy], or [neverEqualPolicy]. However, a custom mutation policy can be
created by implementing this interface, such as a counter policy,"
type: "interface"
---

<div class='type'>Interface</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>



```kotlin
@JvmDefaultWithCompatibility
public interface SnapshotMutationPolicy<T>
```


A policy to control how the result of `mutableStateOf` report and merge changes to the state
object.

A mutation policy can be passed as an parameter to `mutableStateOf`, and `compositionLocalOf`.

Typically, one of the stock policies should be used such as `referentialEqualityPolicy`,
`structuralEqualityPolicy`, or `neverEqualPolicy`. However, a custom mutation policy can be
created by implementing this interface, such as a counter policy,


## Functions

```kotlin
public fun equivalent(a: T, b: T): Boolean
```


Determine if setting a state value's are equivalent and should be treated as equal. If
`equivalent` returns `true` the new value is not considered a change.


```kotlin
public fun merge(previous: T, current: T, applied: T): T?
```


Merge conflicting changes in snapshots. This is only called if `current` and `applied` are
not `equivalent`. If a valid merged value can be calculated then it should be returned.

For example, if the state object holds an immutable data class with multiple fields, and
`applied` has changed fields that are unmodified by `current` it might be valid to return a
new copy of the data class that combines that changes from both `current` and `applied`
allowing a snapshot to apply that would have otherwise failed.



## Code Examples

### counterSample
```kotlin
fun counterSample() {
    /**
     * A policy that treats an `MutableState<Int>` as a counter. Changing the value to the same
     * integer value will not be considered a change. When snapshots are applied the changes made by
     * the applying snapshot are added together with changes of other snapshots. Changes to a
     * [MutableState] with a counterPolicy will never cause an apply conflict.
     *
     * As the name implies, this is useful when counting things, such as tracking the amount of a
     * resource consumed or produced while in a snapshot. For example, if snapshot A produces 10
     * things and snapshot B produces 20 things, the result of applying both A and B should be that
     * 30 things were produced.
     */
    fun counterPolicy(): SnapshotMutationPolicy<Int> =
        object : SnapshotMutationPolicy<Int> {
            override fun equivalent(a: Int, b: Int): Boolean = a == b
            override fun merge(previous: Int, current: Int, applied: Int) =
                current + (applied - previous)
        }
    val state = mutableStateOf(0, counterPolicy())
    val snapshot1 = Snapshot.takeMutableSnapshot()
    val snapshot2 = Snapshot.takeMutableSnapshot()
    try {
        snapshot1.enter { state.value += 10 }
        snapshot2.enter { state.value += 20 }
        snapshot1.apply().check()
        snapshot2.apply().check()
    } finally {
        snapshot1.dispose()
        snapshot2.dispose()
    }
    // State is now equals 30 as the changes made in the snapshots are added together.
}
```

