@@ -52,6 +52,8 @@ There are three central features of a `TapedTask`, which we demonstrate via thre
5252
5353## Resumption
5454
55+ The function [`Libtask.produce`](@ref) has a special meaning in Libtask. You can insert it
56+ into regular Julia functions anywhere that you like. For example
5557```jldoctest tt
5658julia> function f()
5759 for t in 1:2
@@ -63,60 +65,96 @@ julia> function f()
6365f (generic function with 1 method)
6466```
6567
68+ If you construct a `TapedTask` from `f`, and call [`Libtask.consume`](@ref) on it, you'll
69+ see
6670```jldoctest tt
6771julia> t = TapedTask(nothing, f);
6872
6973julia> consume(t)
70741
7175```
76+ The semantics of this are that [`Libtask.consume`](@ref) runs the function `f` until it
77+ reaches the call to [`Libtask.produce`](@ref), at which point it will return the argument
78+ to [`Libtask.produce`](@ref).
7279
80+ Subsequent calls to [`Libtask.produce`](@ref) will _resume_ execution of `f` immediately
81+ after the last [`Libtask.produce`](@ref) statement that was hit.
7382```jldoctest tt
7483julia> consume(t)
75842
85+ ```
7686
87+ When there are no more [`Libtask.produce`](@ref) statements to hit, calling
88+ [`Libtask.consume`](@ref) will return `nothing`:
89+ ```jldoctest tt
7790julia> consume(t)
7891
7992```
8093
8194## Copying
8295
96+ [`TapedTask`](@ref)s can be copied. Doing so creates a completely independent object.
97+ For example:
8398```jldoctest tt
8499julia> t2 = TapedTask(nothing, f);
85100
86101julia> consume(t2)
871021
88103```
89104
105+ If we make a copy and advance its state, it produces the same value that the original would
106+ have produced:
90107```jldoctest tt
91108julia> t3 = copy(t2);
92109
93110julia> consume(t3)
941112
112+ ```
95113
114+ Moreover, advancing the state of the copy has not advanced the state of the original,
115+ because they are completely independent copies:
116+ ```jldoctest tt
96117julia> consume(t2)
971182
98119```
99120
100121## Scoped Values
101122
102- ```jldoctest
123+ It is often desirable to permit a copy of a task and the original to differ in very specific
124+ ways. For example, in the context of Sequential Monte Carlo, you might want the only
125+ difference between two copies to be their random number generator.
126+
127+ A generic mechanism is available to achieve this. [`Libtask.get_dynamic_scope`](@ref) and
128+ [`Libtask.set_dynamic_scope!`](@ref) let you set and retrieve a variable which is specific
129+ to a given [`Libtask.TapedTask`](@ref). The former can be called inside a function:
130+ ```jldoctest sv
103131julia> function f()
104132 produce(get_dynamic_scope())
105133 produce(get_dynamic_scope())
106134 return nothing
107135 end
108136f (generic function with 1 method)
137+ ```
109138
139+ The first argument to [`Libtask.TapedTask`](@ref) is the value that
140+ [`Libtask.get_dynamic_scope`](@ref) will return:
141+ ```jldoctest sv
110142julia> t = TapedTask(1, f);
111143
112144julia> consume(t)
1131451
146+ ```
114147
148+ The value that it returns can be changed between [`Libtask.consume`](@ref) calls:
149+ ```jldoctest sv
115150julia> set_dynamic_scope!(t, 2)
116151
117152julia> consume(t)
1181532
119154```
155+
156+ `Int`s have been used here, but it is permissible to set the value returned by
157+ [`Libtask.get_dynamic_scope`](@ref) to anything you like.
120158"""
121159function TapedTask (dynamic_scope:: Any , fargs... )
122160 mc, count_ref = build_callable (Base. code_ircode_by_type (typeof (fargs))[1 ][1 ])
0 commit comments