|
1 | | -import Base: convert |
2 | | - |
3 | | -Base.@deprecate_binding NO_FIELDS NoTangent() |
4 | | - |
5 | | -const EXTERN_DEPRECATION = "`extern` is deprecated, use `unthunk` or `backing` instead, " * |
6 | | - "depending on the use case." |
7 | | - |
8 | | -""" |
9 | | - extern(x) |
10 | | -
|
11 | | -Makes a best effort attempt to convert a differential into a primal value. |
12 | | -This is not always a well-defined operation. |
13 | | -For two reasons: |
14 | | - - It may not be possible to determine the primal type for a given differential. |
15 | | - For example, `Zero` is a valid differential for any primal. |
16 | | - - The primal type might not be a vector space, thus might not be a valid differential type. |
17 | | - For example, if the primal type is `DateTime`, it's not a valid differential type as two |
18 | | - `DateTime` can not be added (fun fact: `Milisecond` is a differential for `DateTime`). |
19 | | -
|
20 | | -Where it is defined the operation of `extern` for a primal type `P` should be |
21 | | -`extern(x) = zero(P) + x`. |
22 | | -
|
23 | | -!!! note |
24 | | - Because of its limitations, `extern` should only really be used for testing. |
25 | | - It can be useful, if you know what you are getting out, as it recursively removes |
26 | | - thunks, and otherwise makes outputs more consistent with finite differencing. |
27 | | -
|
28 | | - The more useful action in general is to call `+`, or in the case of a [`Thunk`](@ref) |
29 | | - to call [`unthunk`](@ref). |
30 | | -
|
31 | | -!!! warning |
32 | | - `extern` may return an alias (not necessarily a copy) to data |
33 | | - wrapped by `x`, such that mutating `extern(x)` might mutate `x` itself. |
34 | | -""" |
35 | | -@inline function extern(x) |
36 | | - Base.depwarn(EXTERN_DEPRECATION, :extern) |
37 | | - return x |
38 | | -end |
39 | | - |
40 | | -extern(x::ZeroTangent) = (Base.depwarn(EXTERN_DEPRECATION, :extern); return false) # false is a strong 0. E.g. `false * NaN = 0.0` |
41 | | - |
42 | | -function extern(x::NoTangent) |
43 | | - Base.depwarn(EXTERN_DEPRECATION, :extern) |
44 | | - throw(ArgumentError("Derivative does not exit. Cannot be converted to an external type.")) |
45 | | -end |
46 | | - |
47 | | -extern(comp::Tangent) = (Base.depwarn(EXTERN_DEPRECATION, :extern); return backing(map(extern, comp))) # gives a NamedTuple or Tuple |
48 | | - |
49 | | -extern(x::NotImplemented) = (Base.depwarn(EXTERN_DEPRECATION, :extern); throw(NotImplementedException(x))) |
50 | | - |
51 | | -@inline extern(x::AbstractThunk) = (Base.depwarn(EXTERN_DEPRECATION, :extern); return extern(unthunk(x))) |
52 | | - |
53 | | -for T in (:Thunk, :InplaceableThunk) |
54 | | - @eval function (x::$T)() |
55 | | - Base.depwarn("`(x::" * string($T) * ")()` is deprecated, use `unthunk(x)`", Symbol(:call_, $(T))) |
56 | | - return unthunk(x) |
57 | | - end |
58 | | -end |
59 | | - |
60 | | - |
61 | | -Base.@deprecate InplaceableThunk(t::Thunk, add!) InplaceableThunk(add!, t) |
62 | | - |
63 | | -Base.@deprecate convert(::Type{<:Tuple}, t::Tangent{<:Any, <:Tuple}) backing(t) |
64 | | -Base.@deprecate convert(::Type{<:NamedTuple}, t::Tangent{<:Any, <:NamedTuple}) backing(t) |
65 | | -Base.@deprecate convert(::Type{<:Dict}, t::Tangent{<:Dict, <:Dict}) backing(t) |
0 commit comments