Skip to content

Commit e478e7f

Browse files
committed
docs more consistent
1 parent e912e46 commit e478e7f

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

docs/src/rule_author/superpowers/mutation_support.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Mutation Support
22

3-
ChainRulesCore.jl offers experimental support for mutation, targetting use in forward mode AD.
3+
ChainRulesCore.jl offers experimental support for mutation, targeting use in forward mode AD.
44
(Mutation support in reverse mode AD is more complicated and will likely require more changes to the interface)
55

66
!!! warning "Experimental"
@@ -17,18 +17,23 @@ It is required to be a structural tangent, having one tangent for each field of
1717
Technically, not all `mutable struct`s need to use `MutableTangent` to represent their tangents.
1818
Just like not all `struct`s need to use `Tangent`s.
1919
Common examples away from this are natural tangent types like for arrays.
20-
However, if one is setting up to use a custom tangent type for this it is surficiently off the beated path that we can not provide much guidance.
20+
However, if one is setting up to use a custom tangent type for this it is sufficiently off the beaten path that we can not provide much guidance.
2121

2222
## `zero_tangent`
2323

2424
The [`zero_tangent`](@ref) function functions to give you a zero (i.e. additive identity) for any primal value.
2525
The [`ZeroTangent`](@ref) type also does this.
26-
The difference is that [`zero_tangent`](@ref) is (where possible) a full structural tangent mirroring the structure of the primal.
26+
The difference is that [`zero_tangent`](@ref) is in general full structural tangent mirroring the structure of the primal.
27+
To be technical the promise of [`zero_tangent`](@ref) is that it will be a value that supports mutation.
28+
However, in practice[^1] this is achieved through in a structural tangent
2729
For mutation support this is important, since it means that there is mutable memory available in the tangent to be mutated when the primal changes.
2830
To support this you thus need to make sure your zeros are created in various places with [`zero_tangent`](@ref) rather than []`ZeroTangent`](@ref).
2931

30-
It is also useful for reasons of type stability, since it is always a structural tangent.
31-
For this reason AD system implementors might chose to use this to create the tangent for all literal values they encounter, mutable or not.
32+
33+
34+
It is also useful for reasons of type stability, since it forces a consistent type (generally a structural tangent) for any given primal type.
35+
For this reason AD system implementors might chose to use this to create the tangent for all literal values they encounter, mutable or not,
36+
and to process the output of `frule`s to convert [`ZeroTangent`](@ref) into corresponding [`zero_tangent`](@ref)s.
3237

3338
## Writing a frule for a mutating function
3439
It is relatively straight forward to write a frule for a mutating function.
@@ -41,7 +46,7 @@ There are a few key points to follow:
4146
### Example
4247
For example, consider the primal function with:
4348
1. takes two `Ref`s
44-
2. doubles the first one inplace
49+
2. doubles the first one in place
4550
3. overwrites the second one's value with the literal 5.0
4651
4. returns the first one
4752

@@ -70,4 +75,8 @@ function ChainRulesCore.frule((ȧ, ḃ), ::typeof(foo!), a::Base.RefValue, b::B
7075
end
7176
```
7277

73-
Then assuming the AD system does its part to makes sure you are indeed given mutable values to mutate (i.e. those `@assert`ions are true) then all is well and this rule will make mutation correct.
78+
Then assuming the AD system does its part to makes sure you are indeed given mutable values to mutate (i.e. those `@assert`ions are true) then all is well and this rule will make mutation correct.
79+
80+
[^1]:
81+
Further, it is hard to achieve this promise of allowing mutation to be supported without returning a structural tangent.
82+
Except in the special case of where the struct is not mutable and has no nested fields that are mutable.

src/tangent_types/abstract_zero.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ For mutable composites types this is a structural [`MutableTangent`](@ref)
100100
For `Array`s, it is applied recursively for each element.
101101
For other types, in particular immutable types, we do not make promises beyond that it will be `iszero`
102102
and suitable for accumulating against.
103-
In general though, it is more likely to produce a structural tangent.
103+
For types without a tangent space (e.g. singleton structs) this returns `NoTangent()`.
104+
In general, it is more likely to produce a structural tangent.
104105
105106
!!! warning Exprimental
106107
`zero_tangent`is an experimental feature, and is part of the mutation support featureset.

0 commit comments

Comments
 (0)